Merge pull request #6557 from mitchellh/sethvargo/chef_windows

Allow ChefDK installation, add Windows installer support
This commit is contained in:
Seth Vargo 2015-11-19 15:11:05 -08:00
commit ae35dd6218
15 changed files with 180 additions and 112 deletions

View File

@ -5,11 +5,11 @@ module VagrantPlugins
module Cap module Cap
module Debian module Debian
module ChefInstall 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 update -y -qq")
machine.communicate.sudo("apt-get install -y -qq curl") 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) machine.communicate.sudo(command)
end end
end end

View File

@ -5,13 +5,13 @@ module VagrantPlugins
module Cap module Cap
module OmniOS module OmniOS
module ChefInstall module ChefInstall
def self.chef_install(machine, version, prerelease, download_path) def self.chef_install(machine, project, version, channel, options = {})
su_cmd = machine.config.solaris.suexec_cmd 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) command = Omnibus.sh_command(project, version, channel, options)
machine.communicate.execute(su_cmd + ' ' + command) machine.communicate.execute("#{su} #{command}")
end end
end end
end end

View File

@ -5,14 +5,14 @@ module VagrantPlugins
module Cap module Cap
module Redhat module Redhat
module ChefInstall module ChefInstall
def self.chef_install(machine, version, prerelease, download_path) def self.chef_install(machine, project, version, channel, options = {})
if dnf?(machine) if dnf?(machine)
machine.communicate.sudo("dnf install -y -q curl") machine.communicate.sudo("dnf install -y -q curl")
else else
machine.communicate.sudo("yum install -y -q curl") machine.communicate.sudo("yum install -y -q curl")
end end
command = Omnibus.build_command(version, prerelease, download_path) command = Omnibus.sh_command(project, version, channel, options)
machine.communicate.sudo(command) machine.communicate.sudo(command)
end end

View File

@ -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

View File

@ -50,7 +50,7 @@ module VagrantPlugins
args << " --log_level #{config.log_level}" if config.log_level args << " --log_level #{config.log_level}" if config.log_level
args << " --no-color" if !options[:colored] 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" args << " --force-formatter"
end end

View File

@ -11,6 +11,12 @@ module VagrantPlugins
# @return [String] # @return [String]
attr_accessor :binary_env 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. # Install Chef on the system if it does not exist. Default is true.
# This is a trinary attribute (it can have three values): # This is a trinary attribute (it can have three values):
# #
@ -26,9 +32,11 @@ module VagrantPlugins
# @return [String, Symbol] # @return [String, Symbol]
attr_accessor :log_level attr_accessor :log_level
# Install a prerelease version of Chef. # The channel from which to download Chef. Currently known values are
# @return [true, false] # "current" and "stable", but more may be added in the future. The
attr_accessor :prerelease # default is "current".
# @return [String]
attr_accessor :channel
# The version of Chef to install. If Chef is already installed on the # The version of Chef to install. If Chef is already installed on the
# system, the installed version is compared with the requested version. # system, the installed version is compared with the requested version.
@ -52,25 +60,38 @@ module VagrantPlugins
# @return [String] # @return [String]
attr_accessor :installer_download_path 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 def initialize
super super
@binary_path = UNSET_VALUE @binary_path = UNSET_VALUE
@binary_env = UNSET_VALUE @binary_env = UNSET_VALUE
@product = UNSET_VALUE
@install = UNSET_VALUE @install = UNSET_VALUE
@log_level = UNSET_VALUE @log_level = UNSET_VALUE
@prerelease = UNSET_VALUE @channel = UNSET_VALUE
@version = UNSET_VALUE @version = UNSET_VALUE
@installer_download_path = UNSET_VALUE @installer_download_path = UNSET_VALUE
end end
def finalize! def finalize!
@binary_path = nil if @binary_path == UNSET_VALUE @binary_path = nil if @binary_path == UNSET_VALUE
@binary_env = nil if @binary_env == UNSET_VALUE @binary_env = nil if @binary_env == UNSET_VALUE
@install = true if @install == UNSET_VALUE @product = "chef" if @product == UNSET_VALUE
@log_level = :info if @log_level == UNSET_VALUE @install = true if @install == UNSET_VALUE
@prerelease = false if @prerelease == UNSET_VALUE @log_level = :info if @log_level == UNSET_VALUE
@version = :latest if @version == UNSET_VALUE @channel = "current" if @channel == UNSET_VALUE
@version = :latest if @version == UNSET_VALUE
@installer_download_path = nil if @installer_download_path == 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 # Make sure the install is a symbol if it's not a boolean

View File

@ -61,12 +61,6 @@ module VagrantPlugins
@run_list = [] @run_list = []
end 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! def finalize!
super super

View File

@ -3,10 +3,11 @@ module VagrantPlugins
class Installer class Installer
def initialize(machine, options = {}) def initialize(machine, options = {})
@machine = machine @machine = machine
@version = options.fetch(:version, :latest) @product = options.fetch(:product)
@prerelease = options.fetch(:prerelease, :latest) @channel = options.fetch(:channel)
@force = options.fetch(:force, false) @version = options.fetch(:version)
@download_path = options.fetch(:download_path, nil) @force = options.fetch(:force)
@options = options.dup
end end
# This handles verifying the Chef installation, installing it if it was # 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", @machine.ui.detail(I18n.t("vagrant.chef_installing",
version: @version.to_s)) 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) if !@machine.guest.capability(:chef_installed, @version)
raise Provisioner::Base::ChefError, :install_failed raise Provisioner::Base::ChefError, :install_failed

View File

