Extract common capability platform service for host and guest plugins

This commit is contained in:
sophia 2021-08-27 17:08:21 -05:00 committed by Paul Hinze
parent d75f76edf7
commit 5892c47ead
No known key found for this signature in database
GPG Key ID: B69DEDF2D55501C0
4 changed files with 140 additions and 177 deletions

View File

@ -1,6 +1,7 @@
module VagrantPlugins
module CommandServe
module Service
autoload :CapabilityPlatformService, Vagrant.source_root.join("plugins/commands/serve/service/capability_platform_service").to_s
autoload :CommandService, Vagrant.source_root.join("plugins/commands/serve/service/command_service").to_s
autoload :GuestService, Vagrant.source_root.join("plugins/commands/serve/service/guest_service").to_s
autoload :HostService, Vagrant.source_root.join("plugins/commands/serve/service/host_service").to_s

View File

@ -0,0 +1,110 @@
require "google/protobuf/well_known_types"
module VagrantPlugins
module CommandServe
module Service
module CapabilityPlatformService
prepend Util::HasMapper
prepend Util::HasBroker
prepend Util::ExceptionLogger
def initialize_capability_platform!(capabilities, default_args)
@capabilities = capabilities
@default_args = default_args
end
def has_capability_spec(*_)
SDK::FuncSpec.new(
name: "has_capability_spec",
args: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Args.NamedCapability",
name: "",
)
],
result: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Platform.Capability.CheckResp",
name: "",
),
],
)
end
def has_capability(req, ctx)
ServiceInfo.with_info(ctx) do |info|
cap_name = req.args.detect { |a|
a.type == "hashicorp.vagrant.sdk.Args.NamedCapability"
}&.value&.value.strip.gsub("\b", "")
plugin_name = info.plugin_name
LOGGER.debug("checking for #{cap_name} capability in #{plugin_name}")
caps_registry = @capabilities[plugin_name.to_sym]
has_cap = caps_registry.key?(cap_name.to_sym)
SDK::Platform::Capability::CheckResp.new(
has_capability: has_cap
)
end
end
def capability_spec(req, ctx)
ServiceInfo.with_info(ctx) do |info|
cap_name = req.name.to_sym
plugin_name = info.plugin_name.to_sym
LOGGER.debug("generating capabillity spec for #{cap_name} capability in #{plugin_name}")
caps_registry = @capabilities[plugin_name]
target_cap = caps_registry.get(cap_name)
args = target_cap.method(cap_name).parameters
# The first argument is always a machine, drop it
args.shift
cap_args = default_args
# TODO: take the rest of `args` and create entries for them in
# `cap_args`
return SDK::FuncSpec.new(
name: "has_capability_spec",
args: cap_args,
result: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Platform.Capability.Resp",
name: "",
),
],
)
end
end
def capability(req, ctx)
ServiceInfo.with_info(ctx) do |info|
LOGGER.debug("executing capability, got req #{req}")
cap_name = req.name.to_sym
plugin_name = info.plugin_name.to_sym
caps_registry = @capabilities[plugin_name]
target_cap = caps_registry.get(cap_name)
# TODO: how to get this Target out of the args
# A machine should always be provided to a guest capability
raw_target = req.func_args.args.detect { |a|
a.type == "hashicorp.vagrant.sdk.Args.Target"
}&.value&.value
target = Client::Target.load(raw_target, broker: broker)
project = target.project
env = Vagrant::Environment.new({client: project})
machine = env.machine(target.name.to_sym, target.provider_name.to_sym)
cap_method = target_cap.method(cap_name)
# TODO: pass in other args too
cap_method.call(machine)
end
end
end
end
end
end

View File

