pushes/local-exec: add args config
This commit is contained in:
parent
25ff027b08
commit
77031a79b7
|
@ -10,14 +10,24 @@ module VagrantPlugins
|
|||
# @return [String]
|
||||
attr_accessor :inline
|
||||
|
||||
# The arguments to provide when executing the script.
|
||||
# @return [Array<String>]
|
||||
attr_accessor :args
|
||||
|
||||
def initialize
|
||||
@script = UNSET_VALUE
|
||||
@inline = UNSET_VALUE
|
||||
@args = UNSET_VALUE
|
||||
end
|
||||
|
||||
def finalize!
|
||||
@script = nil if @script == UNSET_VALUE
|
||||
@inline = nil if @inline == UNSET_VALUE
|
||||
@args = nil if @args == UNSET_VALUE
|
||||
|
||||
if @args && args_valid?
|
||||
@args = @args.is_a?(Array) ? @args.map { |a| a.to_s } : @args.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def validate(machine)
|
||||
|
@ -33,6 +43,10 @@ module VagrantPlugins
|
|||
errors << I18n.t("local_exec_push.errors.cannot_specify_script_and_inline")
|
||||
end
|
||||
|
||||
if !args_valid?
|
||||
errors << I18n.t("local_exec_push.errors.args_bad_type")
|
||||
end
|
||||
|
||||
{ "Local Exec push" => errors }
|
||||
end
|
||||
|
||||
|
@ -43,6 +57,21 @@ module VagrantPlugins
|
|||
def missing?(obj)
|
||||
obj.to_s.strip.empty?
|
||||
end
|
||||
|
||||
# Args are optional, but if they're provided we only support them as a
|
||||
# string or as an array.
|
||||
def args_valid?
|
||||
return true if !args
|
||||
return true if args.is_a?(String)
|
||||
return true if args.is_a?(Fixnum)
|
||||
if args.is_a?(Array)
|
||||
args.each do |a|
|
||||
return false if !a.kind_of?(String) && !a.kind_of?(Fixnum)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,3 +20,4 @@ en:
|
|||
config.push.define "local-exec" do |push|
|
||||
push.%{attribute} = "..."
|
||||
end
|
||||
args_bad_type: "Local-exec push `args` must be a string or array."
|
|
@ -9,20 +9,20 @@ module VagrantPlugins
|
|||
class Push < Vagrant.plugin("2", :push)
|
||||
def push
|
||||
if config.inline
|
||||
execute_inline!(config.inline)
|
||||
execute_inline!(config.inline, config.args)
|
||||
else
|
||||
execute_script!(config.script)
|
||||
execute_script!(config.script, config.args)
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the inline script by writing it to a tempfile and executing.
|
||||
def execute_inline!(inline)
|
||||
def execute_inline!(inline, args)
|
||||
script = Tempfile.new(["vagrant-local-exec-script", ".sh"])
|
||||
script.write(inline)
|
||||
script.rewind
|
||||
script.close
|
||||
|
||||
execute_script!(script.path)
|
||||
execute_script!(script.path, args)
|
||||
ensure
|
||||
if script
|
||||
script.close
|
||||
|
@ -31,10 +31,18 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
# Execute the script, expanding the path relative to the current env root.
|
||||
def execute_script!(path)
|
||||
def execute_script!(path, args)
|
||||
path = File.expand_path(path, env.root_path)
|
||||
FileUtils.chmod("+x", path)
|
||||
execute!(path)
|
||||
|
||||
if args.is_a?(String)
|
||||
args = " #{args.to_s}"
|
||||
elsif args.is_a?(Array)
|
||||
args = args.map { |a| quote_and_escape(a) }
|
||||
args = " #{args.join(" ")}"
|
||||
end
|
||||
|
||||
execute!("#{path}#{args}")
|
||||
end
|
||||
|
||||
# Execute the script, raising an exception if it fails.
|
||||
|
@ -48,6 +56,11 @@ module VagrantPlugins
|
|||
|
||||
private
|
||||
|
||||
# Quote and escape strings for shell execution, thanks to Capistrano.
|
||||
def quote_and_escape(text, quote = '"')
|
||||
"#{quote}#{text.gsub(/#{quote}/) { |m| "#{m}\\#{m}#{m}" }}#{quote}"
|
||||
end
|
||||
|
||||
# Run the command as exec (unix).
|
||||
def execute_exec!(*cmd)
|
||||
Vagrant::Util::SafeExec.exec(cmd[0], *cmd[1..-1])
|
||||
|
|
|
@ -26,6 +26,13 @@ describe VagrantPlugins::LocalExecPush::Config do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#args" do
|
||||
it "defaults to nil" do
|
||||
subject.finalize!
|
||||
expect(subject.args).to be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#validate" do
|
||||
before do
|
||||
allow(machine).to receive(:env)
|
||||
|
@ -57,6 +64,42 @@ describe VagrantPlugins::LocalExecPush::Config do
|
|||
it "does not return an error" do
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "passes with string args" do
|
||||
subject.args = "a string"
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "passes with fixnum args" do
|
||||
subject.args = 1
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "passes with array args" do
|
||||
subject.args = ["an", "array"]
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "returns an error if args is neither a string nor an array" do
|
||||
neither_array_nor_string = Object.new
|
||||
|
||||
subject.args = neither_array_nor_string
|
||||
expect(errors).to include(
|
||||
I18n.t("local_exec_push.errors.args_bad_type")
|
||||
)
|
||||
end
|
||||
|
||||
it "handles scalar array args" do
|
||||
subject.args = ["string", 1, 2]
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "returns an error if args is an array with non-scalar types" do
|
||||
subject.args = [[1]]
|
||||
expect(errors).to include(
|
||||
I18n.t("local_exec_push.errors.args_bad_type")
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -69,6 +112,42 @@ describe VagrantPlugins::LocalExecPush::Config do
|
|||
it "does not return an error" do
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "passes with string args" do
|
||||
subject.args = "a string"
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "passes with fixnum args" do
|
||||
subject.args = 1
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "passes with array args" do
|
||||
subject.args = ["an", "array"]
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "returns an error if args is neither a string nor an array" do
|
||||
neither_array_nor_string = Object.new
|
||||
|
||||
subject.args = neither_array_nor_string
|
||||
expect(errors).to include(
|
||||
I18n.t("local_exec_push.errors.args_bad_type")
|
||||
)
|
||||
end
|
||||
|
||||
it "handles scalar array args" do
|
||||
subject.args = ["string", 1, 2]
|
||||
expect(errors).to be_empty
|
||||
end
|
||||
|
||||
it "returns an error if args is an array with non-scalar types" do
|
||||
subject.args = [[1]]
|
||||
expect(errors).to include(
|
||||
I18n.t("local_exec_push.errors.args_bad_type")
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "when inline is not present" do
|
||||
|
|
|
@ -15,6 +15,7 @@ describe VagrantPlugins::LocalExecPush::Push do
|
|||
double("config",
|
||||
script: nil,
|
||||
inline: nil,
|
||||
args: "some args",
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -37,7 +38,7 @@ describe VagrantPlugins::LocalExecPush::Push do
|
|||
|
||||
it "executes the inline script" do
|
||||
expect(subject).to receive(:execute_inline!)
|
||||
.with(config.inline)
|
||||
.with(config.inline, config.args)
|
||||
subject.push
|
||||
end
|
||||
end
|
||||
|
@ -47,7 +48,7 @@ describe VagrantPlugins::LocalExecPush::Push do
|
|||
|
||||
it "executes the script" do
|
||||
expect(subject).to receive(:execute_script!)
|
||||
.with(config.script)
|
||||
.with(config.script, config.args)
|
||||
subject.push
|
||||
end
|
||||
end
|
||||
|
@ -58,12 +59,12 @@ describe VagrantPlugins::LocalExecPush::Push do
|
|||
|
||||
it "writes the script to a tempfile" do
|
||||
expect(Tempfile).to receive(:new).and_call_original
|
||||
subject.execute_inline!("echo")
|
||||
subject.execute_inline!("echo", config.args)
|
||||
end
|
||||
|
||||
it "executes the script" do
|
||||
expect(subject).to receive(:execute_script!)
|
||||
subject.execute_inline!("echo")
|
||||
subject.execute_inline!("echo", config.args)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -76,19 +77,33 @@ describe VagrantPlugins::LocalExecPush::Push do
|
|||
it "expands the path relative to the machine root" do
|
||||
expect(subject).to receive(:execute!)
|
||||
.with(File.expand_path("foo.sh", env.root_path))
|
||||
subject.execute_script!("./foo.sh")
|
||||
subject.execute_script!("./foo.sh", nil)
|
||||
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")
|
||||
subject.execute_script!("./foo.sh", config.args)
|
||||
end
|
||||
|
||||
it "calls execute!" do
|
||||
expect(subject).to receive(:execute!)
|
||||
.with(File.expand_path("foo.sh", env.root_path))
|
||||
subject.execute_script!("./foo.sh")
|
||||
subject.execute_script!("./foo.sh", nil)
|
||||
end
|
||||
|
||||
context "when args is given" do
|
||||
it "passes string args to execute!" do
|
||||
expect(subject).to receive(:execute!)
|
||||
.with(File.expand_path("foo.sh", env.root_path) + " " + config.args)
|
||||
subject.execute_script!("./foo.sh", config.args)
|
||||
end
|
||||
|
||||
it "passes array args as string to execute!" do
|
||||
expect(subject).to receive(:execute!)
|
||||
.with(File.expand_path("foo.sh", env.root_path) + " \"one\" \"two\" \"three\"")
|
||||
subject.execute_script!("./foo.sh", ["one", "two", "three"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -27,6 +27,11 @@ options:
|
|||
execute. Vagrant will attempt to convert this script to an executable, but an
|
||||
exception will be raised if that fails.
|
||||
- `inline` - The inline script to execute (as a string).
|
||||
- `args` (string or array) - Optional arguments to pass to the shell script when executing it
|
||||
as a single string. These arguments must be written as if they were typed
|
||||
directly on the command line, so be sure to escape characters, quote,
|
||||
etc. as needed. You may also pass the arguments in using an array. In this
|
||||
case, Vagrant will handle quoting for you.
|
||||
|
||||
Please note - only one of the `script` and `inline` options may be specified in
|
||||
a single push definition.
|
||||
|
@ -70,3 +75,7 @@ And then invoke the push with Vagrant:
|
|||
```shell
|
||||
$ vagrant push
|
||||
```
|
||||
|
||||
### Script Arguments
|
||||
|
||||
Refer to [Shell Provisioner](/v2/provisioning/shell.html).
|
||||
|
|
Loading…
Reference in New Issue