From 609ff9f7b299050eb0378642975760752979a98a Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Thu, 19 Nov 2015 14:55:46 -0800 Subject: [PATCH 1/5] Allow provisioner cleanup task to exit on failure --- .../provisioners/chef/provisioner/chef_client.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/provisioners/chef/provisioner/chef_client.rb b/plugins/provisioners/chef/provisioner/chef_client.rb index d5168efa8..e876703d5 100644 --- a/plugins/provisioners/chef/provisioner/chef_client.rb +++ b/plugins/provisioners/chef/provisioner/chef_client.rb @@ -145,7 +145,20 @@ module VagrantPlugins command = "knife #{deletable} delete #{node_name}" command << " --config '#{guest_client_rb_path}'" command << " --yes" - @machine.communicate.sudo(command, error_check: true) + + output = [] + result = @machine.communicate.sudo(command, error_check: false) do |_, data| + output << data + end + + if result != 0 + @machine.ui.error("There were errors removing the #{deletable} from the Chef Server:") + @machine.ui.error("") + @machine.ui.error(output.join("\n")) + @machine.ui.error("") + @machine.ui.error("Vagrant will continue destroying the virtual machine, but you may need") + @machine.ui.error("to manually delete the #{deletable} from the Chef Server!") + end end end end From 2dbd24129fad65a899e590d696f49ca8fa8b96df Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Thu, 19 Nov 2015 14:56:03 -0800 Subject: [PATCH 2/5] Remove deprecated method --- plugins/provisioners/chef/config/base_runner.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/provisioners/chef/config/base_runner.rb b/plugins/provisioners/chef/config/base_runner.rb index cfee8e76e..e7bc6cb07 100644 --- a/plugins/provisioners/chef/config/base_runner.rb +++ b/plugins/provisioners/chef/config/base_runner.rb @@ -61,12 +61,6 @@ module VagrantPlugins @run_list = [] end - def encrypted_data_bag_secret=(value) - puts "DEPRECATION: Chef encrypted_data_bag_secret has no effect anymore." - puts "Remove this from your Vagrantfile since it'll be removed in the next" - puts "Vagrant version." - end - def finalize! super From 43ef92762814b8574376991f480f3d8d16b024f6 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Thu, 19 Nov 2015 14:56:18 -0800 Subject: [PATCH 3/5] Latest will have the formatter option --- plugins/provisioners/chef/command_builder.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/provisioners/chef/command_builder.rb b/plugins/provisioners/chef/command_builder.rb index 8a97facc7..4138ae84f 100644 --- a/plugins/provisioners/chef/command_builder.rb +++ b/plugins/provisioners/chef/command_builder.rb @@ -50,7 +50,7 @@ module VagrantPlugins args << " --log_level #{config.log_level}" if config.log_level args << " --no-color" if !options[:colored] - if config.install && config.version >= "11.0" + if config.install && (config.version == :latest || config.version >= "11.0") args << " --force-formatter" end From a90e6cfe4c64eab13b3d9350c935e603254113a4 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Thu, 19 Nov 2015 14:57:01 -0800 Subject: [PATCH 4/5] Use the new Chef installation channel and options This deprecates "prerelease", which will be removed in the next release. --- .../chef/cap/debian/chef_install.rb | 4 +- .../chef/cap/omnios/chef_install.rb | 10 ++--- .../chef/cap/redhat/chef_install.rb | 4 +- plugins/provisioners/chef/config/base.rb | 41 ++++++++++++++----- plugins/provisioners/chef/installer.rb | 11 ++--- plugins/provisioners/chef/provisioner/base.rb | 7 ++-- .../provisioners/chef/config/base_test.rb | 21 ++++++++-- .../v2/provisioning/chef_common.html.md | 11 +++-- 8 files changed, 76 insertions(+), 33 deletions(-) diff --git a/plugins/provisioners/chef/cap/debian/chef_install.rb b/plugins/provisioners/chef/cap/debian/chef_install.rb index 3d9302d80..e1cf9470d 100644 --- a/plugins/provisioners/chef/cap/debian/chef_install.rb +++ b/plugins/provisioners/chef/cap/debian/chef_install.rb @@ -5,11 +5,11 @@ module VagrantPlugins module Cap module Debian module ChefInstall - def self.chef_install(machine, version, prerelease, download_path) + def self.chef_install(machine, project, version, channel, options = {}) machine.communicate.sudo("apt-get update -y -qq") machine.communicate.sudo("apt-get install -y -qq curl") - command = Omnibus.build_command(version, prerelease, download_path) + command = Omnibus.sh_command(project, version, channel, options) machine.communicate.sudo(command) end end diff --git a/plugins/provisioners/chef/cap/omnios/chef_install.rb b/plugins/provisioners/chef/cap/omnios/chef_install.rb index b20332638..034b2ff5a 100644 --- a/plugins/provisioners/chef/cap/omnios/chef_install.rb +++ b/plugins/provisioners/chef/cap/omnios/chef_install.rb @@ -5,13 +5,13 @@ module VagrantPlugins module Cap module OmniOS module ChefInstall - def self.chef_install(machine, version, prerelease, download_path) - su_cmd = machine.config.solaris.suexec_cmd + def self.chef_install(machine, project, version, channel, options = {}) + su = machine.config.solaris.suexec_cmd - machine.communicate.execute("#{su_cmd} pkg list --no-refresh web/curl > /dev/null 2>&1 || pkg install -q --accept web/curl") + machine.communicate.execute("#{su} pkg list --no-refresh web/curl > /dev/null 2>&1 || pkg install -q --accept web/curl") - command = VagrantPlugins::Chef::Omnibus.build_command(version, prerelease, download_path) - machine.communicate.execute(su_cmd + ' ' + command) + command = Omnibus.sh_command(project, version, channel, options) + machine.communicate.execute("#{su} #{command}") end end end diff --git a/plugins/provisioners/chef/cap/redhat/chef_install.rb b/plugins/provisioners/chef/cap/redhat/chef_install.rb index 7d376e7d0..f91356d13 100644 --- a/plugins/provisioners/chef/cap/redhat/chef_install.rb +++ b/plugins/provisioners/chef/cap/redhat/chef_install.rb @@ -5,14 +5,14 @@ module VagrantPlugins module Cap module Redhat module ChefInstall - def self.chef_install(machine, version, prerelease, download_path) + def self.chef_install(machine, project, version, channel, options = {}) if dnf?(machine) machine.communicate.sudo("dnf install -y -q curl") else machine.communicate.sudo("yum install -y -q curl") end - command = Omnibus.build_command(version, prerelease, download_path) + command = Omnibus.sh_command(project, version, channel, options) machine.communicate.sudo(command) end diff --git a/plugins/provisioners/chef/config/base.rb b/plugins/provisioners/chef/config/base.rb index 370736fd6..2c46198e9 100644 --- a/plugins/provisioners/chef/config/base.rb +++ b/plugins/provisioners/chef/config/base.rb @@ -11,6 +11,12 @@ module VagrantPlugins # @return [String] attr_accessor :binary_env + # The name of the Chef project to install. This is "chef" for the Chef + # Client or "chefdk" for the Chef Development Kit. Other product names + # may be available as well. + # @return [String] + attr_accessor :product + # Install Chef on the system if it does not exist. Default is true. # This is a trinary attribute (it can have three values): # @@ -26,9 +32,11 @@ module VagrantPlugins # @return [String, Symbol] attr_accessor :log_level - # Install a prerelease version of Chef. - # @return [true, false] - attr_accessor :prerelease + # The channel from which to download Chef. Currently known values are + # "current" and "stable", but more may be added in the future. The + # default is "current". + # @return [String] + attr_accessor :channel # The version of Chef to install. If Chef is already installed on the # system, the installed version is compared with the requested version. @@ -52,25 +60,38 @@ module VagrantPlugins # @return [String] attr_accessor :installer_download_path + # @deprecated + def prerelease=(value) + STDOUT.puts <<-EOH +[DEPRECATED] The configuration `chef.prerelease' has been deprecated. Please use +`chef.channel' instead. The default value for channel is "current", which +includes prelease versions of Chef Client and the Chef Development Kit. You can +probably just remove the `prerelease' setting from your Vagrantfile and things +will continue working as expected. +EOH + end + def initialize super @binary_path = UNSET_VALUE @binary_env = UNSET_VALUE + @product = UNSET_VALUE @install = UNSET_VALUE @log_level = UNSET_VALUE - @prerelease = UNSET_VALUE + @channel = UNSET_VALUE @version = UNSET_VALUE @installer_download_path = UNSET_VALUE end def finalize! - @binary_path = nil if @binary_path == UNSET_VALUE - @binary_env = nil if @binary_env == UNSET_VALUE - @install = true if @install == UNSET_VALUE - @log_level = :info if @log_level == UNSET_VALUE - @prerelease = false if @prerelease == UNSET_VALUE - @version = :latest if @version == UNSET_VALUE + @binary_path = nil if @binary_path == UNSET_VALUE + @binary_env = nil if @binary_env == UNSET_VALUE + @product = "chef" if @product == UNSET_VALUE + @install = true if @install == UNSET_VALUE + @log_level = :info if @log_level == UNSET_VALUE + @channel = "current" if @channel == UNSET_VALUE + @version = :latest if @version == UNSET_VALUE @installer_download_path = nil if @installer_download_path == UNSET_VALUE # Make sure the install is a symbol if it's not a boolean diff --git a/plugins/provisioners/chef/installer.rb b/plugins/provisioners/chef/installer.rb index 16467111c..3dc5efadc 100644 --- a/plugins/provisioners/chef/installer.rb +++ b/plugins/provisioners/chef/installer.rb @@ -3,10 +3,11 @@ module VagrantPlugins class Installer def initialize(machine, options = {}) @machine = machine - @version = options.fetch(:version, :latest) - @prerelease = options.fetch(:prerelease, :latest) - @force = options.fetch(:force, false) - @download_path = options.fetch(:download_path, nil) + @product = options.fetch(:product) + @channel = options.fetch(:channel) + @version = options.fetch(:version) + @force = options.fetch(:force) + @options = options.dup end # This handles verifying the Chef installation, installing it if it was @@ -28,7 +29,7 @@ module VagrantPlugins @machine.ui.detail(I18n.t("vagrant.chef_installing", version: @version.to_s)) - @machine.guest.capability(:chef_install, @version, @prerelease, @download_path) + @machine.guest.capability(:chef_install, @product, @version, @channel, @options) if !@machine.guest.capability(:chef_installed, @version) raise Provisioner::Base::ChefError, :install_failed diff --git a/plugins/provisioners/chef/provisioner/base.rb b/plugins/provisioners/chef/provisioner/base.rb index 525e98a9e..4f3636ae2 100644 --- a/plugins/provisioners/chef/provisioner/base.rb +++ b/plugins/provisioners/chef/provisioner/base.rb @@ -42,9 +42,10 @@ module VagrantPlugins @logger.info("Checking for Chef installation...") installer = Installer.new(@machine, - force: config.install == :force, - version: config.version, - prerelease: config.prerelease, + product: config.product, + channel: config.channel, + version: config.version, + force: config.install == :force, download_path: config.installer_download_path ) installer.ensure_installed diff --git a/test/unit/plugins/provisioners/chef/config/base_test.rb b/test/unit/plugins/provisioners/chef/config/base_test.rb index 4b018f11b..4c1a31321 100644 --- a/test/unit/plugins/provisioners/chef/config/base_test.rb +++ b/test/unit/plugins/provisioners/chef/config/base_test.rb @@ -23,6 +23,13 @@ describe VagrantPlugins::Chef::Config::Base do end end + describe "#product" do + it "defaults to \"chef\"" do + subject.finalize! + expect(subject.product).to eq("chef") + end + end + describe "#install" do it "defaults to true" do subject.finalize! @@ -49,10 +56,18 @@ describe VagrantPlugins::Chef::Config::Base do end end - describe "#prerelease" do - it "defaults to true" do + describe "#channel" do + it "defaults to \"current\"" do subject.finalize! - expect(subject.prerelease).to be(false) + expect(subject.channel).to eq("current") + end + end + + describe "#prerelease" do + it "should not exist in Vagrant 1.9" do + if Vagrant::VERSION >= "1.9" + raise "This option should be removed!" + end end end diff --git a/website/docs/source/v2/provisioning/chef_common.html.md b/website/docs/source/v2/provisioning/chef_common.html.md index b5347d522..48d3f12cf 100644 --- a/website/docs/source/v2/provisioning/chef_common.html.md +++ b/website/docs/source/v2/provisioning/chef_common.html.md @@ -30,13 +30,18 @@ their purpose. - `installer_download_path` (string) - The path where the Chef installer will be downloaded to. This option is only honored if the `install` attribute is `true` or `"force"`. The default value is to use the path provided by Chef's - Omnibus installer, which varies between releases. + Omnibus installer, which varies between releases. This value has no effect on + Windows because Chef's omnibus installer lacks the option on Windows. - `log_level` (string) - The Chef log level. See the Chef docs for acceptable values. -- `prerelease` (boolean) - Install a prerelease version of Chef. The default - value is false. +- `product` (string) - The name of the Chef product to install. The default + value is "chef", which corresponds to the Chef Client. You can also specify + "chefdk", which will install the Chef Development Kit. + +- `channel` (string) - The release channel from which to pull the Chef Client + or the Chef Development Kit. The default value is `"current"`. - `version` (string) - The version of Chef to install on the guest. If Chef is already installed on the system, the installed version is compared with the From c30467a6f981c1ad28f54c848b0307676d4d5224 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Thu, 19 Nov 2015 15:01:09 -0800 Subject: [PATCH 5/5] Allow Chef to install on Windows --- .../chef/cap/windows/chef_install.rb | 16 +++++ plugins/provisioners/chef/omnibus.rb | 39 ++++++----- plugins/provisioners/chef/plugin.rb | 40 +++++++----- .../plugins/provisioners/chef/omnibus_test.rb | 65 ++++++++----------- 4 files changed, 89 insertions(+), 71 deletions(-) create mode 100644 plugins/provisioners/chef/cap/windows/chef_install.rb diff --git a/plugins/provisioners/chef/cap/windows/chef_install.rb b/plugins/provisioners/chef/cap/windows/chef_install.rb new file mode 100644 index 000000000..f1f2317a6 --- /dev/null +++ b/plugins/provisioners/chef/cap/windows/chef_install.rb @@ -0,0 +1,16 @@ +require_relative "../../omnibus" + +module VagrantPlugins + module Chef + module Cap + module Windows + module ChefInstall + def self.chef_install(machine, project, version, channel, options = {}) + command = Omnibus.ps_command(project, version, channel, options) + machine.communicate.sudo(command) + end + end + end + end + end +end diff --git a/plugins/provisioners/chef/omnibus.rb b/plugins/provisioners/chef/omnibus.rb index 5c2eef2fb..897e5282d 100644 --- a/plugins/provisioners/chef/omnibus.rb +++ b/plugins/provisioners/chef/omnibus.rb @@ -1,32 +1,39 @@ module VagrantPlugins module Chef + # Read more about the Omnibus installer here: + # + # https://docs.chef.io/install_omnibus.html + # module Omnibus - OMNITRUCK = "https://www.chef.io/chef/install.sh".freeze + OMNITRUCK = "https://omnitruck.chef.io".freeze - # Read more about the Omnibus installer here: - # https://docs.getchef.com/install_omnibus.html - def build_command(version, prerelease = false, download_path = nil) - command = "curl -sL #{OMNITRUCK} | sudo bash" - - if prerelease || version != :latest || download_path != nil - command << " -s --" - end - - if prerelease - command << " -p" - end + def sh_command(project, version, channel, options = {}) + command = "curl -sL #{OMNITRUCK}/install.sh | sudo bash" + command << " -s -- -P \"#{project}\" -c \"#{channel}\"" if version != :latest command << " -v \"#{version}\"" end - if download_path - command << " -d \"#{download_path}\"" + if options[:download_path] + command << " -d \"#{options[:download_path]}\"" end command end - module_function :build_command + module_function :sh_command + + def ps_command(project, version, channel, options = {}) + command = ". { iwr -useb #{OMNITRUCK}/install.ps1 } | iex; install" + command << " -project '#{project}' -channel '#{channel}'" + + if version != :latest + command << " -version '#{version}'" + end + + command + end + module_function :ps_command end end end diff --git a/plugins/provisioners/chef/plugin.rb b/plugins/provisioners/chef/plugin.rb index 540429fad..f7af36138 100644 --- a/plugins/provisioners/chef/plugin.rb +++ b/plugins/provisioners/chef/plugin.rb @@ -53,29 +53,14 @@ module VagrantPlugins Provisioner::ChefZero end - guest_capability(:linux, :chef_installed) do - require_relative "cap/linux/chef_installed" - Cap::Linux::ChefInstalled - end - - guest_capability(:windows, :chef_installed) do - require_relative "cap/windows/chef_installed" - Cap::Windows::ChefInstalled - end - guest_capability(:debian, :chef_install) do require_relative "cap/debian/chef_install" Cap::Debian::ChefInstall end - guest_capability(:redhat, :chef_install) do - require_relative "cap/redhat/chef_install" - Cap::Redhat::ChefInstall - end - - guest_capability(:omnios, :chef_installed) do - require_relative "cap/omnios/chef_installed" - Cap::OmniOS::ChefInstalled + guest_capability(:linux, :chef_installed) do + require_relative "cap/linux/chef_installed" + Cap::Linux::ChefInstalled end guest_capability(:omnios, :chef_install) do @@ -83,6 +68,25 @@ module VagrantPlugins Cap::OmniOS::ChefInstall end + guest_capability(:omnios, :chef_installed) do + require_relative "cap/omnios/chef_installed" + Cap::OmniOS::ChefInstalled + end + + guest_capability(:redhat, :chef_install) do + require_relative "cap/redhat/chef_install" + Cap::Redhat::ChefInstall + end + + guest_capability(:windows, :chef_install) do + require_relative "cap/windows/chef_install" + Cap::Windows::ChefInstall + end + + guest_capability(:windows, :chef_installed) do + require_relative "cap/windows/chef_installed" + Cap::Windows::ChefInstalled + end end end end diff --git a/test/unit/plugins/provisioners/chef/omnibus_test.rb b/test/unit/plugins/provisioners/chef/omnibus_test.rb index b053f94bc..5e8c4aaea 100644 --- a/test/unit/plugins/provisioners/chef/omnibus_test.rb +++ b/test/unit/plugins/provisioners/chef/omnibus_test.rb @@ -3,53 +3,44 @@ require_relative "../../../base" require Vagrant.source_root.join("plugins/provisioners/chef/omnibus") describe VagrantPlugins::Chef::Omnibus do - let(:prefix) { "curl -sL #{described_class.const_get(:OMNITRUCK)}" } + describe "#sh_command" do + it "includes the project name" do + command = described_class.sh_command("chef", nil, "stable") + expect(command).to include %|-P "chef"| + end - let(:version) { :latest } - let(:prerelease) { false } - let(:download_path) { nil } + it "includes the channel" do + command = described_class.sh_command("chef", nil, "stable") + expect(command).to include %|-c "stable"| + end - let(:build_command) { described_class.build_command(version, prerelease, download_path) } + it "includes the version" do + command = described_class.sh_command("chef", "1.2.3", "stable") + expect(command).to include %|-v "1.2.3"| + end - context "when prerelease is given" do - let(:prerelease) { true } - - it "returns the correct command" do - expect(build_command).to eq("#{prefix} | sudo bash -s -- -p") + it "includes the download path" do + command = described_class.sh_command("chef", "1.2.3", "stable", + download_path: "/some/path", + ) + expect(command).to include %|-d "/some/path"| end end - context "when download_path is given" do - let(:download_path) { '/tmp/path/to/omnibuses' } - - it "returns the correct command" do - expect(build_command).to eq("#{prefix} | sudo bash -s -- -d \"/tmp/path/to/omnibuses\"") + describe "#ps_command" do + it "includes the project name" do + command = described_class.ps_command("chef", nil, "stable") + expect(command).to include %|-project 'chef'| end - end - context "when version is :latest" do - let(:version) { :latest } - - it "returns the correct command" do - expect(build_command).to eq("#{prefix} | sudo bash") + it "includes the channel" do + command = described_class.ps_command("chef", nil, "stable") + expect(command).to include %|-channel 'stable'| end - end - context "when version is a string" do - let(:version) { "1.2.3" } - - it "returns the correct command" do - expect(build_command).to eq("#{prefix} | sudo bash -s -- -v \"1.2.3\"") - end - end - - context "when prerelease and version and download_path are given" do - let(:version) { "1.2.3" } - let(:prerelease) { true } - let(:download_path) { "/some/path" } - - it "returns the correct command" do - expect(build_command).to eq("#{prefix} | sudo bash -s -- -p -v \"1.2.3\" -d \"/some/path\"") + it "includes the version" do + command = described_class.ps_command("chef", "1.2.3", "stable") + expect(command).to include %|-version '1.2.3'| end end end