@ -4,13 +4,25 @@ module VagrantPlugins
module CommandServe
module Service
class GuestService < Hashicorp::Vagrant::Sdk::GuestService::Service
include CapabilityPlatformService
prepend Util::HasMapper
prepend Util::HasBroker
prepend Util::ExceptionLogger
LOGGER = Log4r::Logger.new("vagrant::command::serve::guest")
def initialize(*args, **opts, &block)
super()
caps = Vagrant.plugin("2").manager.guest_capabilities
default_args = [
# Always get a target to pass the guest capability
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Args.Target",
name: "",
),
]
initialize_capability_platform!(caps, default_args)
super(*args, **opts, &block)
end
def detect_spec(*_)
@ -79,100 +91,6 @@ module VagrantPlugins
)
end
end
def has_capability_spec(*_)
SDK::FuncSpec.new(
name: "has_capability_spec",
args: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Args.NamedCapability",
name: "",
)
],
result: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Platform.Capability.CheckResp",
name: "",
),
],
)
end
def has_capability(req, ctx)
ServiceInfo.with_info(ctx) do |info|
cap_name = mapper.funcspec_map(req).to_sym
plugin_name = info.plugin_name
LOGGER.debug("checking for #{cap_name} capability in #{plugin_name}")
caps_registry = Vagrant.plugin("2").manager.guest_capabilities[plugin_name.to_sym]
has_cap = caps_registry.key?(cap_name.to_sym)
SDK::Platform::Capability::CheckResp.new(
has_capability: has_cap
)
end
end
def capability_spec(req, ctx)
ServiceInfo.with_info(ctx) do |info|
cap_name = req.name.to_sym
plugin_name = info.plugin_name.to_sym
LOGGER.debug("generating capabillity spec for #{cap_name} capability in #{plugin_name}")
caps_registry = Vagrant.plugin("2").manager.guest_capabilities[plugin_name]
target_cap = caps_registry.get(cap_name)
args = target_cap.method(cap_name).parameters
# The first argument is always a machine, drop it
args.shift
cap_args = [
# Always get a target to pass the guest capability
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Args.Target",
name: "",
),
]
# TODO: take the rest of `args` and create entries for them in
# `cap_args`
return SDK::FuncSpec.new(
name: "has_capability_spec",
args: cap_args,
result: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Platform.Capability.Resp",
name: "",
),
],
)
end
end
def capability(req, ctx)
ServiceInfo.with_info(ctx) do |info|
LOGGER.debug("executing capability, got req #{req}")
cap_name = req.name.to_sym
plugin_name = info.plugin_name.to_sym
caps_registry = Vagrant.plugin("2").manager.guest_capabilities[plugin_name]
target_cap = caps_registry.get(cap_name)
# A machine should always be provided to a guest capability
raw_target = req.func_args.args.detect { |a|
a.type == "hashicorp.vagrant.sdk.Args.Target"
}&.value&.value
target = Client::Target.load(raw_target, broker: broker)
project = target.project
env = Vagrant::Environment.new({client: project})
machine = env.machine(target.name.to_sym, target.provider_name.to_sym)
cap_method = target_cap.method(cap_name)
# TODO: pass in other args too
cap_method.call(machine)
end
end
end
end
end

View File

@ -4,10 +4,26 @@ module VagrantPlugins
module CommandServe
module Service
class HostService < Hashicorp::Vagrant::Sdk::HostService::Service
include CapabilityPlatformService
prepend Util::HasMapper
prepend Util::HasBroker
prepend Util::ExceptionLogger
def initialize(*args, **opts, &block)
caps = Vagrant.plugin("2").manager.host_capabilities
default_args = [
# Always get a target to pass the guest capability
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Args.Project",
name: "",
),
]
initialize_capability_platform!(caps, default_args)
super(*args, **opts, &block)
end
def detect_spec(*_)
SDK::FuncSpec.new(
name: "detect_spec",
@ -54,88 +70,6 @@ module VagrantPlugins
)
end
end
def has_capability_spec(*_)
SDK::FuncSpec.new(
name: "has_capability_spec",
args: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Args.NamedCapability",
name: "",
)
],
result: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Host.Capability.CheckResp",
name: "",
),
],
)
end
def has_capability(req, ctx)
ServiceInfo.with_info(ctx) do |info|
plugin_name = info.plugin_name
n_cap = req.args.detect { |a|
a.type == 'hashicorp.vagrant.sdk.Args.NamedCapability'
}&.value&.value
p = Vagrant::Host.new(
plugin_name.to_sym,
Vagrant.plugin("2").manager.hosts,
Vagrant.plugin("2").manager.host_capabilities,
nil,
)
SDK::Host::Capability::CheckResp.new(
has_capability: p.capability?(n_cap.strip.to_s.to_sym)
)
end
end
def capability_spec(*_)
SDK::FuncSpec.new(
name: "capability_spec",
args: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Args.TerminalUI",
name: "",
),
],
result: [
SDK::FuncSpec::Value.new(
type: "hashicorp.vagrant.sdk.Host.Capability.Resp"
)
]
)
end
def capability(req, ctx)
ServiceInfo.with_info(ctx) do |info|
begin
res = nil
plugin_name = info.plugin_name
n_cap = req.name
ui_client = mapper.funcspec_map(req.spec)
ui = Vagrant::UI::Remote.new(ui_client)
p = Vagrant::Host.new(
plugin_name.to_sym,
Vagrant.plugin("2").manager.hosts,
Vagrant.plugin("2").manager.host_capabilities,
nil,
)
res = p.capability(n_cap.to_s.strip.to_sym, ui) # TODO(spox): first arg needs to be env / statebag
vres = Google::Protobuf::Value.new
vres.from_ruby(res)
SDK::Host::Capability::Resp.new(
result: Google::Protobuf::Any.pack(vres)
)
rescue => err
raise "#{err.class}: #{err}\n#{err.backtrace.join("\n")}"
end
end
end
end
end
end