Fix local exec pushes in server mode

The local-exec push strategy was assuming it was running from a CLI and
so it wouldn't be a big deal for it to straight up `exec` and replace
its running with the user command. That command will just do its thing
and we want the exit code for the CLI command to match anyways, right?

Sure that works for a shell, but in a GRPC server setting it's decidedly
Not Cool to suddenly swap out the running process!

As you can imagine - the effect of doing this was all sorts of broken
pipes and unexpected EOFs and a very confused @phinze.

Luckily we had a subprocess strategy sitting right there for Windows
compat, so it was just a matter of switching to that in the server
context as well. Long and winding debugging process; simple fix;
just another classic!
This commit is contained in:
Paul Hinze 2022-01-06 12:24:42 -06:00
parent aa934f4436
commit 142b1af0cc
No known key found for this signature in database
GPG Key ID: B69DEDF2D55501C0
2 changed files with 13 additions and 2 deletions

View File

@ -7,6 +7,8 @@ require_relative "errors"
module VagrantPlugins
module LocalExecPush
class Push < Vagrant.plugin("2", :push)
@@logger = Log4r::Logger.new("vagrant::push::local_exec")
def push
if config.inline
execute_inline!(config.inline, config.args)
@ -47,7 +49,7 @@ module VagrantPlugins
# Execute the script, raising an exception if it fails.
def execute!(*cmd)
if Vagrant::Util::Platform.windows?
if Vagrant::Util::Platform.windows? || Vagrant.server_mode?
execute_subprocess!(*cmd)
else
execute_exec!(*cmd)
@ -63,11 +65,13 @@ module VagrantPlugins
# Run the command as exec (unix).
def execute_exec!(*cmd)
@@logger.debug("executing command via exec: #{cmd.inspect}")
Vagrant::Util::SafeExec.exec(cmd[0], *cmd[1..-1])
end
# Run the command as a subprocess (windows).
def execute_subprocess!(*cmd)
@@logger.debug("executing command via subprocess: #{cmd.inspect}")
cmd = cmd.dup << { notify: [:stdout, :stderr] }
result = Vagrant::Util::Subprocess.execute(*cmd) do |type, data|
if type == :stdout
@ -77,7 +81,7 @@ module VagrantPlugins
end
end
Kernel.exit(result.exit_code)
Kernel.exit(result.exit_code) unless Vagrant.server_mode?
end
end
end

View File

@ -122,5 +122,12 @@ describe VagrantPlugins::LocalExecPush::Push do
expect(e).to be_a(SystemExit)
}
end
it "uses subprocess when running in server mode, and does not exit" do
allow(Vagrant).to receive(:server_mode?).and_return(true)
result = double("result", exit_code: 0)
expect(Vagrant::Util::Subprocess).to receive(:execute).and_return(result)
expect { subject.execute! }.to_not raise_error
end
end
end