Separate local-exec push `script` from `inline`

This commit is contained in:
Seth Vargo 2014-11-17 13:16:39 -05:00
parent aa60fe6031
commit ede14d7daa
5 changed files with 165 additions and 23 deletions

View File

@ -1,27 +1,38 @@
module VagrantPlugins
module LocalExecPush
class Config < Vagrant.plugin("2", :config)
# The path (relative to the machine root) to a local script that will be
# executed.
# @return [String]
attr_accessor :script
# The command (as a string) to execute.
# @return [String]
attr_accessor :command
attr_accessor :inline
def initialize
@command = UNSET_VALUE
@script = UNSET_VALUE
@inline = UNSET_VALUE
end
def finalize!
@command = nil if @command == UNSET_VALUE
@script = nil if @script == UNSET_VALUE
@inline = nil if @inline == UNSET_VALUE
end
def validate(machine)
errors = _detected_errors
if missing?(@command)
if missing?(@script) && missing?(@inline)
errors << I18n.t("local_exec_push.errors.missing_attribute",
attribute: "command",
attribute: "script",
)
end
if !missing?(@script) && !missing?(@inline)
errors << I18n.t("local_exec_push.errors.cannot_specify_script_and_inline")
end
{ "Local Exec push" => errors }
end

View File

@ -1,6 +1,10 @@
en:
local_exec_push:
errors:
cannot_specify_script_and_inline: |-
You have specified both the 'script' and 'inline' attributes for the
Vagrant Local Exec Push plugin. You may only specify one of these
attributes.
command_failed: |-
The following command exited with a non-zero exit status:

View File

@ -1,3 +1,5 @@
require "fileutils"
require "tempfile"
require "vagrant/util/subprocess"
require_relative "errors"
@ -6,11 +8,35 @@ module VagrantPlugins
module LocalExecPush
class Push < Vagrant.plugin("2", :push)
def push
execute!(config.command)
if config.inline
execute_inline!(config.inline)
else
execute_script!(config.script)
end
end
# Execute the command, raising an exception if it fails.
# @return [Vagrant::Util::Subprocess::Result]
# Execute the inline script by writing it to a tempfile and executing.
def execute_inline!(inline)
script = Tempfile.new(["vagrant-local-exec-script", ".sh"])
script.write(inline)
script.rewind
execute_script!(script.path)
ensure
if script
script.close
script.unlink
end
end
# Execute the script, expanding the path relative to the current env root.
def execute_script!(path)
path = File.expand_path(path, env.root_path)
FileUtils.chmod("+x", path)
execute!(path)
end
# Execute the script, raising an exception if it fails.
def execute!(*cmd)
result = Vagrant::Util::Subprocess.execute(*cmd)

View File

@ -12,10 +12,17 @@ describe VagrantPlugins::LocalExecPush::Config do
let(:machine) { double("machine") }
describe "#command" do
describe "#script" do
it "defaults to nil" do
subject.finalize!
expect(subject.command).to be(nil)
expect(subject.script).to be(nil)
end
end
describe "#inline" do
it "defaults to nil" do
subject.finalize!
expect(subject.inline).to be(nil)
end
end
@ -25,20 +32,53 @@ describe VagrantPlugins::LocalExecPush::Config do
.and_return(double("env",
root_path: "",
))
subject.command = "echo"
subject.finalize!
end
let(:result) { subject.validate(machine) }
let(:errors) { result["Local Exec push"] }
context "when the command is missing" do
it "returns an error" do
subject.command = ""
subject.finalize!
expect(errors).to include(I18n.t("local_exec_push.errors.missing_attribute",
attribute: "command",
))
context "when script is present" do
before { subject.script = "foo.sh" }
context "when inline is present" do
before { subject.inline = "echo" }
it "returns an error" do
expect(errors).to include(
I18n.t("local_exec_push.errors.cannot_specify_script_and_inline")
)
end
end
context "when inline is not present" do
before { subject.inline = "" }
it "does not return an error" do
expect(errors).to be_empty
end
end
end
context "when script is not present" do
before { subject.script = "" }
context "when inline is present" do
before { subject.inline = "echo" }
it "does not return an error" do
expect(errors).to be_empty
end
end
context "when inline is not present" do
before { subject.inline = "" }
it "returns an error" do
expect(errors).to include(I18n.t("local_exec_push.errors.missing_attribute",
attribute: "script",
))
end
end
end
end

View File

@ -13,21 +13,82 @@ describe VagrantPlugins::LocalExecPush::Push do
let(:env) { isolated_environment }
let(:config) do
double("config",
command: "echo",
script: nil,
inline: nil,
)
end
subject { described_class.new(env, config) }
before do
allow(env).to receive(:root_path)
.and_return(File.expand_path("..", __FILE__))
end
describe "#push" do
before do
allow(subject).to receive(:execute_inline!)
allow(subject).to receive(:execute_script!)
allow(subject).to receive(:execute!)
end
it "executes the command" do
context "when inline is given" do
before { allow(config).to receive(:inline).and_return("echo") }
it "executes the inline script" do
expect(subject).to receive(:execute_inline!)
.with(config.inline)
subject.push
end
end
context "when script is given" do
before { allow(config).to receive(:script).and_return("foo.sh") }
it "executes the script" do
expect(subject).to receive(:execute_script!)
.with(config.script)
subject.push
end
end
end
describe "#execute_inline!" do
before { allow(subject).to receive(:execute_script!) }
it "writes the script to a tempfile" do
expect(Tempfile).to receive(:new).and_call_original
subject.execute_inline!("echo")
end
it "executes the script" do
expect(subject).to receive(:execute_script!)
subject.execute_inline!("echo")
end
end
describe "#execute_script!" do
before do
allow(subject).to receive(:execute!)
allow(FileUtils).to receive(:chmod)
end
it "expands the path relative to the machine root" do
expect(subject).to receive(:execute!)
.with(config.command)
subject.push
.with(File.expand_path("foo.sh", env.root_path))
subject.execute_script!("./foo.sh")
end
it "makes the file executable" do
expect(FileUtils).to receive(:chmod)
.with("+x", File.expand_path("foo.sh", env.root_path))
subject.execute_script!("./foo.sh")
end
it "calls execute!" do
expect(subject).to receive(:execute!)
.with(File.expand_path("foo.sh", env.root_path))
subject.execute_script!("./foo.sh")
end
end