Merge pull request #6661 from hasyimibhar/feature/push-local-exec-args
pushes/local-exec: add args config
This commit is contained in:
commit
e92a214803
|
@ -10,14 +10,24 @@ module VagrantPlugins
|
||||||
# @return [String]
|
# @return [String]
|
||||||
attr_accessor :inline
|
attr_accessor :inline
|
||||||
|
|
||||||
|
# The arguments to provide when executing the script.
|
||||||
|
# @return [Array<String>]
|
||||||
|
attr_accessor :args
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@script = UNSET_VALUE
|
@script = UNSET_VALUE
|
||||||
@inline = UNSET_VALUE
|
@inline = UNSET_VALUE
|
||||||
|
@args = UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
@script = nil if @script == UNSET_VALUE
|
@script = nil if @script == UNSET_VALUE
|
||||||
@inline = nil if @inline == 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
|
end
|
||||||
|
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
|
@ -33,6 +43,10 @@ module VagrantPlugins
|
||||||
errors << I18n.t("local_exec_push.errors.cannot_specify_script_and_inline")
|
errors << I18n.t("local_exec_push.errors.cannot_specify_script_and_inline")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if !args_valid?
|
||||||
|
errors << I18n.t("local_exec_push.errors.args_bad_type")
|
||||||
|
end
|
||||||
|
|
||||||
{ "Local Exec push" => errors }
|
{ "Local Exec push" => errors }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -43,6 +57,21 @@ module VagrantPlugins
|
||||||
def missing?(obj)
|
def missing?(obj)
|
||||||
obj.to_s.strip.empty?
|
obj.to_s.strip.empty?
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,3 +20,4 @@ en:
|
||||||
config.push.define "local-exec" do |push|
|
config.push.define "local-exec" do |push|
|
||||||
push.%{attribute} = "..."
|
push.%{attribute} = "..."
|
||||||
end
|
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)
|
class Push < Vagrant.plugin("2", :push)
|
||||||
def push
|
def push
|
||||||
if config.inline
|
if config.inline
|
||||||
execute_inline!(config.inline)
|
execute_inline!(config.inline, config.args)
|
||||||
else
|
else
|
||||||
execute_script!(config.script)
|
execute_script!(config.script, config.args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Execute the inline script by writing it to a tempfile and executing.
|
# 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 = Tempfile.new(["vagrant-local-exec-script", ".sh"])
|
||||||
script.write(inline)
|
script.write(inline)
|
||||||
script.rewind
|
script.rewind
|
||||||
script.close
|
script.close
|
||||||
|
|
||||||
execute_script!(script.path)
|
execute_script!(script.path, args)
|
||||||
ensure
|
ensure
|
||||||
if script
|
if script
|
||||||
script.close
|
script.close
|
||||||
|
@ -31,10 +31,18 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
# Execute the script, expanding the path relative to the current env root.
|
# 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)
|
path = File.expand_path(path, env.root_path)
|
||||||
FileUtils.chmod("+x", 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
|
end
|
||||||
|
|
||||||
# Execute the script, raising an exception if it fails.
|
# Execute the script, raising an exception if it fails.
|
||||||
|
@ -48,6 +56,11 @@ module VagrantPlugins
|
||||||
|
|
||||||
private
|
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).
|
# Run the command as exec (unix).
|
||||||
def execute_exec!(*cmd)
|
def execute_exec!(*cmd)
|
||||||
Vagrant::Util::SafeExec.exec(cmd[0], *cmd[1..-1])
|
Vagrant::Util::SafeExec.exec(cmd[0], *cmd[1..-1])
|
||||||
|
|
|
@ -26,6 +26,13 @@ describe VagrantPlugins::LocalExecPush::Config do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#args" do
|
||||||
|
it "defaults to nil" do
|
||||||
|
subject.finalize!
|
||||||
|
expect(subject.args).to be(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#validate" do
|
describe "#validate" do
|
||||||
before do
|
before do
|
||||||
allow(machine).to receive(:env)
|
allow(machine).to receive(:env)
|
||||||
|
@ -57,6 +64,42 @@ describe VagrantPlugins::LocalExecPush::Config do
|
||||||
it "does not return an error" do
|
it "does not return an error" do
|
||||||
expect(errors).to be_empty
|
expect(errors).to be_empty
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -69,6 +112,42 @@ describe VagrantPlugins::LocalExecPush::Config do
|
||||||
it "does not return an error" do
|
it "does not return an error" do
|
||||||
expect(errors).to be_empty
|
expect(errors).to be_empty
|
||||||
end
|
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
|
||||||
|
|
||||||
context "when inline is not present" do
|
context "when inline is not present" do
|
||||||
|
|
|
@ -15,6 +15,7 @@ describe VagrantPlugins::LocalExecPush::Push do
|
||||||
double("config",
|
double("config",
|
||||||
script: nil,
|
script: nil,
|
||||||
inline: nil,
|
inline: nil,
|
||||||
|
args: "some args",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ describe VagrantPlugins::LocalExecPush::Push do
|
||||||
|
|
||||||
it "executes the inline script" do
|
it "executes the inline script" do
|
||||||
expect(subject).to receive(:execute_inline!)
|
expect(subject).to receive(:execute_inline!)
|
||||||
.with(config.inline)
|
.with(config.inline, config.args)
|
||||||
subject.push
|
subject.push
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -47,7 +48,7 @@ describe VagrantPlugins::LocalExecPush::Push do
|
||||||
|
|
||||||
it "executes the script" do
|
it "executes the script" do
|
||||||
expect(subject).to receive(:execute_script!)
|
expect(subject).to receive(:execute_script!)
|
||||||
.with(config.script)
|
.with(config.script, config.args)
|
||||||
subject.push
|
subject.push
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -58,12 +59,12 @@ describe VagrantPlugins::LocalExecPush::Push do
|
||||||
|
|
||||||
it "writes the script to a tempfile" do
|
it "writes the script to a tempfile" do
|
||||||
expect(Tempfile).to receive(:new).and_call_original
|
expect(Tempfile).to receive(:new).and_call_original
|
||||||
subject.execute_inline!("echo")
|
subject.execute_inline!("echo", config.args)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes the script" do
|
it "executes the script" do
|
||||||
expect(subject).to receive(:execute_script!)
|
expect(subject).to receive(:execute_script!)
|
||||||
subject.execute_inline!("echo")
|
subject.execute_inline!("echo", config.args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -76,19 +77,33 @@ describe VagrantPlugins::LocalExecPush::Push do
|
||||||
it "expands the path relative to the machine root" do
|
it "expands the path relative to the machine root" do
|
||||||
expect(subject).to receive(:execute!)
|
expect(subject).to receive(:execute!)
|
||||||
.with(File.expand_path("foo.sh", env.root_path))
|
.with(File.expand_path("foo.sh", env.root_path))
|
||||||
subject.execute_script!("./foo.sh")
|
subject.execute_script!("./foo.sh", nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "makes the file executable" do
|
it "makes the file executable" do
|
||||||
expect(FileUtils).to receive(:chmod)
|
expect(FileUtils).to receive(:chmod)
|
||||||
.with("+x", File.expand_path("foo.sh", env.root_path))
|
.with("+x", File.expand_path("foo.sh", env.root_path))
|
||||||
subject.execute_script!("./foo.sh")
|
subject.execute_script!("./foo.sh", config.args)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "calls execute!" do
|
it "calls execute!" do
|
||||||
expect(subject).to receive(:execute!)
|
expect(subject).to receive(:execute!)
|
||||||
.with(File.expand_path("foo.sh", env.root_path))
|
.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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,11 @@ options:
|
||||||
execute. Vagrant will attempt to convert this script to an executable, but an
|
execute. Vagrant will attempt to convert this script to an executable, but an
|
||||||
exception will be raised if that fails.
|
exception will be raised if that fails.
|
||||||
- `inline` - The inline script to execute (as a string).
|
- `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
|
Please note - only one of the `script` and `inline` options may be specified in
|
||||||
a single push definition.
|
a single push definition.
|
||||||
|
@ -70,3 +75,7 @@ And then invoke the push with Vagrant:
|
||||||
```shell
|
```shell
|
||||||
$ vagrant push
|
$ vagrant push
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Script Arguments
|
||||||
|
|
||||||
|
Refer to [Shell Provisioner](/v2/provisioning/shell.html).
|
||||||
|
|
Loading…
Reference in New Issue