diff --git a/builtin/myplugin/command.go b/builtin/myplugin/command.go index 7033104ae..16e9df7b9 100644 --- a/builtin/myplugin/command.go +++ b/builtin/myplugin/command.go @@ -71,7 +71,7 @@ func (c *Command) CommandInfoFunc() interface{} { func (c *Command) CommandInfo() *plugincore.CommandInfo { return &plugincore.CommandInfo{ - Name: []string{"myplugin"}, + Name: "myplugin", Help: c.Help(), Synopsis: c.Synopsis(), Flags: c.Flags(), diff --git a/internal/core/basis.go b/internal/core/basis.go index cbf945b2b..516f93377 100644 --- a/internal/core/basis.go +++ b/internal/core/basis.go @@ -102,7 +102,8 @@ func (b *Basis) Init() (result *vagrant_server.Job_InitResult, err error) { if err != nil { b.logger.Error("failed to get command info for command "+name, "error", err) } - err = RegisterSubcommands(cmd, result) + names := []string{cmdInfo.Name} + err = RegisterSubcommands(cmdInfo, names, result) if err != nil { b.logger.Error("subcommand error", err) } @@ -120,24 +121,21 @@ func (b *Basis) Init() (result *vagrant_server.Job_InitResult, err error) { return } -func RegisterSubcommands(cmd sdkcore.Command, result *vagrant_server.Job_InitResult) (err error) { - subcmds, err := cmd.Subcommands() +func RegisterSubcommands(cmd *sdkcore.CommandInfo, names []string, result *vagrant_server.Job_InitResult) (err error) { + subcmds := cmd.Subcommands if len(subcmds) > 0 { for _, scmd := range subcmds { - scmdInfo, err := scmd.CommandInfo() - if err != nil { - return err - } + name := append(names, scmd.Name) result.Commands = append( result.Commands, &vagrant_server.Job_Command{ - Name: strings.Join(scmdInfo.Name, " "), - Synopsis: scmdInfo.Synopsis, - Help: scmdInfo.Help, - Flags: FlagsToProtoMapper(scmdInfo.Flags), + Name: strings.Join(name, " "), + Synopsis: scmd.Synopsis, + Help: scmd.Help, + Flags: FlagsToProtoMapper(scmd.Flags), }, ) - err = RegisterSubcommands(scmd, result) + err = RegisterSubcommands(scmd, name, result) } } return diff --git a/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb.rb b/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb.rb index de14e1be3..ecd0339ba 100644 --- a/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb.rb +++ b/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb.rb @@ -326,17 +326,19 @@ Google::Protobuf::DescriptorPool.generated_pool.build do value :STRING, 0 value :BOOL, 2 end + add_message "hashicorp.vagrant.sdk.Command.CommandInfo" do + optional :name, :string, 1 + optional :help, :string, 2 + optional :synopsis, :string, 3 + repeated :flags, :message, 4, "hashicorp.vagrant.sdk.Command.Flag" + repeated :subcommands, :message, 5, "hashicorp.vagrant.sdk.Command.CommandInfo" + end add_message "hashicorp.vagrant.sdk.Command.CommandInfoResp" do - optional :help, :string, 1 - optional :synopsis, :string, 2 - repeated :flags, :message, 3, "hashicorp.vagrant.sdk.Command.Flag" + optional :command_info, :message, 1, "hashicorp.vagrant.sdk.Command.CommandInfo" end add_message "hashicorp.vagrant.sdk.Command.ExecuteResp" do optional :exit_code, :int64, 1 end - add_message "hashicorp.vagrant.sdk.Command.SubcommandResp" do - repeated :commands, :string, 1 - end add_message "hashicorp.vagrant.sdk.Command.Arguments" do repeated :flags, :message, 1, "hashicorp.vagrant.sdk.Command.Arguments.Flag" repeated :args, :string, 2 @@ -606,9 +608,9 @@ module Hashicorp Command = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command").msgclass Command::Flag = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.Flag").msgclass Command::Flag::Type = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.Flag.Type").enummodule + Command::CommandInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.CommandInfo").msgclass Command::CommandInfoResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.CommandInfoResp").msgclass Command::ExecuteResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.ExecuteResp").msgclass - Command::SubcommandResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.SubcommandResp").msgclass Command::Arguments = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.Arguments").msgclass Command::Arguments::Flag = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.Arguments.Flag").msgclass Command::Arguments::Flag::Type = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.Command.Arguments.Flag.Type").enummodule diff --git a/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_services_pb.rb b/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_services_pb.rb index c2efbb06b..5ce9e4117 100644 --- a/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_services_pb.rb +++ b/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_services_pb.rb @@ -143,8 +143,6 @@ module Hashicorp rpc :Documentation, ::Google::Protobuf::Empty, ::Hashicorp::Vagrant::Sdk::Config::Documentation rpc :ExecuteSpec, ::Google::Protobuf::Empty, ::Hashicorp::Vagrant::Sdk::FuncSpec rpc :Execute, ::Hashicorp::Vagrant::Sdk::FuncSpec::Args, ::Hashicorp::Vagrant::Sdk::Command::ExecuteResp - rpc :SubcommandSpec, ::Google::Protobuf::Empty, ::Hashicorp::Vagrant::Sdk::FuncSpec - rpc :Subcommands, ::Hashicorp::Vagrant::Sdk::FuncSpec::Args, ::Hashicorp::Vagrant::Sdk::Command::SubcommandResp rpc :CommandInfoSpec, ::Google::Protobuf::Empty, ::Hashicorp::Vagrant::Sdk::FuncSpec rpc :CommandInfo, ::Hashicorp::Vagrant::Sdk::FuncSpec::Args, ::Hashicorp::Vagrant::Sdk::Command::CommandInfoResp end diff --git a/plugins/commands/serve/service/command_service.rb b/plugins/commands/serve/service/command_service.rb index 833ae16a9..f8aa7425f 100644 --- a/plugins/commands/serve/service/command_service.rb +++ b/plugins/commands/serve/service/command_service.rb @@ -6,7 +6,9 @@ module VagrantPlugins class CommandService < SDK::CommandService::Service prepend VagrantPlugins::CommandServe::Service::ExceptionLogger - [:execute, :subcommands, :command_info].each do |method| + LOGGER = Log4r::Logger.new("vagrant::plugins::command::service:command_service") + + [:execute, :command_info].each do |method| VagrantPlugins::CommandServe::Service::ExceptionLogger.log_exception method end @@ -16,60 +18,74 @@ module VagrantPlugins def command_info(req, ctx) ServiceInfo.with_info(ctx) do |info| - plugin_name = info.plugin_name - - options = command_options_for(plugin_name, info.command) - - if options.nil? - hlp_msg = "" - flags = [] - else - hlp_msg = options.help - # Now we can build our list of flags - flags = options.top.list.find_all { |o| - o.is_a?(OptionParser::Switch) - }.map { |o| - SDK::Command::Flag.new( - description: o.desc.join(" "), - long_name: o.switch_name, - short_name: o.short.first, - type: o.is_a?(OptionParser::Switch::NoArgument) ? - SDK::Command::Flag::Type::BOOL : - SDK::Command::Flag::Type::STRING - ) - } - end - - if info.command.empty? - plugin = Vagrant::Plugin::V2::Plugin.manager.commands[plugin_name.to_sym].to_a.first - if !plugin - raise "Failed to locate command plugin for: #{plugin_name}" - end - klass = plugin.call - synopsis = klass.synopsis - else - synopsis = "" - end - + command_info = collect_command_info(info.plugin_name, info.command) + LOGGER.info("command info, #{command_info}") SDK::Command::CommandInfoResp.new( - help: hlp_msg, - flags: flags, - synopsis: synopsis, + command_info: command_info, ) end end - def subcommand_spec(*args) - return SDK::FuncSpec.new + def collect_command_info(plugin_name, subcommand_names) + LOGGER.info("collecting command information for #{plugin_name} #{subcommand_names}") + options = command_options_for(plugin_name, subcommand_names) + if options.nil? + hlp_msg = "" + flags = [] + else + hlp_msg = options.help + # Now we can build our list of flags + flags = options.top.list.find_all { |o| + o.is_a?(OptionParser::Switch) + }.map { |o| + SDK::Command::Flag.new( + description: o.desc.join(" "), + long_name: o.switch_name, + short_name: o.short.first, + type: o.is_a?(OptionParser::Switch::NoArgument) ? + SDK::Command::Flag::Type::BOOL : + SDK::Command::Flag::Type::STRING + ) + } + end + + if subcommand_names.empty? + plugin = Vagrant::Plugin::V2::Plugin.manager.commands[plugin_name.to_sym].to_a.first + if !plugin + raise "Failed to locate command plugin for: #{plugin_name}" + end + klass = plugin.call + synopsis = klass.synopsis + command_name = plugin_name + else + synopsis = "" + command_name = subcommand_names.last + end + subcommands = get_subcommands(plugin_name, subcommand_names) + + SDK::Command::CommandInfo.new( + name: command_name, + help: hlp_msg, + flags: flags, + synopsis: synopsis, + subcommands: subcommands + ) end - def subcommands(req, ctx) - ServiceInfo.with_info(ctx) do |info| - cmds = subcommands_for(info.plugin_name, info.command) - SDK::Command::SubcommandResp.new( - commands: cmds.nil? ? [] : cmds.keys, - ) + def get_subcommands(plugin_name, subcommand_names) + LOGGER.info("collecting subcommands for #{plugin_name} #{subcommand_names}") + subcommands = [] + cmds = subcommands_for(plugin_name, subcommand_names) + if !cmds.nil? + LOGGER.info("found subcommands #{cmds.keys}") + cmds.keys.each do |subcmd| + subnms = subcommand_names.dup + subcommands << collect_command_info(plugin_name, subnms.append(subcmd.to_s)) + end + else + LOGGER.info("no subcommands found") end + return subcommands end def augment_cmd_class(cmd_cls)