@ -1,32 +1,39 @@
module VagrantPlugins module VagrantPlugins
module Chef module Chef
# Read more about the Omnibus installer here:
#
# https://docs.chef.io/install_omnibus.html
#
module Omnibus module Omnibus
OMNITRUCK = "https://www.chef.io/chef/install.sh".freeze OMNITRUCK = "https://omnitruck.chef.io".freeze
# Read more about the Omnibus installer here: def sh_command(project, version, channel, options = {})
# https://docs.getchef.com/install_omnibus.html command = "curl -sL #{OMNITRUCK}/install.sh | sudo bash"
def build_command(version, prerelease = false, download_path = nil) command << " -s -- -P \"#{project}\" -c \"#{channel}\""
command = "curl -sL #{OMNITRUCK} | sudo bash"
if prerelease || version != :latest || download_path != nil
command << " -s --"
end
if prerelease
command << " -p"
end
if version != :latest if version != :latest
command << " -v \"#{version}\"" command << " -v \"#{version}\""
end end
if download_path if options[:download_path]
command << " -d \"#{download_path}\"" command << " -d \"#{options[:download_path]}\""
end end
command command
end 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 end
end end

View File

@ -53,29 +53,14 @@ module VagrantPlugins
Provisioner::ChefZero Provisioner::ChefZero
end 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 guest_capability(:debian, :chef_install) do
require_relative "cap/debian/chef_install" require_relative "cap/debian/chef_install"
Cap::Debian::ChefInstall Cap::Debian::ChefInstall
end end
guest_capability(:redhat, :chef_install) do guest_capability(:linux, :chef_installed) do
require_relative "cap/redhat/chef_install" require_relative "cap/linux/chef_installed"
Cap::Redhat::ChefInstall Cap::Linux::ChefInstalled
end
guest_capability(:omnios, :chef_installed) do
require_relative "cap/omnios/chef_installed"
Cap::OmniOS::ChefInstalled
end end
guest_capability(:omnios, :chef_install) do guest_capability(:omnios, :chef_install) do
@ -83,6 +68,25 @@ module VagrantPlugins
Cap::OmniOS::ChefInstall Cap::OmniOS::ChefInstall
end 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 end
end end

View File

@ -42,9 +42,10 @@ module VagrantPlugins
@logger.info("Checking for Chef installation...") @logger.info("Checking for Chef installation...")
installer = Installer.new(@machine, installer = Installer.new(@machine,
force: config.install == :force, product: config.product,
version: config.version, channel: config.channel,
prerelease: config.prerelease, version: config.version,
force: config.install == :force,
download_path: config.installer_download_path download_path: config.installer_download_path
) )
installer.ensure_installed installer.ensure_installed

View File

@ -145,7 +145,20 @@ module VagrantPlugins
command = "knife #{deletable} delete #{node_name}" command = "knife #{deletable} delete #{node_name}"
command << " --config '#{guest_client_rb_path}'" command << " --config '#{guest_client_rb_path}'"
command << " --yes" 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 end
end end

View File

@ -23,6 +23,13 @@ describe VagrantPlugins::Chef::Config::Base do
end end
end end
describe "#product" do
it "defaults to \"chef\"" do
subject.finalize!
expect(subject.product).to eq("chef")
end
end
describe "#install" do describe "#install" do
it "defaults to true" do it "defaults to true" do
subject.finalize! subject.finalize!
@ -49,10 +56,18 @@ describe VagrantPlugins::Chef::Config::Base do
end end
end end
describe "#prerelease" do describe "#channel" do
it "defaults to true" do it "defaults to \"current\"" do
subject.finalize! 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
end end

View File

@ -3,53 +3,44 @@ require_relative "../../../base"
require Vagrant.source_root.join("plugins/provisioners/chef/omnibus") require Vagrant.source_root.join("plugins/provisioners/chef/omnibus")
describe VagrantPlugins::Chef::Omnibus do 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 } it "includes the channel" do
let(:prerelease) { false } command = described_class.sh_command("chef", nil, "stable")
let(:download_path) { nil } 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 it "includes the download path" do
let(:prerelease) { true } command = described_class.sh_command("chef", "1.2.3", "stable",
download_path: "/some/path",
it "returns the correct command" do )
expect(build_command).to eq("#{prefix} | sudo bash -s -- -p") expect(command).to include %|-d "/some/path"|
end end
end end
context "when download_path is given" do describe "#ps_command" do
let(:download_path) { '/tmp/path/to/omnibuses' } it "includes the project name" do
command = described_class.ps_command("chef", nil, "stable")
it "returns the correct command" do expect(command).to include %|-project 'chef'|
expect(build_command).to eq("#{prefix} | sudo bash -s -- -d \"/tmp/path/to/omnibuses\"")
end end
end
context "when version is :latest" do it "includes the channel" do
let(:version) { :latest } command = described_class.ps_command("chef", nil, "stable")
expect(command).to include %|-channel 'stable'|
it "returns the correct command" do
expect(build_command).to eq("#{prefix} | sudo bash")
end end
end
context "when version is a string" do it "includes the version" do
let(:version) { "1.2.3" } command = described_class.ps_command("chef", "1.2.3", "stable")
expect(command).to include %|-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\"")
end end
end end
end end

View File

@ -30,13 +30,18 @@ their purpose.
- `installer_download_path` (string) - The path where the Chef installer will be - `installer_download_path` (string) - The path where the Chef installer will be
downloaded to. This option is only honored if the `install` attribute is 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 `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 - `log_level` (string) - The Chef log level. See the Chef docs for acceptable
values. values.
- `prerelease` (boolean) - Install a prerelease version of Chef. The default - `product` (string) - The name of the Chef product to install. The default
value is false. 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 - `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 already installed on the system, the installed version is compared with the