From 829f64406ecb39c00507fe8fb73af70f333ee79a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 12 Jan 2012 23:07:18 -0800 Subject: [PATCH] Add `attempts` to chef provisioners. [GH-282] --- CHANGELOG.md | 3 +++ lib/vagrant/provisioners/chef.rb | 4 +++- lib/vagrant/provisioners/chef_client.rb | 27 ++++++++++++++++++------- lib/vagrant/provisioners/chef_solo.rb | 27 ++++++++++++++++++------- templates/locales/en.yml | 5 +++++ 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51160820b..4f3a9c3cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,9 @@ `ssh`. [GH-554] - Ubuntu guests will now emit a `vagrant-mounted` upstart event after shared folders are mounted. + - `attempts` is a new option on chef client and chef solo provisioners. This + will run the provisioner multiple times until erroring about failing + convergence. [GH-282] - Removed Thor as a dependency for the command line interfaces. This resulted in general speed increases across all command line commands. - Linux uses `shutdown -h` instead of `halt` to hopefully more consistently diff --git a/lib/vagrant/provisioners/chef.rb b/lib/vagrant/provisioners/chef.rb index dd15f3f7d..933505cf1 100644 --- a/lib/vagrant/provisioners/chef.rb +++ b/lib/vagrant/provisioners/chef.rb @@ -112,11 +112,13 @@ module Vagrant attr_accessor :no_proxy attr_accessor :binary_path attr_accessor :binary_env + attr_accessor :attempts attr_writer :run_list def initialize - @log_level = :info + @attempts = 1 @json = {} + @log_level = :info end # This returns the json that is merged with the defaults and the diff --git a/lib/vagrant/provisioners/chef_client.rb b/lib/vagrant/provisioners/chef_client.rb index 831786470..5b8792752 100644 --- a/lib/vagrant/provisioners/chef_client.rb +++ b/lib/vagrant/provisioners/chef_client.rb @@ -94,15 +94,28 @@ module Vagrant command_env = config.binary_env ? "#{config.binary_env} " : "" command = "#{command_env}#{chef_binary_path("chef-client")} -c #{config.provisioning_path}/client.rb -j #{config.provisioning_path}/dna.json" - env[:ui].info I18n.t("vagrant.provisioners.chef.running_client") - env[:vm].channel.sudo(command) do |type, data| - # Output the data with the proper color based on the stream. - color = type == :stdout ? :green : :red + config.attempts.times do |attempt| + if attempt == 0 + env[:ui].info I18n.t("vagrant.provisioners.chef.running_client") + else + env[:ui].info I18n.t("vagrant.provisioners.chef.running_client_again") + end - # Note: Be sure to chomp the data to avoid the newlines that the - # Chef outputs. - env[:ui].info(data.chomp, :color => color, :prefix => false) + exit_status = env[:vm].channel.sudo(command) do |type, data| + # 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 + + # There is no need to run Chef again if it converges + return if exit_status == 0 end + + # If we reached this point then Chef never converged! Error. + raise ChefError, :no_convergence end def validation_key_path diff --git a/lib/vagrant/provisioners/chef_solo.rb b/lib/vagrant/provisioners/chef_solo.rb index a2ac82d80..e1b5389f6 100644 --- a/lib/vagrant/provisioners/chef_solo.rb +++ b/lib/vagrant/provisioners/chef_solo.rb @@ -145,15 +145,28 @@ module Vagrant command_env = config.binary_env ? "#{config.binary_env} " : "" command = "#{command_env}#{chef_binary_path("chef-solo")} -c #{config.provisioning_path}/solo.rb -j #{config.provisioning_path}/dna.json" - env[:ui].info I18n.t("vagrant.provisioners.chef.running_solo") - env[:vm].channel.sudo(command) do |type, data| - # Output the data with the proper color based on the stream. - color = type == :stdout ? :green : :red + config.attempts.times do |attempt| + if attempt == 0 + env[:ui].info I18n.t("vagrant.provisioners.chef.running_solo") + else + env[:ui].info I18n.t("vagrant.provisioners.chef.running_solo_again") + end - # Note: Be sure to chomp the data to avoid the newlines that the - # Chef outputs. - env[:ui].info(data.chomp, :color => color, :prefix => false) + exit_status = env[:vm].channel.sudo(command, :error_check => false) do |type, data| + # 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 + + # There is no need to run Chef again if it converges + return if exit_status == 0 end + + # If we reached this point then Chef never converged! Error. + raise ChefError, :no_convergence end def verify_shared_folders(folders) diff --git a/templates/locales/en.yml b/templates/locales/en.yml index a80e0d589..73b02b0fe 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -558,7 +558,9 @@ en: upload_validation_key: "Uploading chef client validation key..." upload_encrypted_data_bag_secret_key: "Uploading chef encrypted data bag secret key..." running_client: "Running chef-client..." + running_client_again: "Running chef-client again (failed to converge)..." running_solo: "Running chef-solo..." + running_solo_again: "Running chef-solo again (failed to converge)..." invalid_provisioner: |- Vagrant::Provisioners::Chef is not a valid provisioner! Use ChefSolo or ChefClient instead. @@ -567,6 +569,9 @@ en: This is usually due to configuration changing after already booting the machine. The fix is to run a `vagrant reload` so that the proper shared folders will prepared and mounted on the VM. + no_convergence: |- + Chef never successfully completed! Any errors should be visible in the + output above. Please fix your recipes so that they properly complete. not_detected: |- The `%{binary}` binary appears to not be in the PATH of the guest. This could be because the PATH is not properly setup or perhaps chef is not