diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c804d4bb..a4f320aa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,61 @@ -## 1.2.2 (unreleased) +## 1.2.3 (unreleased) + +FEATURES: + + - Puppet provisioner now supports Hiera by specifying a `hiera_config_path`. + - Added a `working_directory` configuration option to the Puppet apply + provisioner so you can specify the working directory when `puppet` is + called, making it friendly to Hiera data and such. [GH-1670] + +IMPROVEMENTS: + + - Setting hostnames works properly on OmniOS. [GH-1672] + - Better VBoxManage error detection on Windows systems. This avoids + some major issues where Vagrant would sometimes "lose" your VM. [GH-1669] + - Better detection of missing VirtualBox kernel drivers on Linux + systems. [GH-1671] + - More precise detection of Ubuntu/Debian guests so that running Vagrant + within an LXC container works properly now. + - Allow strings in addition to symbols to more places in V1 configuration + as well as V2 configuration. + +BUG FIXES: + + - Ignore "guest not ready" errors when attempting to graceful halt and + carry on checks whether the halt succeeded. [GH-1679] + - Handle the case where a roles path for Chef solo isn't properly + defined. [GH-1665] + - Finding V1 boxes now works properly again to avoid "box not found" + errors. [GH-1691] + +## 1.2.2 (April 23, 2013) + +FEATURES: + + - New `DestroyConfirm` built-in middleware for providers so they can + more easily conform to the `destroy` action. + +IMPROVEMENTS: + + - No longer an error if the Chef run list is empty. It is now + a warning. [GH-1620] + - Better locking around handling the `box_url` parameter for + parallel providers. + - Solaris guest is now properly detected on SmartOS, OmniOS, etc. [GH-1639] + - Guest addition version detection is more robust, attempting other + routes to get the version, and also retrying a few times. [GH-1575] BUG FIXES: - `vagrant package --base` works again. [GH-1615] + - Box overrides specified in provider config overrides no longer + fail to detect the box. [GH-1617] + - In a multi-machine environment, a box not found won't be downloaded + multiple times. [GH-1467] + - `vagrant box add` with a file path now works correctly on Windows + when a drive letter is specified. + - DOS line endings are converted to Unix line endings for the + shell provisioner automatically. [GH-1495] ## 1.2.1 (April 17, 2013) @@ -36,6 +89,8 @@ BACKWARDS INCOMPATIBILITIES: To work around this, either set `VAGRANT_HOME` to your Cygwin ".vagrant.d" folder or move your ".vagrant.d" folder to `USERPROFILE`. The latter is recommended for long-term support. + - The constant `Vagrant::Environment::VAGRANT_HOME` was removed in favor of + `Vagrant::Environment#default_vagrant_home`. FEATURES: diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index b6ebe3066..74b55ac6a 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -12,6 +12,7 @@ module Vagrant autoload :Call, "vagrant/action/builtin/call" autoload :Confirm, "vagrant/action/builtin/confirm" autoload :ConfigValidate, "vagrant/action/builtin/config_validate" + autoload :DestroyConfirm, "vagrant/action/builtin/destroy_confirm" autoload :EnvSet, "vagrant/action/builtin/env_set" autoload :GracefulHalt, "vagrant/action/builtin/graceful_halt" autoload :HandleBoxUrl, "vagrant/action/builtin/handle_box_url" diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index 020a90eac..f0813092f 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -19,8 +19,8 @@ module Vagrant @logger.info("Downloading box to: #{@temp_path}") url = env[:box_url] - if url !~ /^[a-z0-9]+:.*$/i - @logger.info("No protocol found on box URL, assuming file:") + if File.file?(url) || url !~ /^[a-z0-9]+:.*$/i + @logger.info("URL is a file or protocol not found and assuming file.") file_path = File.expand_path(url) file_path = Util::Platform.cygwin_windows_path(file_path) url = "file:#{file_path}" diff --git a/lib/vagrant/action/builtin/destroy_confirm.rb b/lib/vagrant/action/builtin/destroy_confirm.rb new file mode 100644 index 000000000..2e76737c6 --- /dev/null +++ b/lib/vagrant/action/builtin/destroy_confirm.rb @@ -0,0 +1,21 @@ +require_relative "confirm" + +module Vagrant + module Action + module Builtin + # This class asks the user to confirm the destruction of a machine + # that Vagrant manages. This is provided as a built-in on top of + # {Confirm} because it sets up the proper keys and such so that + # `vagrant destroy -f` works properly. + class DestroyConfirm < Confirm + def initialize(app, env) + force_key = :force_confirm_destroy + message = I18n.t("vagrant.commands.destroy.confirmation", + :name => env[:machine].name) + + super(app, env, message, force_key) + end + end + end + end +end diff --git a/lib/vagrant/action/builtin/graceful_halt.rb b/lib/vagrant/action/builtin/graceful_halt.rb index da1235551..fc218a94c 100644 --- a/lib/vagrant/action/builtin/graceful_halt.rb +++ b/lib/vagrant/action/builtin/graceful_halt.rb @@ -44,7 +44,12 @@ module Vagrant # checked above. if graceful env[:ui].info I18n.t("vagrant.actions.vm.halt.graceful") - env[:machine].guest.capability(:halt) + + begin + env[:machine].guest.capability(:halt) + rescue Errors::MachineGuestNotReady + @logger.info("Machine guest not ready while attempting to halt. Ignoring.") + end @logger.debug("Waiting for target graceful halt state: #{@target_state}") count = 0 diff --git a/lib/vagrant/action/builtin/handle_box_url.rb b/lib/vagrant/action/builtin/handle_box_url.rb index d6e99a74d..7cbac6570 100644 --- a/lib/vagrant/action/builtin/handle_box_url.rb +++ b/lib/vagrant/action/builtin/handle_box_url.rb @@ -1,3 +1,5 @@ +require "thread" + module Vagrant module Action module Builtin @@ -6,29 +8,61 @@ module Vagrant # sequence for a provider after configuration validation but before # you attempt to use any box. class HandleBoxUrl + @@big_lock = Mutex.new + @@handle_box_url_locks = Hash.new { |h,k| h[k] = Mutex.new } + def initialize(app, env) @app = app end def call(env) if !env[:machine].box + # Get a "big lock" to make sure that our more fine grained + # lock access is thread safe. + lock = nil + @@big_lock.synchronize do + lock = @@handle_box_url_locks[env[:machine].config.vm.box] + end + # We can assume a box URL is set because the Vagrantfile # validation should do this for us. If not, though, we do # raise a terrible runtime error. box_name = env[:machine].config.vm.box box_url = env[:machine].config.vm.box_url - # Add the box then reload the box collection so that it becomes - # aware of it. - env[:ui].info I18n.t( - "vagrant.actions.vm.check_box.not_found", - :name => box_name, - :provider => env[:machine].provider_name) - env[:action_runner].run(Vagrant::Action.action_box_add, { - :box_name => box_name, - :box_provider => env[:machine].provider_name, - :box_url => box_url - }) + lock.synchronize do + # First see if we actually have the box now. + has_box = false + + formats = env[:machine].provider_options[:box_format] || + env[:machine].provider_name + [formats].flatten.each do |format| + if env[:box_collection].find(box_name, format) + has_box = true + break + end + end + + if !has_box + # Add the box then reload the box collection so that it becomes + # aware of it. + env[:ui].info I18n.t( + "vagrant.actions.vm.check_box.not_found", + :name => box_name, + :provider => env[:machine].provider_name) + + begin + env[:action_runner].run(Vagrant::Action.action_box_add, { + :box_name => box_name, + :box_provider => env[:machine].provider_name, + :box_url => box_url + }) + rescue Errors::BoxAlreadyExists + # Just ignore this, since it means the next part will succeed! + # This can happen in a multi-threaded environment. + end + end + end # Reload the environment and set the VM to be the new loaded VM. env[:machine] = env[:machine].env.machine( diff --git a/lib/vagrant/box_collection.rb b/lib/vagrant/box_collection.rb index c467cbe32..6b30411cf 100644 --- a/lib/vagrant/box_collection.rb +++ b/lib/vagrant/box_collection.rb @@ -1,4 +1,5 @@ require "digest/sha1" +require "thread" require "tmpdir" require "log4r" @@ -43,6 +44,7 @@ module Vagrant options ||= {} @directory = directory + @lock = Mutex.new @temp_root = options[:temp_dir_root] @logger = Log4r::Logger.new("vagrant::box_collection") end @@ -69,97 +71,99 @@ module Vagrant # @param [Boolean] force If true, any existing box with the same name # and provider will be replaced. def add(path, name, provider=nil, force=false) - # A helper to check if a box exists. We store this in a variable - # since we call it multiple times. - check_box_exists = lambda do |box_provider| - box = find(name, box_provider) - next if !box + with_collection_lock do + # A helper to check if a box exists. We store this in a variable + # since we call it multiple times. + check_box_exists = lambda do |box_provider| + box = find(name, box_provider) + next if !box - if !force - @logger.error("Box already exists, can't add: #{name} #{box_provider}") - raise Errors::BoxAlreadyExists, :name => name, :provider => box_provider + if !force + @logger.error("Box already exists, can't add: #{name} #{box_provider}") + raise Errors::BoxAlreadyExists, :name => name, :provider => box_provider + end + + # We're forcing, so just delete the old box + @logger.info("Box already exists, but forcing so removing: #{name} #{box_provider}") + box.destroy! end - # We're forcing, so just delete the old box - @logger.info("Box already exists, but forcing so removing: #{name} #{box_provider}") - box.destroy! - end + log_provider = provider ? provider : "any provider" + @logger.debug("Adding box: #{name} (#{log_provider}) from #{path}") - log_provider = provider ? provider : "any provider" - @logger.debug("Adding box: #{name} (#{log_provider}) from #{path}") + # Verify the box doesn't exist early if we're given a provider. This + # can potentially speed things up considerably since we don't need + # to unpack any files. + check_box_exists.call(provider) if provider - # Verify the box doesn't exist early if we're given a provider. This - # can potentially speed things up considerably since we don't need - # to unpack any files. - check_box_exists.call(provider) if provider + # Verify that a V1 box doesn't exist. If it does, then we signal + # to the user that we need an upgrade. + raise Errors::BoxUpgradeRequired, :name => name if v1_box?(@directory.join(name)) - # Verify that a V1 box doesn't exist. If it does, then we signal - # to the user that we need an upgrade. - raise Errors::BoxUpgradeRequired, :name => name if v1_box?(@directory.join(name)) + # Create a temporary directory since we're not sure at this point if + # the box we're unpackaging already exists (if no provider was given) + with_temp_dir do |temp_dir| + # Extract the box into a temporary directory. + @logger.debug("Unpacking box into temporary directory: #{temp_dir}") + result = Util::Subprocess.execute( + "bsdtar", "-v", "-x", "-m", "-C", temp_dir.to_s, "-f", path.to_s) + raise Errors::BoxUnpackageFailure, :output => result.stderr.to_s if result.exit_code != 0 - # Create a temporary directory since we're not sure at this point if - # the box we're unpackaging already exists (if no provider was given) - with_temp_dir do |temp_dir| - # Extract the box into a temporary directory. - @logger.debug("Unpacking box into temporary directory: #{temp_dir}") - result = Util::Subprocess.execute( - "bsdtar", "-v", "-x", "-m", "-C", temp_dir.to_s, "-f", path.to_s) - raise Errors::BoxUnpackageFailure, :output => result.stderr.to_s if result.exit_code != 0 + # If we get a V1 box, we want to update it in place + if v1_box?(temp_dir) + @logger.debug("Added box is a V1 box. Upgrading in place.") + temp_dir = v1_upgrade(temp_dir) + end - # If we get a V1 box, we want to update it in place - if v1_box?(temp_dir) - @logger.debug("Added box is a V1 box. Upgrading in place.") - temp_dir = v1_upgrade(temp_dir) - end + # We re-wrap ourselves in the safety net in case we upgraded. + # If we didn't upgrade, then this is still safe because the + # helper will only delete the directory if it exists + with_temp_dir(temp_dir) do |final_temp_dir| + # Get an instance of the box we just added before it is finalized + # in the system so we can inspect and use its metadata. + box = Box.new(name, provider, final_temp_dir) - # We re-wrap ourselves in the safety net in case we upgraded. - # If we didn't upgrade, then this is still safe because the - # helper will only delete the directory if it exists - with_temp_dir(temp_dir) do |final_temp_dir| - # Get an instance of the box we just added before it is finalized - # in the system so we can inspect and use its metadata. - box = Box.new(name, provider, final_temp_dir) + # Get the provider, since we'll need that to at the least add it + # to the system or check that it matches what is given to us. + box_provider = box.metadata["provider"] - # Get the provider, since we'll need that to at the least add it - # to the system or check that it matches what is given to us. - box_provider = box.metadata["provider"] + if provider + # Verify that the given provider matches what the box has. + if box_provider.to_sym != provider + @logger.error("Added box provider doesnt match expected: #{box_provider}") + raise Errors::BoxProviderDoesntMatch, :expected => provider, :actual => box_provider + end + else + # We weren't given a provider, so store this one. + provider = box_provider.to_sym - if provider - # Verify that the given provider matches what the box has. - if box_provider.to_sym != provider - @logger.error("Added box provider doesnt match expected: #{box_provider}") - raise Errors::BoxProviderDoesntMatch, :expected => provider, :actual => box_provider + # Verify the box doesn't already exist + check_box_exists.call(provider) end - else - # We weren't given a provider, so store this one. - provider = box_provider.to_sym - # Verify the box doesn't already exist - check_box_exists.call(provider) - end + # Create the directory for this box, not including the provider + box_dir = @directory.join(name) + box_dir.mkpath + @logger.debug("Box directory: #{box_dir}") - # Create the directory for this box, not including the provider - box_dir = @directory.join(name) - box_dir.mkpath - @logger.debug("Box directory: #{box_dir}") + # This is the final directory we'll move it to + final_dir = box_dir.join(provider.to_s) + if final_dir.exist? + @logger.debug("Removing existing provider directory...") + final_dir.rmtree + end - # This is the final directory we'll move it to - final_dir = box_dir.join(provider.to_s) - if final_dir.exist? - @logger.debug("Removing existing provider directory...") - final_dir.rmtree - end + # Move to final destination + final_dir.mkpath - # Move to final destination - final_dir.mkpath - - # Go through each child and copy them one-by-one. This avoids - # an issue where on Windows cross-device directory copies are - # failing for some reason. [GH-1424] - final_temp_dir.children(true).each do |f| - destination = final_dir.join(f.basename) - @logger.debug("Moving: #{f} => #{destination}") - FileUtils.mv(f, destination) + # Go through each child and copy them one-by-one. This avoids + # an issue where on Windows cross-device directory copies are + # failing for some reason. [GH-1424] + final_temp_dir.children(true).each do |f| + destination = final_dir.join(f.basename) + @logger.debug("Moving: #{f} => #{destination}") + FileUtils.mv(f, destination) + end end end end @@ -177,33 +181,35 @@ module Vagrant def all results = [] - @logger.debug("Finding all boxes in: #{@directory}") - @directory.children(true).each do |child| - # Ignore non-directories, since files are not interesting to - # us in our folder structure. - next if !child.directory? + with_collection_lock do + @logger.debug("Finding all boxes in: #{@directory}") + @directory.children(true).each do |child| + # Ignore non-directories, since files are not interesting to + # us in our folder structure. + next if !child.directory? - box_name = child.basename.to_s + box_name = child.basename.to_s - # If this is a V1 box, we still return that name, but specify - # that the box is a V1 box. - if v1_box?(child) - @logger.debug("V1 box found: #{box_name}") - results << [box_name, :virtualbox, :v1] - next - end + # If this is a V1 box, we still return that name, but specify + # that the box is a V1 box. + if v1_box?(child) + @logger.debug("V1 box found: #{box_name}") + results << [box_name, :virtualbox, :v1] + next + end - # Otherwise, traverse the subdirectories and see what providers - # we have. - child.children(true).each do |provider| - # Verify this is a potentially valid box. If it looks - # correct enough then include it. - if provider.directory? && provider.join("metadata.json").file? - provider_name = provider.basename.to_s.to_sym - @logger.debug("Box: #{box_name} (#{provider_name})") - results << [box_name, provider_name] - else - @logger.debug("Invalid box, ignoring: #{provider}") + # Otherwise, traverse the subdirectories and see what providers + # we have. + child.children(true).each do |provider| + # Verify this is a potentially valid box. If it looks + # correct enough then include it. + if provider.directory? && provider.join("metadata.json").file? + provider_name = provider.basename.to_s.to_sym + @logger.debug("Box: #{box_name} (#{provider_name})") + results << [box_name, provider_name] + else + @logger.debug("Invalid box, ignoring: #{provider}") + end end end end @@ -217,29 +223,31 @@ module Vagrant # @Param [String] provider Provider that the box implements. # @return [Box] The box found, or `nil` if not found. def find(name, provider) - # First look directly for the box we're asking for. - box_directory = @directory.join(name, provider.to_s, "metadata.json") - @logger.info("Searching for box: #{name} (#{provider}) in #{box_directory}") - if box_directory.file? - @logger.info("Box found: #{name} (#{provider})") - return Box.new(name, provider, box_directory.dirname) - end + with_collection_lock do + # First look directly for the box we're asking for. + box_directory = @directory.join(name, provider.to_s, "metadata.json") + @logger.info("Searching for box: #{name} (#{provider}) in #{box_directory}") + if box_directory.file? + @logger.info("Box found: #{name} (#{provider})") + return Box.new(name, provider, box_directory.dirname) + end - # If we're looking for a VirtualBox box, then we check if there is - # a V1 box. - if provider == :virtualbox - # Check if a V1 version of this box exists, and if so, raise an - # exception notifying the caller that the box exists but needs - # to be upgraded. We don't do the upgrade here because it can be - # a fairly intensive activity and don't want to immediately degrade - # user performance on a find. - # - # To determine if it is a V1 box we just do a simple heuristic - # based approach. - @logger.info("Searching for V1 box: #{name}") - if v1_box?(@directory.join(name)) - @logger.warn("V1 box found: #{name}") - raise Errors::BoxUpgradeRequired, :name => name + # If we're looking for a VirtualBox box, then we check if there is + # a V1 box. + if provider.to_sym == :virtualbox + # Check if a V1 version of this box exists, and if so, raise an + # exception notifying the caller that the box exists but needs + # to be upgraded. We don't do the upgrade here because it can be + # a fairly intensive activity and don't want to immediately degrade + # user performance on a find. + # + # To determine if it is a V1 box we just do a simple heuristic + # based approach. + @logger.info("Searching for V1 box: #{name}") + if v1_box?(@directory.join(name)) + @logger.warn("V1 box found: #{name}") + raise Errors::BoxUpgradeRequired, :name => name + end end end @@ -255,21 +263,23 @@ module Vagrant # # @return [Boolean] `true` otherwise an exception is raised. def upgrade(name) - @logger.debug("Upgrade request for box: #{name}") - box_dir = @directory.join(name) + with_collection_lock do + @logger.debug("Upgrade request for box: #{name}") + box_dir = @directory.join(name) - # If the box doesn't exist at all, raise an exception - raise Errors::BoxNotFound, :name => name if !box_dir.directory? + # If the box doesn't exist at all, raise an exception + raise Errors::BoxNotFound, :name => name if !box_dir.directory? - if v1_box?(box_dir) - @logger.debug("V1 box #{name} found. Upgrading!") + if v1_box?(box_dir) + @logger.debug("V1 box #{name} found. Upgrading!") - # First we actually perform the upgrade - temp_dir = v1_upgrade(box_dir) + # First we actually perform the upgrade + temp_dir = v1_upgrade(box_dir) - # Rename the temporary directory to the provider. - FileUtils.mv(temp_dir.to_s, box_dir.join("virtualbox").to_s) - @logger.info("Box '#{name}' upgraded from V1 to V2.") + # Rename the temporary directory to the provider. + FileUtils.mv(temp_dir.to_s, box_dir.join("virtualbox").to_s) + @logger.info("Box '#{name}' upgraded from V1 to V2.") + end end # We did it! Or the v1 box didn't exist so it doesn't matter. @@ -330,6 +340,24 @@ module Vagrant temp_dir end + # This locks the region given by the block with a lock on this + # collection. + def with_collection_lock + lock = @lock + + begin + lock.synchronize {} + rescue ThreadError + # If we already hold the lock, just create a new lock so + # we definitely don't block and don't get an error. + lock = Mutex.new + end + + lock.synchronize do + return yield + end + end + # This is a helper that makes sure that our temporary directories # are cleaned up no matter what. # diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 1e2b042e4..451cc81ed 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -328,58 +328,65 @@ module Vagrant config, config_warnings, config_errors = \ @config_loader.load([:default, :home, :root, vm_config_key]) + # Determine the possible box formats for any boxes and find the box + box_formats = provider_options[:box_format] || provider box = nil - if config.vm.box - # Determine the box formats we support - formats = provider_options[:box_format] - formats ||= provider - formats = [formats] if !formats.is_a?(Array) - @logger.info("Provider-supported box formats: #{formats.inspect}") - formats.each do |format| - begin - box = boxes.find(config.vm.box, format.to_s) - rescue Errors::BoxUpgradeRequired - # Upgrade the box if we must - @logger.info("Upgrading box during config load: #{config.vm.box}") - boxes.upgrade(config.vm.box) - retry - end + # Set this variable in order to keep track of if the box changes + # too many times. + original_box = config.vm.box + box_changed = false - # If a box was found, we exit - if box - @logger.info("Box found with format: #{format}") - break + load_box_and_overrides = lambda do + box = find_box(config.vm.box, box_formats) if config.vm.box + + # If a box was found, then we attempt to load the Vagrantfile for + # that box. We don't require a box since we allow providers to download + # boxes and so on. + if box + box_vagrantfile = find_vagrantfile(box.directory) + if box_vagrantfile + # The box has a custom Vagrantfile, so we load that into the config + # as well. + @logger.info("Box exists with Vagrantfile. Reloading machine config.") + box_config_key = "box_#{box.name}_#{box.provider}".to_sym + @config_loader.set(box_config_key, box_vagrantfile) + config, config_warnings, config_errors = \ + @config_loader.load([:default, box_config_key, :home, :root, vm_config_key]) end end - end - # If a box was found, then we attempt to load the Vagrantfile for - # that box. We don't require a box since we allow providers to download - # boxes and so on. - if box - box_vagrantfile = find_vagrantfile(box.directory) - if box_vagrantfile - # The box has a custom Vagrantfile, so we load that into the config - # as well. - @logger.info("Box exists with Vagrantfile. Reloading machine config.") - box_config_key = "box_#{box.name}_#{box.provider}".to_sym - @config_loader.set(box_config_key, box_vagrantfile) + # If there are provider overrides for the machine, then we run + # those as well. + provider_overrides = config.vm.get_provider_overrides(provider) + if provider_overrides.length > 0 + @logger.info("Applying #{provider_overrides.length} provider overrides. Reloading config.") + provider_override_key = "vm_#{name}_#{config.vm.box}_#{provider}".to_sym + @config_loader.set(provider_override_key, provider_overrides) config, config_warnings, config_errors = \ - @config_loader.load([:default, box_config_key, :home, :root, vm_config_key]) + @config_loader.load([:default, box_config_key, :home, :root, vm_config_key, provider_override_key]) + end + + if config.vm.box && original_box != config.vm.box + if box_changed + # We already changed boxes once, so report an error that a + # box is attempting to change boxes again. + raise Errors::BoxConfigChangingBox + end + + # The box changed, probably due to the provider override. Let's + # run the configuration one more time with the new box. + @logger.info("Box changed to: #{config.vm.box}. Reloading configurations.") + original_box = config.vm.box + box_changed = true + + # Recurse so that we reload all the configurations + load_box_and_overrides.call end end - # If there are provider overrides for the machine, then we run - # those as well. - provider_overrides = config.vm.get_provider_overrides(provider) - if provider_overrides.length > 0 - @logger.info("Applying #{provider_overrides.length} provider overrides. Reloading config.") - provider_override_key = "vm_#{name}_#{config.vm.box}_#{provider}".to_sym - @config_loader.set(provider_override_key, provider_overrides) - config, config_warnings, config_errors = \ - @config_loader.load([:default, box_config_key, :home, :root, vm_config_key, provider_override_key]) - end + # Load the box and overrides configuration + load_box_and_overrides.call # Get the provider configuration from the final loaded configuration provider_config = config.vm.get_provider_config(provider) @@ -398,11 +405,11 @@ module Vagrant "config/messages", :warnings => config_warnings, :errors => config_errors).chomp - @ui.send(level, I18n.t("vagrant.general.config_upgrade_messages", - :output => output)) + @ui.send(level, I18n.t("vagrant.general.config_upgrade_messages", + :output => output)) - # If we had errors, then we bail - raise Errors::ConfigUpgradeErrors if !config_errors.empty? + # If we had errors, then we bail + raise Errors::ConfigUpgradeErrors if !config_errors.empty? end # Create the machine and cache it for future calls. This will also @@ -686,6 +693,39 @@ module Vagrant Pathname.new(path) end + # This finds a box for the given name and formats, or returns nil + # if the box isn't found. + # + # @param [String] name Name of the box + # @param [Array] formats The formats to search for the box. + # @return [Box] + def find_box(name, formats) + # Determine the box formats we support + formats = [formats] if !formats.is_a?(Array) + + @logger.info("Provider-supported box formats: #{formats.inspect}") + formats.each do |format| + box = nil + + begin + box = boxes.find(name, format.to_s) + rescue Errors::BoxUpgradeRequired + # Upgrade the box if we must + @logger.info("Upgrading box during config load: #{name}") + boxes.upgrade(name) + retry + end + + # If a box was found, we exit + if box + @logger.info("Box found with format: #{format}") + return box + end + end + + nil + end + # Finds the Vagrantfile in the given directory. # # @param [Pathname] path Path to search in. @@ -797,7 +837,7 @@ module Vagrant # Upgrade complete! Let the user know @ui.info(I18n.t("vagrant.general.upgraded_v1_dotfile", - :backup_path => backup_file.to_s)) + :backup_path => backup_file.to_s)) end end end diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 1fbfd4c3f..1377464bb 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -103,6 +103,10 @@ module Vagrant error_key(:already_exists, "vagrant.actions.box.unpackage") end + class BoxConfigChangingBox < VagrantError + error_key(:box_config_changing_box) + end + class BoxMetadataFileNotFound < VagrantError error_key(:box_metadata_file_not_found) end diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index 6bb8a4286..632dcf9a5 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -193,6 +193,8 @@ module Vagrant # # @param [String] value The ID. def id=(value) + @logger.info("New machine ID: #{value.inspect}") + # The file that will store the id if we have one. This allows the # ID to persist across Vagrant runs. id_file = @data_dir.join("id") diff --git a/lib/vagrant/version.rb b/lib/vagrant/version.rb index 67453e086..142f9d08d 100644 --- a/lib/vagrant/version.rb +++ b/lib/vagrant/version.rb @@ -2,5 +2,5 @@ module Vagrant # This will always be up to date with the current version of Vagrant, # since it is used to generate the gemspec and is also the source of # the version for `vagrant -v` - VERSION = "1.2.2.dev" + VERSION = "1.2.3.dev" end diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 8223d5a4b..00c058155 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -194,7 +194,12 @@ module VagrantPlugins :verbose => :debug }) - @logger.info("Attempting to connect to SSH: #{ssh_info[:host]}:#{ssh_info[:port]}") + @logger.info("Attempting to connect to SSH...") + @logger.info(" - Host: #{ssh_info[:host]}") + @logger.info(" - Port: #{ssh_info[:port]}") + @logger.info(" - Username: #{ssh_info[:username]}") + @logger.info(" - Key Path: #{ssh_info[:private_key_path]}") + Net::SSH.start(ssh_info[:host], ssh_info[:username], connect_opts) ensure # Make sure we output the connection log diff --git a/plugins/guests/debian/guest.rb b/plugins/guests/debian/guest.rb index ec6b6a9a1..a7f3d65de 100644 --- a/plugins/guests/debian/guest.rb +++ b/plugins/guests/debian/guest.rb @@ -2,7 +2,7 @@ module VagrantPlugins module GuestDebian class Guest < Vagrant.plugin("2", :guest) def detect?(machine) - machine.communicate.test("cat /proc/version | grep 'Debian'") + machine.communicate.test("cat /etc/issue | grep 'Debian'") end end end diff --git a/plugins/guests/omnios/cap/change_host_name.rb b/plugins/guests/omnios/cap/change_host_name.rb new file mode 100644 index 000000000..13f70f304 --- /dev/null +++ b/plugins/guests/omnios/cap/change_host_name.rb @@ -0,0 +1,17 @@ +module VagrantPlugins + module GuestOmniOS + module Cap + class ChangeHostName + def self.change_host_name(machine, name) + su_cmd = machine.config.solaris.suexec_cmd + + # Only do this if the hostname is not already set + if !machine.communicate.test("#{su_cmd} hostname | grep '#{name}'") + machine.communicate.execute("#{su_cmd} sh -c \"echo '#{name}' > /etc/nodename\"") + machine.communicate.execute("#{su_cmd} hostname #{name}") + end + end + end + end + end +end diff --git a/plugins/guests/omnios/guest.rb b/plugins/guests/omnios/guest.rb new file mode 100644 index 000000000..7474b020b --- /dev/null +++ b/plugins/guests/omnios/guest.rb @@ -0,0 +1,11 @@ +require "vagrant" + +module VagrantPlugins + module GuestOmniOS + class Guest < Vagrant.plugin("2", :guest) + def detect?(machine) + machine.communicate.test("cat /etc/release | grep -i OmniOS") + end + end + end +end diff --git a/plugins/guests/omnios/plugin.rb b/plugins/guests/omnios/plugin.rb new file mode 100644 index 000000000..929132cf8 --- /dev/null +++ b/plugins/guests/omnios/plugin.rb @@ -0,0 +1,20 @@ +require "vagrant" + +module VagrantPlugins + module GuestOmniOS + class Plugin < Vagrant.plugin("2") + name "OmniOS guest." + description "OmniOS guest support." + + guest("omnios", "solaris") do + require File.expand_path("../guest", __FILE__) + Guest + end + + guest_capability("omnios", "change_host_name") do + require_relative "cap/change_host_name" + Cap::ChangeHostName + end + end + end +end diff --git a/plugins/guests/solaris/guest.rb b/plugins/guests/solaris/guest.rb index 06b2ae375..e0eab6709 100644 --- a/plugins/guests/solaris/guest.rb +++ b/plugins/guests/solaris/guest.rb @@ -7,7 +7,7 @@ module VagrantPlugins # Contributed by Blake Irvin class Guest < Vagrant.plugin("2", :guest) def detect?(machine) - machine.communicate.test("grep 'Solaris' /etc/release") + machine.communicate.test("uname -o | grep Solaris") end end end diff --git a/plugins/guests/ubuntu/guest.rb b/plugins/guests/ubuntu/guest.rb index 35e3d30c9..ce6ab801a 100644 --- a/plugins/guests/ubuntu/guest.rb +++ b/plugins/guests/ubuntu/guest.rb @@ -6,7 +6,7 @@ module VagrantPlugins module GuestUbuntu class Guest < VagrantPlugins::GuestDebian::Guest def detect?(machine) - machine.communicate.test("cat /proc/version | grep 'Ubuntu'") + machine.communicate.test("cat /etc/issue | grep 'Ubuntu'") end def mount_shared_folder(name, guestpath, options) diff --git a/plugins/kernel_v1/config/vm.rb b/plugins/kernel_v1/config/vm.rb index 21a4c10dd..239afa219 100644 --- a/plugins/kernel_v1/config/vm.rb +++ b/plugins/kernel_v1/config/vm.rb @@ -53,6 +53,9 @@ module VagrantPlugins end def network(type, *args) + # Convert to symbol so we can allow most anything... + type = type.to_sym if type + if type == :hostonly @networks << [:private_network, args] elsif type == :bridged @@ -110,8 +113,8 @@ module VagrantPlugins # VirtualBox provider on the new VM. if !self.customizations.empty? warnings << "`config.vm.customize` calls are VirtualBox-specific. If you're\n" + - "using any other provider, you'll have to find provider-specific configuration\n" + - "to translate to manually in your Vagrantfile." + "using any other provider, you'll have to use config.vm.provider in a\n" + + "v2 configuration block." new.vm.provider :virtualbox do |vb| self.customizations.each do |customization| diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index 96f25e6c2..89f70b5c5 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -31,12 +31,12 @@ module VagrantPlugins # Internal state @__compiled_provider_configs = {} - @__compiled_provider_overrides = {} @__defined_vm_keys = [] @__defined_vms = {} @__finalized = false @__networks = {} @__providers = {} + @__provider_overrides = {} @__synced_folders = {} end @@ -80,6 +80,14 @@ module VagrantPlugins new_providers[key] += blocks end + # Merge the provider overrides by appending them... + other_overrides = other.instance_variable_get(:@__provider_overrides) + new_overrides = @__provider_overrides.dup + other_overrides.each do |key, blocks| + new_overrides[key] ||= [] + new_overrides[key] += blocks + end + # Merge synced folders. other_folders = other.instance_variable_get(:@__synced_folders) new_folders = @__synced_folders.dup @@ -91,6 +99,7 @@ module VagrantPlugins result.instance_variable_set(:@__defined_vm_keys, new_defined_vm_keys) result.instance_variable_set(:@__defined_vms, new_defined_vms) result.instance_variable_set(:@__providers, new_providers) + result.instance_variable_set(:@__provider_overrides, new_overrides) result.instance_variable_set(:@__synced_folders, new_folders) end end @@ -165,7 +174,17 @@ module VagrantPlugins def provider(name, &block) name = name.to_sym @__providers[name] ||= [] - @__providers[name] << block if block_given? + @__provider_overrides[name] ||= [] + + if block_given? + @__providers[name] << block if block_given? + + # If this block takes two arguments, then we curry it and store + # the configuration override for use later. + if block.arity == 2 + @__provider_overrides[name] << block.curry[Vagrant::Config::V2::DummyConfig.new] + end + end end def provision(name, options=nil, &block) @@ -223,23 +242,15 @@ module VagrantPlugins # Load it up config = config_class.new - overrides = [] blocks.each do |b| b.call(config, Vagrant::Config::V2::DummyConfig.new) - - # If the block takes two arguments, then we store the second - # one away for overrides later. - if b.arity == 2 - overrides << b.curry[Vagrant::Config::V2::DummyConfig.new] - end end config.finalize! # Store it for retrieval later @__compiled_provider_configs[name] = config - @__compiled_provider_overrides[name] = overrides end # Flag that we finalized @@ -274,7 +285,7 @@ module VagrantPlugins # @param [Symbol] name Name of the provider # @return [Array] def get_provider_overrides(name) - (@__compiled_provider_overrides[name] || []).map do |p| + (@__provider_overrides[name] || []).map do |p| ["2", p] end end diff --git a/plugins/providers/virtualbox/action.rb b/plugins/providers/virtualbox/action.rb index c83bc9b01..513583d4e 100644 --- a/plugins/providers/virtualbox/action.rb +++ b/plugins/providers/virtualbox/action.rb @@ -16,7 +16,6 @@ module VagrantPlugins autoload :Created, File.expand_path("../action/created", __FILE__) autoload :Customize, File.expand_path("../action/customize", __FILE__) autoload :Destroy, File.expand_path("../action/destroy", __FILE__) - autoload :DestroyConfirm, File.expand_path("../action/destroy_confirm", __FILE__) autoload :DestroyUnusedNetworkInterfaces, File.expand_path("../action/destroy_unused_network_interfaces", __FILE__) autoload :DiscardState, File.expand_path("../action/discard_state", __FILE__) autoload :Export, File.expand_path("../action/export", __FILE__) diff --git a/plugins/providers/virtualbox/action/destroy_confirm.rb b/plugins/providers/virtualbox/action/destroy_confirm.rb deleted file mode 100644 index 062450680..000000000 --- a/plugins/providers/virtualbox/action/destroy_confirm.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "vagrant/action/builtin/confirm" - -module VagrantPlugins - module ProviderVirtualBox - module Action - class DestroyConfirm < Vagrant::Action::Builtin::Confirm - def initialize(app, env) - force_key = :force_confirm_destroy - message = I18n.t("vagrant.commands.destroy.confirmation", - :name => env[:machine].name) - - super(app, env, message, force_key) - end - end - end - end -end diff --git a/plugins/providers/virtualbox/driver/base.rb b/plugins/providers/virtualbox/driver/base.rb index 8ec8ed194..5e9f9afb2 100644 --- a/plugins/providers/virtualbox/driver/base.rb +++ b/plugins/providers/virtualbox/driver/base.rb @@ -303,7 +303,16 @@ module VagrantPlugins # Sometimes, VBoxManage fails but doesn't actual return a non-zero # exit code. For this we inspect the output and determine if an error # occurred. - if r.stderr =~ /VBoxManage: error:/ + + if r.stderr =~ /failed to open \/dev\/vboxnetctl/i + # This catches an error message that only shows when kernel + # drivers aren't properly installed. + @logger.error("Error message about unable to open vboxnetctl") + raise Vagrant::Errors::VirtualBoxKernelModuleNotLoaded + end + + if r.stderr =~ /VBoxManage([.a-z]+?): error:/ + # This catches the generic VBoxManage error case. @logger.info("VBoxManage error text found, assuming error.") errored = true end diff --git a/plugins/providers/virtualbox/driver/version_4_2.rb b/plugins/providers/virtualbox/driver/version_4_2.rb index a145a6e69..dded1bc6f 100644 --- a/plugins/providers/virtualbox/driver/version_4_2.rb +++ b/plugins/providers/virtualbox/driver/version_4_2.rb @@ -264,6 +264,13 @@ module VagrantPlugins return value.split("_").first end + # If we can't get the guest additions version by guest property, try + # to get it from the VM info itself. + info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true) + info.split("\n").each do |line| + return $1.to_s if line =~ /^GuestAdditionsVersion="(.+?)"$/ + end + return nil end diff --git a/plugins/provisioners/chef/config/chef_client.rb b/plugins/provisioners/chef/config/chef_client.rb index aa9cff1b3..ad536067d 100644 --- a/plugins/provisioners/chef/config/chef_client.rb +++ b/plugins/provisioners/chef/config/chef_client.rb @@ -34,16 +34,12 @@ module VagrantPlugins @chef_server_url = nil if @chef_server_url == UNSET_VALUE @client_key_path = "/etc/chef/client.pem" if @client_key_path == UNSET_VALUE @encrypted_data_bag_secret_key_path = nil if @encrypted_data_bag_secret_key_path == UNSET_VALUE - @encrypted_data_bag_secret = nil if @encrypted_data_bag_secret == UNSET_VALUE + @encrypted_data_bag_secret = "/tmp/encrypted_data_bag_secret" if @encrypted_data_bag_secret == UNSET_VALUE @environment = nil if @environment == UNSET_VALUE @file_backup_path = "/srv/chef/cache" if @file_backup_path == UNSET_VALUE @file_cache_path = "/srv/chef/file_store" if @file_cache_path == UNSET_VALUE @validation_client_name = "chef-validator" if @validation_client_name == UNSET_VALUE @validation_key_path = nil if @validation_key_path == UNSET_VALUE - - if @encrypted_data_bag_secret == UNSET_VALUE - @encrypted_data_bag_secret = "/tmp/encrypted_data_bag_secret" - end end def validate(machine) @@ -52,8 +48,6 @@ module VagrantPlugins !chef_server_url || chef_server_url.strip == "" errors << I18n.t("vagrant.config.chef.validation_key_path") if \ !validation_key_path - errors << I18n.t("vagrant.config.chef.run_list_empty") if \ - @run_list && @run_list.empty? { "chef client provisioner" => errors } end diff --git a/plugins/provisioners/chef/config/chef_solo.rb b/plugins/provisioners/chef/config/chef_solo.rb index 3d832738d..2268dccb5 100644 --- a/plugins/provisioners/chef/config/chef_solo.rb +++ b/plugins/provisioners/chef/config/chef_solo.rb @@ -61,8 +61,6 @@ module VagrantPlugins errors = _detected_errors errors << I18n.t("vagrant.config.chef.cookbooks_path_empty") if \ !cookbooks_path || [cookbooks_path].flatten.empty? - errors << I18n.t("vagrant.config.chef.run_list_empty") if \ - !run_list || run_list.empty? { "chef solo provisioner" => errors } end diff --git a/plugins/provisioners/chef/provisioner/chef_client.rb b/plugins/provisioners/chef/provisioner/chef_client.rb index 549f5a7f8..d14a6862c 100644 --- a/plugins/provisioners/chef/provisioner/chef_client.rb +++ b/plugins/provisioners/chef/provisioner/chef_client.rb @@ -58,6 +58,10 @@ module VagrantPlugins end def run_chef_client + if @config.run_list && @config.run_list.empty? + @machine.ui.warn(I18n.t("vagrant.chef_run_list_empty")) + end + command_env = @config.binary_env ? "#{@config.binary_env} " : "" command_args = @config.arguments ? " #{@config.arguments}" : "" command = "#{command_env}#{chef_binary_path("chef-client")} -c #{@config.provisioning_path}/client.rb -j #{@config.provisioning_path}/dna.json #{command_args}" diff --git a/plugins/provisioners/chef/provisioner/chef_solo.rb b/plugins/provisioners/chef/provisioner/chef_solo.rb index 584acbae7..c0ce268a0 100644 --- a/plugins/provisioners/chef/provisioner/chef_solo.rb +++ b/plugins/provisioners/chef/provisioner/chef_solo.rb @@ -135,6 +135,10 @@ module VagrantPlugins end def run_chef_solo + if @config.run_list && @config.run_list.empty? + @machine.ui.warn(I18n.t("vagrant.chef_run_list_empty")) + end + command_env = @config.binary_env ? "#{@config.binary_env} " : "" command_args = @config.arguments ? " #{@config.arguments}" : "" command = "#{command_env}#{chef_binary_path("chef-solo")} -c #{@config.provisioning_path}/solo.rb -j #{@config.provisioning_path}/dna.json #{command_args}" diff --git a/plugins/provisioners/puppet/config/puppet.rb b/plugins/provisioners/puppet/config/puppet.rb index 9febf3e0e..c114ad900 100644 --- a/plugins/provisioners/puppet/config/puppet.rb +++ b/plugins/provisioners/puppet/config/puppet.rb @@ -2,18 +2,38 @@ module VagrantPlugins module Puppet module Config class Puppet < Vagrant.plugin("2", :config) + attr_accessor :facter + attr_accessor :hiera_config_path attr_accessor :manifest_file attr_accessor :manifests_path attr_accessor :module_path - attr_accessor :pp_path attr_accessor :options - attr_accessor :facter + attr_accessor :temp_dir + attr_accessor :working_directory - def manifest_file; @manifest_file || "default.pp"; end - def manifests_path; @manifests_path || "manifests"; end - def pp_path; @pp_path || "/tmp/vagrant-puppet"; end - def options; @options ||= []; end - def facter; @facter ||= {}; end + def initialize + super + + @hiera_config_path = UNSET_VALUE + @manifest_file = UNSET_VALUE + @manifests_path = UNSET_VALUE + @module_path = UNSET_VALUE + @options = [] + @facter = {} + @temp_dir = UNSET_VALUE + @working_directory = UNSET_VALUE + end + + def finalize! + super + + @hiera_config_path = nil if @hiera_config_path == UNSET_VALUE + @manifest_file = "default.pp" if @manifest_file == UNSET_VALUE + @manifests_path = "manifests" if @manifests_path == UNSET_VALUE + @module_path = nil if @module_path == UNSET_VALUE + @temp_dir = "/tmp/vagrant-puppet" if @temp_dir == UNSET_VALUE + @working_directory = nil if @working_directory == UNSET_VALUE + end # Returns the manifests path expanded relative to the root path of the # environment. diff --git a/plugins/provisioners/puppet/provisioner/puppet.rb b/plugins/provisioners/puppet/provisioner/puppet.rb index 386ee5263..485abd7bb 100644 --- a/plugins/provisioners/puppet/provisioner/puppet.rb +++ b/plugins/provisioners/puppet/provisioner/puppet.rb @@ -19,12 +19,12 @@ module VagrantPlugins root_path = @machine.env.root_path @expanded_manifests_path = @config.expanded_manifests_path(root_path) @expanded_module_paths = @config.expanded_module_paths(root_path) - @manifest_file = @config.manifest_file + @manifest_file = File.join(manifests_guest_path, @config.manifest_file) # Setup the module paths @module_paths = [] @expanded_module_paths.each_with_index do |path, i| - @module_paths << [path, File.join(config.pp_path, "modules-#{i}")] + @module_paths << [path, File.join(config.temp_dir, "modules-#{i}")] end # Share the manifests directory with the guest @@ -52,11 +52,26 @@ module VagrantPlugins # Verify Puppet is installed and run it verify_binary("puppet") + + # Make sure the temporary directory is properly set up + @machine.communicate.tap do |comm| + comm.sudo("mkdir -p #{config.temp_dir}") + comm.sudo("chmod 0777 #{config.temp_dir}") + end + + # Upload Hiera configuration if we have it + @hiera_config_path = nil + if config.hiera_config_path + local_hiera_path = File.expand_path(config.hiera_config_path, @machine.env.root_path) + @hiera_config_path = File.join(config.temp_dir, "hiera.yaml") + @machine.communicate.upload(local_hiera_path, @hiera_config_path) + end + run_puppet_apply end def manifests_guest_path - File.join(config.pp_path, "manifests") + File.join(config.temp_dir, "manifests") end def verify_binary(binary) @@ -78,6 +93,11 @@ module VagrantPlugins options << "--modulepath '#{module_paths.join(':')}'" end + if @hiera_config_path + options << "--hiera_config=#{@hiera_config_path}" + end + + options << "--detailed-exitcodes" options << @manifest_file options = options.join(" ") @@ -92,10 +112,13 @@ module VagrantPlugins facter = "#{facts.join(" ")} " end - command = "cd #{manifests_guest_path} && #{facter}puppet apply #{options} --detailed-exitcodes || [ $? -eq 2 ]" + command = "#{facter}puppet apply #{options} || [ $? -eq 2 ]" + if config.working_directory + command = "cd #{config.working_directory} && #{command}" + end @machine.env.ui.info I18n.t("vagrant.provisioners.puppet.running_puppet", - :manifest => @manifest_file) + :manifest => config.manifest_file) @machine.communicate.sudo(command) do |type, data| data.chomp! diff --git a/plugins/provisioners/shell/provisioner.rb b/plugins/provisioners/shell/provisioner.rb index af4980830..f62fa1a69 100644 --- a/plugins/provisioners/shell/provisioner.rb +++ b/plugins/provisioners/shell/provisioner.rb @@ -48,13 +48,20 @@ module VagrantPlugins # on the remote server. This method will properly clean up the # script file if needed. def with_script_file + script = nil + if config.path # Just yield the path to that file... root_path = @machine.env.root_path - yield Pathname.new(config.path).expand_path(root_path) - return + script = Pathname.new(config.path).expand_path(root_path).read + else + # The script is just the inline code... + script = config.inline end + # Replace Windows line endings with Unix ones + script.gsub!(/\r\n?$/, "\n") + # Otherwise we have an inline script, we need to Tempfile it, # and handle it specially... file = Tempfile.new('vagrant-shell') @@ -65,7 +72,7 @@ module VagrantPlugins file.binmode begin - file.write(config.inline) + file.write(script) file.fsync file.close yield file.path diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 1500dff59..b5d423b0b 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -25,6 +25,8 @@ en: CFEngine running in "single run" mode. Will execute one file. cfengine_single_run_execute: |- Executing run file for CFEngine... + chef_run_list_empty: |- + Warning: Chef solo run list is empty. This may not be what you want. cfengine_config: classes_array: |- @@ -118,6 +120,11 @@ en: Any errors that occurred are shown below. %{message} + box_config_changing_box: |- + While loading the Vagrantfile, the provider override specified + a new box. This box, in turn, specified a different box. This isn't + allowed, as it could lead to infinite recursion of Vagrant configuration + loading. Please fix this. box_metadata_file_not_found: |- The "metadata.json" file for the box '%{name}' was not found. Boxes require this file in order for Vagrant to determine the @@ -521,8 +528,8 @@ en: %{supported_versions} virtualbox_kernel_module_not_loaded: |- VirtualBox is complaining that the kernel module is not loaded. Please - run `VBoxManage --version` to see the error message which should contain - instructions on how to fix this error. + run `VBoxManage --version` or open the VirtualBox GUI to see the error + message which should contain instructions on how to fix this error. virtualbox_install_incomplete: |- VirtualBox is complaining that the installation is incomplete. Please run `VBoxManage --version` to see the error message which should contain @@ -569,7 +576,6 @@ en: cookbooks_path_empty: "Must specify a cookbooks path for chef solo." cookbooks_path_missing: |- Cookbook path doesn't exist: %{path} - run_list_empty: "Run list must not be empty." server_url_empty: "Chef server URL must be populated." validation_key_path: "Validation key path must be valid path to your chef server validation key." loader: diff --git a/templates/provisioners/chef_solo/solo.erb b/templates/provisioners/chef_solo/solo.erb index 80f8989a9..10a108437 100644 --- a/templates/provisioners/chef_solo/solo.erb +++ b/templates/provisioners/chef_solo/solo.erb @@ -3,7 +3,9 @@ node_name "<%= node_name %>" <% end %> file_cache_path "<%= provisioning_path %>" cookbook_path <%= cookbooks_path.inspect %> +<% if roles_path %> role_path <%= roles_path.inspect %> +<% end %> log_level <%= log_level.inspect %> encrypted_data_bag_secret "<%= encrypted_data_bag_secret %>"