diff --git a/lib/vagrant/plugin/v2/provisioner.rb b/lib/vagrant/plugin/v2/provisioner.rb index af4975ce9..131c78880 100644 --- a/lib/vagrant/plugin/v2/provisioner.rb +++ b/lib/vagrant/plugin/v2/provisioner.rb @@ -4,45 +4,42 @@ module Vagrant # This is the base class for a provisioner for the V2 API. A provisioner # is primarily responsible for installing software on a Vagrant guest. class Provisioner - # The environment which provisioner is running in. This is the - # action environment, not a Vagrant::Environment. - attr_reader :env - - # The configuration for this provisioner. This will be an instance of - # the `Config` class which is part of the provisioner. + attr_reader :machine attr_reader :config - def initialize(env, config) - @env = env - @config = config - end - - # This method is expected to return a class that is used for - # configuring the provisioner. This return value is expected to be - # a subclass of {Config}. + # Initializes the provisioner with the machine that it will be + # provisioning along with the provisioner configuration (if there + # is any). # - # @return [Config] - def self.config_class + # The provisioner should _not_ do anything at this point except + # initialize internal state. + # + # @param [Machine] machine The machine that this will be provisioning. + # @param [Object] config Provisioner configuration, if one was set. + def initialize(machine, config) + @machine = machine + @config = config end - # This is the method called to "prepare" the provisioner. This is called - # before any actions are run by the action runner (see {Vagrant::Actions::Runner}). - # This can be used to setup shared folders, forward ports, etc. Whatever is - # necessary on a "meta" level. + # Called with the root configuration of the machine so the provisioner + # can add some configuration on top of the machine. + # + # During this step, and this step only, the provisioner should modify + # the root machine configuration to add any additional features it + # may need. Examples include sharing folders, networking, and so on. + # This step is guaranteed to be called before any of those steps are + # done so the provisioner may do that. # # No return value is expected. - def prepare + def configure(root_config) end - # This is the method called to provision the system. This method - # is expected to do whatever necessary to provision the system (create files, - # SSH, etc.) - def provision! - end - - # This is the method called to when the system is being destroyed - # and allows the provisioners to engage in any cleanup tasks necessary. - def cleanup + # This is the method called when the actual provisioning should be + # done. The communicator is guaranteed to be ready at this point, + # and any shared folders or networks are already setup. + # + # No return value is expected. + def provision end end end diff --git a/plugins/provisioners/shell/config.rb b/plugins/provisioners/shell/config.rb new file mode 100644 index 000000000..ef5d10a3e --- /dev/null +++ b/plugins/provisioners/shell/config.rb @@ -0,0 +1,42 @@ +module VagrantPlugins + module Shell + class Config < Vagrant.plugin("2", :config) + attr_accessor :inline + attr_accessor :path + attr_accessor :upload_path + attr_accessor :args + + def initialize + @upload_path = "/tmp/vagrant-shell" + end + + def validate(env, errors) + # 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 = Pathname.new(path).expand_path(env.root_path) + if !expanded_path.file? + errors.add(I18n.t("vagrant.provisioners.shell.path_invalid", + :path => expanded_path)) + end + 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 + + # If there are args and its not a string, that is a problem + if args && !args.is_a?(String) + errors.add(I18n.t("vagrant.provisioners.shell.args_not_string")) + end + end + end + end +end diff --git a/plugins/provisioners/shell/plugin.rb b/plugins/provisioners/shell/plugin.rb index b88ec5630..2da0e5320 100644 --- a/plugins/provisioners/shell/plugin.rb +++ b/plugins/provisioners/shell/plugin.rb @@ -9,7 +9,12 @@ module VagrantPlugins shell scripts. DESC - provisioner("shell") do + config(:shell, :provisioner) do + require File.expand_path("../config", __FILE__) + Config + end + + provisioner(:shell) do require File.expand_path("../provisioner", __FILE__) Provisioner end diff --git a/plugins/provisioners/shell/provisioner.rb b/plugins/provisioners/shell/provisioner.rb index c29ac1da6..a1ef9aa04 100644 --- a/plugins/provisioners/shell/provisioner.rb +++ b/plugins/provisioners/shell/provisioner.rb @@ -4,48 +4,32 @@ require "tempfile" module VagrantPlugins module Shell class Provisioner < Vagrant.plugin("2", :provisioner) - class Config < Vagrant.plugin("2", :config) - attr_accessor :inline - attr_accessor :path - attr_accessor :upload_path - attr_accessor :args + def provision + args = "" + args = " #{config.args}" if config.args + command = "chmod +x #{config.upload_path} && #{config.upload_path}#{args}" - def initialize - @upload_path = "/tmp/vagrant-shell" - end + with_script_file do |path| + # Upload the script to the machine + @machine.communicate.tap do |comm| + comm.upload(path.to_s, config.upload_path) - def validate(env, errors) - # 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 + # Execute it with sudo + comm.sudo(command) do |type, data| + if [:stderr, :stdout].include?(type) + # Output the data with the proper color based on the stream. + color = type == :stdout ? :green : :red - # Validate the existence of a script to upload - if path - expanded_path = Pathname.new(path).expand_path(env.root_path) - if !expanded_path.file? - errors.add(I18n.t("vagrant.provisioners.shell.path_invalid", - :path => expanded_path)) + # Note: Be sure to chomp the data to avoid the newlines that the + # Chef outputs. + @machine.env.ui.info(data.chomp, :color => color, :prefix => false) + end end 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 - - # If there are args and its not a string, that is a problem - if args && !args.is_a?(String) - errors.add(I18n.t("vagrant.provisioners.shell.args_not_string")) - end end end - def self.config_class - Config - end + protected # This method yields the path to a script to upload and execute # on the remote server. This method will properly clean up the @@ -53,7 +37,8 @@ module VagrantPlugins def with_script_file if config.path # Just yield the path to that file... - yield Pathname.new(config.path).expand_path(env[:root_path]) + root_path = @machine.env.root_path + yield Pathname.new(config.path).expand_path(root_path) return end @@ -75,31 +60,6 @@ module VagrantPlugins file.unlink end end - - def provision! - args = "" - args = " #{config.args}" if config.args - command = "chmod +x #{config.upload_path} && #{config.upload_path}#{args}" - - with_script_file do |path| - # Upload the script to the machine - env[:machine].communicate.tap do |comm| - comm.upload(path.to_s, config.upload_path) - - # Execute it with sudo - comm.sudo(command) do |type, data| - if [:stderr, :stdout].include?(type) - # Output the data with the proper color based on the stream. - color = type == :stdout ? :green : :red - - # Note: Be sure to chomp the data to avoid the newlines that the - # Chef outputs. - env[:ui].info(data.chomp, :color => color, :prefix => false) - end - end - end - end - end end end end