From 079975fe2b139d5f4a710711c1b7c8002c8e3274 Mon Sep 17 00:00:00 2001 From: sophia Date: Fri, 20 May 2022 10:49:33 -0500 Subject: [PATCH 1/9] Add machine readable flag --- internal/cli/base.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/cli/base.go b/internal/cli/base.go index d2f61f74d..42cf051c1 100644 --- a/internal/cli/base.go +++ b/internal/cli/base.go @@ -407,6 +407,12 @@ func (c *baseCommand) flagSet(bit flagSetBit, f func([]*component.CommandFlag) [ DefaultValue: "true", Type: component.FlagBool, }, + { + LongName: "machine-readable", + Description: "Target to apply command", + DefaultValue: "false", + Type: component.FlagBool, + }, } if bit&flagSetOperation != 0 { From 58e8e6ff976ba3b7266d782819419383cee0ecba Mon Sep 17 00:00:00 2001 From: sophia Date: Fri, 20 May 2022 10:49:56 -0500 Subject: [PATCH 2/9] Remove unused machine initialization steps --- lib/vagrant/machine/remote.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/vagrant/machine/remote.rb b/lib/vagrant/machine/remote.rb index 6c9d56f5d..21798aa97 100644 --- a/lib/vagrant/machine/remote.rb +++ b/lib/vagrant/machine/remote.rb @@ -62,16 +62,6 @@ module Vagrant @state_mutex = Mutex.new # TODO: get trigger config from go @triggers = Vagrant::Plugin::V2::Trigger.new(@env, @config.trigger, self, @ui) - - # If the ID is the special not created ID, then set our ID to - # nil so that we destroy all our data. - # if state.id == MachineState::NOT_CREATED_ID - # self.id = nil - # end - - # Output a bunch of information about this machine in - # machine-readable format in case someone is listening. - @ui.machine("metadata", "provider", provider_name) end # @return [Box] From 313ba8655a97fab6a182f4835527f76e1202a388 Mon Sep 17 00:00:00 2001 From: sophia Date: Fri, 20 May 2022 10:50:31 -0500 Subject: [PATCH 3/9] Implement missing ui#machine method --- lib/vagrant/ui/remote.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/vagrant/ui/remote.rb b/lib/vagrant/ui/remote.rb index c9346de58..f93fab8a7 100644 --- a/lib/vagrant/ui/remote.rb +++ b/lib/vagrant/ui/remote.rb @@ -42,6 +42,28 @@ module Vagrant client.output(message.gsub("%", "%%"), **opts) end + def machine(type, *data) + opts = {} + opts = data.pop if data.last.kind_of?(Hash) + + target = opts[:target] || "" + + # Prepare the data by replacing characters that aren't outputted + data.each_index do |i| + data[i] = data[i].to_s.dup + data[i].gsub!(",", "%!(VAGRANT_COMMA)") + data[i].gsub!("\n", "\\n") + data[i].gsub!("\r", "\\r") + end + + # Avoid locks in a trap context introduced from Ruby 2.0 + Thread.new do + @lock.synchronize do + safe_puts(["#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}", {}], {}) + end + end.join(THREAD_MAX_JOIN_TIMEOUT) + end + def to_proto @client.proto end From 65e851d646e116e006a08bac6e878d7a2190a004 Mon Sep 17 00:00:00 2001 From: sophia Date: Tue, 31 May 2022 10:28:26 -0500 Subject: [PATCH 4/9] Output machine readable data as table --- lib/vagrant/ui/remote.rb | 11 +++------ plugins/commands/serve/client/terminal.rb | 30 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/vagrant/ui/remote.rb b/lib/vagrant/ui/remote.rb index f93fab8a7..300631f80 100644 --- a/lib/vagrant/ui/remote.rb +++ b/lib/vagrant/ui/remote.rb @@ -45,7 +45,6 @@ module Vagrant def machine(type, *data) opts = {} opts = data.pop if data.last.kind_of?(Hash) - target = opts[:target] || "" # Prepare the data by replacing characters that aren't outputted @@ -55,13 +54,11 @@ module Vagrant data[i].gsub!("\n", "\\n") data[i].gsub!("\r", "\\r") end + table_data = { + rows: [[Time.now.utc.to_i, target, type, data.join(",")]] + } - # Avoid locks in a trap context introduced from Ruby 2.0 - Thread.new do - @lock.synchronize do - safe_puts(["#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}", {}], {}) - end - end.join(THREAD_MAX_JOIN_TIMEOUT) + client.table(table_data, **opts) end def to_proto diff --git a/plugins/commands/serve/client/terminal.rb b/plugins/commands/serve/client/terminal.rb index 3ca46aec6..ef58c975a 100644 --- a/plugins/commands/serve/client/terminal.rb +++ b/plugins/commands/serve/client/terminal.rb @@ -72,6 +72,36 @@ module VagrantPlugins ].each ).each {} end + + # @params [Map] data has the table data for the event. The form of + # this map is: + # { headers: List, rows: List> } + def table(data, **opts) + rows = data[:rows].map { |r| + SDK::TerminalUI::Event::TableRow.new( + entries: r.map { |e| + SDK::TerminalUI::Event::TableEntry.new(value: e.to_s) + } + ) + } + event_resp = client.events( + [ + SDK::TerminalUI::Event.new( + table: SDK::TerminalUI::Event::Table.new( + headers: data[:headers], + rows: rows + ) + ), + ].each + ) + + event_resp.map { |resp| + input = resp.input + if !input.error.nil? + raise Vagrant::Errors::VagrantRemoteError, msg: input.error.message + end + } + end end end end From 32bb18e9b9f9c2f64c017b389124dd57d61ba1a5 Mon Sep 17 00:00:00 2001 From: sophia Date: Tue, 31 May 2022 10:53:07 -0500 Subject: [PATCH 5/9] Only output machine readable data if the terminal is not interactive --- lib/vagrant/ui/remote.rb | 6 ++++++ plugins/commands/serve/client/terminal.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/vagrant/ui/remote.rb b/lib/vagrant/ui/remote.rb index 300631f80..893ff03a7 100644 --- a/lib/vagrant/ui/remote.rb +++ b/lib/vagrant/ui/remote.rb @@ -20,6 +20,7 @@ module Vagrant def initialize(client) super() @client = client + @logger = Log4r::Logger.new("vagrant::ui") end def clear_line @@ -43,6 +44,11 @@ module Vagrant end def machine(type, *data) + if client.is_interactive + @logger.info("Machine: #{type} #{data.inspect}") + return + end + opts = {} opts = data.pop if data.last.kind_of?(Hash) target = opts[:target] || "" diff --git a/plugins/commands/serve/client/terminal.rb b/plugins/commands/serve/client/terminal.rb index ef58c975a..ded1ab058 100644 --- a/plugins/commands/serve/client/terminal.rb +++ b/plugins/commands/serve/client/terminal.rb @@ -19,7 +19,7 @@ module VagrantPlugins end def is_interactive - client.is_interactive.interactive + client.is_interactive(Empty.new).interactive end def input(prompt, **opts) From 9ed92d2ab6095878b4973c38e7fe928283248e3c Mon Sep 17 00:00:00 2001 From: sophia Date: Tue, 31 May 2022 14:41:34 -0500 Subject: [PATCH 6/9] Recognize --machine-readable flag --- internal/cli/base.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/internal/cli/base.go b/internal/cli/base.go index 42cf051c1..42c069d34 100644 --- a/internal/cli/base.go +++ b/internal/cli/base.go @@ -91,6 +91,9 @@ type baseCommand struct { // flagInteractive is whether the output is interactive flagInteractive bool + // flagMachineReadable is whether the terminal ui should only output machine readable data + flagMachineReadable bool + // flagConnection contains manual flag-based connection info. flagConnection clicontext.Config @@ -154,8 +157,11 @@ func BaseCommand(ctx context.Context, log hclog.Logger, logOutput io.Writer, opt // Set UI var ui terminal.UI - // Set non interactive if the --no-interactive flag is provided - if !bc.flagInteractive { + if bc.flagMachineReadable { + // Set machine readable ui if the --machine-readable flag is provided + ui = terminal.MachineReadableUI(ctx, terminal.TableFormat) + } else if !bc.flagInteractive { + // Set non interactive if the --no-interactive flag is provided ui = terminal.NonInteractiveUI(ctx) } else { // If no ui related flags are set, create a new one @@ -285,8 +291,11 @@ func (c *baseCommand) Init(opts ...Option) (err error) { // Set UI var ui terminal.UI - // Set non interactive if the --no-interactive flag is provided - if !c.flagInteractive { + if c.flagMachineReadable { + // Set machine readable ui if the --machine-readable flag is provided + ui = terminal.MachineReadableUI(c.Ctx, terminal.TableFormat) + } else if !c.flagInteractive { + // Set non interactive if the --no-interactive flag is provided ui = terminal.NonInteractiveUI(c.Ctx) } else { // If no ui related flags are set, use the base config ui @@ -499,6 +508,8 @@ func (c *baseCommand) Parse( c.flagRemote = pf.DefaultValue().(bool) case "interactive": c.flagInteractive = pf.DefaultValue().(bool) + case "machine-readable": + c.flagMachineReadable = pf.DefaultValue().(bool) } if !pf.Updated() { continue @@ -515,6 +526,8 @@ func (c *baseCommand) Parse( c.flagRemote = pf.Value().(bool) case "interactive": c.flagInteractive = pf.Value().(bool) + case "machine-readable": + c.flagMachineReadable = pf.Value().(bool) } c.flagData[f] = pf.Value() } From 4ffe33461c4e8e9da1449623659ecfb2932acbb4 Mon Sep 17 00:00:00 2001 From: sophia Date: Tue, 31 May 2022 15:47:27 -0500 Subject: [PATCH 7/9] go generate . --- lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb.rb | 4 ++++ .../protobufs/proto/vagrant_plugin_sdk/plugin_services_pb.rb | 1 + 2 files changed, 5 insertions(+) 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 27f2a6bde..7e4b20fbb 100644 --- a/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb.rb +++ b/lib/vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb.rb @@ -308,6 +308,9 @@ Google::Protobuf::DescriptorPool.generated_pool.build do add_message "hashicorp.vagrant.sdk.TerminalUI.IsInteractiveResponse" do optional :interactive, :bool, 1 end + add_message "hashicorp.vagrant.sdk.TerminalUI.IsMachineReadableResponse" do + optional :machine_readable, :bool, 1 + end add_message "hashicorp.vagrant.sdk.TerminalUI.OutputRequest" do repeated :lines, :string, 1 optional :style, :enum, 2, "hashicorp.vagrant.sdk.TerminalUI.OutputRequest.Style" @@ -1020,6 +1023,7 @@ module Hashicorp ImplementsResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.ImplementsResp").msgclass TerminalUI = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.TerminalUI").msgclass TerminalUI::IsInteractiveResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.TerminalUI.IsInteractiveResponse").msgclass + TerminalUI::IsMachineReadableResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.TerminalUI.IsMachineReadableResponse").msgclass TerminalUI::OutputRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.TerminalUI.OutputRequest").msgclass TerminalUI::OutputRequest::Style = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.TerminalUI.OutputRequest.Style").enummodule TerminalUI::Response = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("hashicorp.vagrant.sdk.TerminalUI.Response").msgclass 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 39ccc159b..2f3b01357 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 @@ -26,6 +26,7 @@ module Hashicorp rpc :Output, ::Hashicorp::Vagrant::Sdk::TerminalUI::OutputRequest, ::Google::Protobuf::Empty rpc :Events, stream(::Hashicorp::Vagrant::Sdk::TerminalUI::Event), stream(::Hashicorp::Vagrant::Sdk::TerminalUI::Response) rpc :IsInteractive, ::Google::Protobuf::Empty, ::Hashicorp::Vagrant::Sdk::TerminalUI::IsInteractiveResponse + rpc :IsMachineReadable, ::Google::Protobuf::Empty, ::Hashicorp::Vagrant::Sdk::TerminalUI::IsMachineReadableResponse end Stub = Service.rpc_stub_class From 194882214aa559c83d81745e0fe3e4f10cf43063 Mon Sep 17 00:00:00 2001 From: sophia Date: Tue, 31 May 2022 15:47:47 -0500 Subject: [PATCH 8/9] Add machine readable bool endpoint to terminal ui --- internal/runner/ui.go | 4 ++++ internal/runner/ui_multi.go | 9 +++++++++ lib/vagrant/ui/remote.rb | 2 +- plugins/commands/serve/client/terminal.rb | 4 ++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/internal/runner/ui.go b/internal/runner/ui.go index f03ce4eb9..8ca8ca421 100644 --- a/internal/runner/ui.go +++ b/internal/runner/ui.go @@ -42,6 +42,10 @@ func (u *runnerUI) Interactive() bool { return false } +func (u *runnerUI) MachineReadable() bool { + return false +} + func (u *runnerUI) ClearLine() { // NO-OP - noninteractive } diff --git a/internal/runner/ui_multi.go b/internal/runner/ui_multi.go index aacef5732..7f7c704da 100644 --- a/internal/runner/ui_multi.go +++ b/internal/runner/ui_multi.go @@ -52,6 +52,15 @@ func (u *multiUI) Interactive() bool { return false } +func (u *multiUI) MachineReadable() bool { + for _, u := range u.UIs { + if u.MachineReadable() { + return true + } + } + return false +} + func (u *multiUI) Output(msg string, raw ...interface{}) { for _, u := range u.UIs { u.Output(msg, raw...) diff --git a/lib/vagrant/ui/remote.rb b/lib/vagrant/ui/remote.rb index 893ff03a7..398ad6453 100644 --- a/lib/vagrant/ui/remote.rb +++ b/lib/vagrant/ui/remote.rb @@ -44,7 +44,7 @@ module Vagrant end def machine(type, *data) - if client.is_interactive + if !client.is_machine_readable @logger.info("Machine: #{type} #{data.inspect}") return end diff --git a/plugins/commands/serve/client/terminal.rb b/plugins/commands/serve/client/terminal.rb index ded1ab058..2e8646298 100644 --- a/plugins/commands/serve/client/terminal.rb +++ b/plugins/commands/serve/client/terminal.rb @@ -22,6 +22,10 @@ module VagrantPlugins client.is_interactive(Empty.new).interactive end + def is_machine_readable + client.is_machine_readable(Empty.new).machine_readable + end + def input(prompt, **opts) event_resp = client.events( [ From 3f4ab04e3d05a6bbabf8c993456c7d5cb767a4e6 Mon Sep 17 00:00:00 2001 From: sophia Date: Fri, 3 Jun 2022 09:28:53 -0500 Subject: [PATCH 9/9] Bump sdk --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 9598400a9..3da69fe49 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl/v2 v2.7.1-0.20201023000745-3de61ecba298 github.com/hashicorp/nomad/api v0.0.0-20200814140818-42de70466a9d - github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220525200400-f1459dc0d92b + github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220603142803-c69edee0b0a1 github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce // indirect github.com/imdario/mergo v0.3.11 github.com/improbable-eng/grpc-web v0.13.0 diff --git a/go.sum b/go.sum index b298c4e00..901ae8dd3 100644 --- a/go.sum +++ b/go.sum @@ -357,6 +357,8 @@ github.com/hashicorp/nomad/api v0.0.0-20200814140818-42de70466a9d h1:afuZ/KNbxwU github.com/hashicorp/nomad/api v0.0.0-20200814140818-42de70466a9d/go.mod h1:DCi2k47yuUDzf2qWAK8E1RVmWgz/lc0jZQeEnICTxmY= github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220525200400-f1459dc0d92b h1:GidqljOXwQSIFn+nk4DOpa0kpR/1x/yS/yCNnA7sUFE= github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220525200400-f1459dc0d92b/go.mod h1:KWfWOiotOWKiAqdroXVc7GUFnuOzlzhnRkGTV9Js7/s= +github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220603142803-c69edee0b0a1 h1:zp+NV96agdfbsO7FI7U8VaL3PkbTNCOvPJxCuIZB8rM= +github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220603142803-c69edee0b0a1/go.mod h1:KWfWOiotOWKiAqdroXVc7GUFnuOzlzhnRkGTV9Js7/s= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce h1:7UnVY3T/ZnHUrfviiAgIUjg2PXxsQfs5bphsG8F7Keo= github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=