diff --git a/CHANGELOG.md b/CHANGELOG.md index ee95c0fc9..343ba4a5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ - SUSE host only networking support. [GH-369] - Show nice error message for invalid HTTP responses for HTTP downloader. [GH-403] + - New `:inline` option for shell provisioner to provide inline + scripts as a string. [GH-395] ## 0.7.6 (July 2, 2011) diff --git a/lib/vagrant/provisioners/shell.rb b/lib/vagrant/provisioners/shell.rb index 9f6c8ce67..97f22453a 100644 --- a/lib/vagrant/provisioners/shell.rb +++ b/lib/vagrant/provisioners/shell.rb @@ -4,10 +4,13 @@ module Vagrant register :shell class Config < Vagrant::Config::Base + attr_accessor :inline attr_accessor :path attr_accessor :upload_path def initialize + @inline = nil + @path = nil @upload_path = "/tmp/vagrant-shell" end @@ -18,31 +21,63 @@ module Vagrant def validate(errors) super - if !path - errors.add(I18n.t("vagrant.provisioners.shell.path_not_set")) - elsif !expanded_path.file? + # Validate that the parameters are properly set + if path && inline + errors.add(I18n.t("vagrant.provisioners.shell.path_and_inline_set")) + elsif !path && !inline + errors.add(I18n.t("vagrant.provisioners.shell.no_path_or_inline")) + end + + # Validate the existence of a script to upload + if path && !expanded_path.file? errors.add(I18n.t("vagrant.provisioners.shell.path_invalid", :path => expanded_path)) end + # There needs to be a path to upload the script to if !upload_path errors.add(I18n.t("vagrant.provisioners.shell.upload_path_not_set")) end end end + # This method yields the path to a script to upload and execute + # on the remote server. This method will properly clean up the + # script file if needed. + def with_script_file + if config.path + # Just yield the path to that file... + yield config.expanded_path + return + end + + # Otherwise we have an inline script, we need to Tempfile it, + # and handle it specially... + file = Tempfile.new('vagrant-shell') + begin + file.write(config.inline) + file.fsync + yield file.path + ensure + file.close + file.unlink + end + end + def provision! commands = ["chmod +x #{config.upload_path}", config.upload_path] - # Upload the script to the VM - vm.ssh.upload!(config.expanded_path.to_s, config.upload_path) + with_script_file do |path| + # Upload the script to the VM + vm.ssh.upload!(path.to_s, config.upload_path) - # Execute it with sudo - vm.ssh.execute do |ssh| - ssh.sudo!(commands) do |ch, type, data| - if type == :exit_status - ssh.check_exit_status(data, commands) - else - env.ui.info(data) + # Execute it with sudo + vm.ssh.execute do |ssh| + ssh.sudo!(commands) do |ch, type, data| + if type == :exit_status + ssh.check_exit_status(data, commands) + else + env.ui.info(data) + end end end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 3beff04ac..2199d3c15 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -512,7 +512,8 @@ en: running_puppetd: "Running Puppet agent..." shell: - path_not_set: "`path` parameter pointing to script file to execute for shell provisioner is required" + path_and_inline_set: "Only one of `path` or `inline` may be set." + no_path_or_inline: "One of `path` or `inline` must be set." path_invalid: "`path` for shell provisioner does not exist on the host system: %{path}" upload_path_not_set: "`upload_path` must be set for the shell provisioner."