Automatically install Chef when provisioning with Chef
This commit is contained in:
parent
b7c03ddbe2
commit
f232dc38c9
|
@ -0,0 +1,19 @@
|
||||||
|
require_relative "../../omnibus"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module Chef
|
||||||
|
module Cap
|
||||||
|
module Debian
|
||||||
|
module ChefInstall
|
||||||
|
def self.chef_install(machine, version, prerelease)
|
||||||
|
machine.communicate.sudo("apt-get update -y -qq")
|
||||||
|
machine.communicate.sudo("apt-get install -y -qq curl")
|
||||||
|
|
||||||
|
command = Omnibus.build_command(version, prerelease)
|
||||||
|
machine.communicate.sudo(command)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,22 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Chef
|
||||||
|
module Cap
|
||||||
|
module Linux
|
||||||
|
module ChefInstalled
|
||||||
|
# Check if Chef is installed at the given version.
|
||||||
|
# @return [true, false]
|
||||||
|
def self.chef_installed(machine, version)
|
||||||
|
knife = "/opt/chef/bin/knife"
|
||||||
|
command = "test -x #{knife}"
|
||||||
|
|
||||||
|
if version != :latest
|
||||||
|
command << "&& #{knife} --version | grep 'Chef: #{version}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
machine.communicate.test(command, sudo: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,18 @@
|
||||||
|
require_relative "../../omnibus"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module Chef
|
||||||
|
module Cap
|
||||||
|
module Redhat
|
||||||
|
module ChefInstall
|
||||||
|
def self.chef_install(machine, version, prerelease)
|
||||||
|
machine.communicate.sudo("yum install -y -q curl")
|
||||||
|
|
||||||
|
command = Omnibus.build_command(version, prerelease)
|
||||||
|
machine.communicate.sudo(command)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -30,6 +30,10 @@ module VagrantPlugins
|
||||||
# @return [String, Symbol]
|
# @return [String, Symbol]
|
||||||
attr_accessor :log_level
|
attr_accessor :log_level
|
||||||
|
|
||||||
|
# Install a prerelease version of Chef.
|
||||||
|
# @return [true, false]
|
||||||
|
attr_accessor :prerelease
|
||||||
|
|
||||||
# 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.
|
||||||
# If they match, no action is taken. If they do not match, version of
|
# If they match, no action is taken. If they do not match, version of
|
||||||
|
@ -47,19 +51,26 @@ module VagrantPlugins
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
|
|
||||||
@binary_path = UNSET_VALUE
|
@binary_path = UNSET_VALUE
|
||||||
@binary_env = UNSET_VALUE
|
@binary_env = UNSET_VALUE
|
||||||
@install = UNSET_VALUE
|
@install = UNSET_VALUE
|
||||||
@log_level = UNSET_VALUE
|
@log_level = UNSET_VALUE
|
||||||
@version = UNSET_VALUE
|
@prerelease = UNSET_VALUE
|
||||||
|
@version = 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
|
@install = true if @install == UNSET_VALUE
|
||||||
@log_level = :info if @log_level == UNSET_VALUE
|
@log_level = :info if @log_level == UNSET_VALUE
|
||||||
@version = :latest if @version == UNSET_VALUE
|
@prerelease = false if @prerelease == UNSET_VALUE
|
||||||
|
@version = :latest if @version == UNSET_VALUE
|
||||||
|
|
||||||
|
# Make sure the install is a symbol if it's not a boolean
|
||||||
|
if @install.respond_to?(:to_sym)
|
||||||
|
@install = @install.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
# Make sure the version is a symbol if it's not a boolean
|
# Make sure the version is a symbol if it's not a boolean
|
||||||
if @version.respond_to?(:to_sym)
|
if @version.respond_to?(:to_sym)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
require_relative "base"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Chef
|
module Chef
|
||||||
module Config
|
module Config
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Chef
|
||||||
|
class Installer
|
||||||
|
def initialize(machine, options = {})
|
||||||
|
@machine = machine
|
||||||
|
@version = options.fetch(:version, :latest)
|
||||||
|
@prerelease = options.fetch(:prerelease, :latest)
|
||||||
|
@force = options.fetch(:force, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
# This handles verifying the Chef installation, installing it if it was
|
||||||
|
# requested, and so on. This method will raise exceptions if things are
|
||||||
|
# wrong.
|
||||||
|
def ensure_installed
|
||||||
|
# If the guest cannot check if Chef is installed, just exit printing a
|
||||||
|
# warning...
|
||||||
|
if !@machine.guest.capability?(:chef_installed)
|
||||||
|
@machine.ui.warn(I18n.t("vagrant.chef_cant_detect"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if !should_install_chef?
|
||||||
|
@machine.ui.info(I18n.t("vagrant.chef_already_installed",
|
||||||
|
version: @version.to_s))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
@machine.ui.detail(I18n.t("vagrant.chef_installing",
|
||||||
|
version: @version.to_s))
|
||||||
|
@machine.guest.capability(:chef_install, @version, @prerelease)
|
||||||
|
|
||||||
|
if !@machine.guest.capability(:chef_installed, @version)
|
||||||
|
raise Provisioner::Base::ChefError, :install_failed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Determine if Chef should be installed. Chef is installed if the "force"
|
||||||
|
# option is given or if the guest does not have Chef installed at the
|
||||||
|
# proper version.
|
||||||
|
def should_install_chef?
|
||||||
|
@force || !@machine.guest.capability(:chef_installed, @version)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Chef
|
||||||
|
module Omnibus
|
||||||
|
OMNITRUCK = "https://www.getchef.com/chef/install.sh".freeze
|
||||||
|
|
||||||
|
# Read more about the Omnibus installer here:
|
||||||
|
# https://docs.getchef.com/install_omnibus.html
|
||||||
|
def build_command(version, prerelease = false)
|
||||||
|
command = "curl -sL #{OMNITRUCK} | sudo bash"
|
||||||
|
|
||||||
|
if prerelease || version != :latest
|
||||||
|
command << " -s --"
|
||||||
|
end
|
||||||
|
|
||||||
|
if prerelease
|
||||||
|
command << " -p"
|
||||||
|
end
|
||||||
|
|
||||||
|
if version != :latest
|
||||||
|
command << " -v \"#{version}\""
|
||||||
|
end
|
||||||
|
|
||||||
|
command
|
||||||
|
end
|
||||||
|
module_function :build_command
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -52,6 +52,21 @@ module VagrantPlugins
|
||||||
require_relative "provisioner/chef_zero"
|
require_relative "provisioner/chef_zero"
|
||||||
Provisioner::ChefZero
|
Provisioner::ChefZero
|
||||||
end
|
end
|
||||||
|
|
||||||
|
guest_capability(:linux, :chef_installed) do
|
||||||
|
require_relative "cap/linux/chef_installed"
|
||||||
|
Cap::Linux::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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,8 @@ require 'tempfile'
|
||||||
|
|
||||||
require "vagrant/util/template_renderer"
|
require "vagrant/util/template_renderer"
|
||||||
|
|
||||||
|
require_relative "../installer"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Chef
|
module Chef
|
||||||
module Provisioner
|
module Provisioner
|
||||||
|
@ -13,6 +15,24 @@ module VagrantPlugins
|
||||||
error_namespace("vagrant.provisioners.chef")
|
error_namespace("vagrant.provisioners.chef")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def initialize(machine, config)
|
||||||
|
super
|
||||||
|
|
||||||
|
@logger = Log4r::Logger.new("vagrant::provisioners::chef")
|
||||||
|
end
|
||||||
|
|
||||||
|
def install_chef
|
||||||
|
return if !config.install
|
||||||
|
|
||||||
|
@logger.info("Checking for Chef installation...")
|
||||||
|
installer = Installer.new(@machine,
|
||||||
|
force: config.install == :force,
|
||||||
|
version: config.version,
|
||||||
|
prerelease: config.prerelease,
|
||||||
|
)
|
||||||
|
installer.ensure_installed
|
||||||
|
end
|
||||||
|
|
||||||
def verify_binary(binary)
|
def verify_binary(binary)
|
||||||
# Checks for the existence of chef binary and error if it
|
# Checks for the existence of chef binary and error if it
|
||||||
# doesn't exist.
|
# doesn't exist.
|
||||||
|
@ -20,7 +40,8 @@ module VagrantPlugins
|
||||||
"which #{binary}",
|
"which #{binary}",
|
||||||
error_class: ChefError,
|
error_class: ChefError,
|
||||||
error_key: :chef_not_detected,
|
error_key: :chef_not_detected,
|
||||||
binary: binary)
|
binary: binary,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# This returns the command to run Chef for the given client
|
# This returns the command to run Chef for the given client
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
require "tempfile"
|
require "tempfile"
|
||||||
|
|
||||||
|
require_relative "base"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Chef
|
module Chef
|
||||||
module Provisioner
|
module Provisioner
|
||||||
class ChefApply < Vagrant.plugin("2", :provisioner)
|
class ChefApply < Base
|
||||||
def provision
|
def provision
|
||||||
|
install_chef
|
||||||
|
verify_binary(chef_binary_path("chef-apply"))
|
||||||
|
|
||||||
command = "chef-apply"
|
command = "chef-apply"
|
||||||
command << " --log-level #{config.log_level}"
|
command << " \"#{target_recipe_path}\""
|
||||||
command << " #{config.upload_path}"
|
command << " --log_level #{config.log_level}"
|
||||||
|
|
||||||
user = @machine.ssh_info[:username]
|
user = @machine.ssh_info[:username]
|
||||||
|
|
||||||
|
@ -18,7 +23,7 @@ module VagrantPlugins
|
||||||
# Upload the recipe
|
# Upload the recipe
|
||||||
upload_recipe
|
upload_recipe
|
||||||
|
|
||||||
@machine.ui.info(I18n.t("vagrant.provisioners.chef.running_chef_apply",
|
@machine.ui.info(I18n.t("vagrant.provisioners.chef.running_apply",
|
||||||
script: config.path)
|
script: config.path)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,6 +39,12 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The destination (on the guest) where the recipe will live
|
||||||
|
# @return [String]
|
||||||
|
def target_recipe_path
|
||||||
|
File.join(config.upload_path, "recipe.rb")
|
||||||
|
end
|
||||||
|
|
||||||
# Write the raw recipe contents to a tempfile and upload that to the
|
# Write the raw recipe contents to a tempfile and upload that to the
|
||||||
# machine.
|
# machine.
|
||||||
def upload_recipe
|
def upload_recipe
|
||||||
|
@ -43,8 +54,7 @@ module VagrantPlugins
|
||||||
file.rewind
|
file.rewind
|
||||||
|
|
||||||
# Upload the tempfile to the guest
|
# Upload the tempfile to the guest
|
||||||
destination = File.join(config.upload_path, "recipe.rb")
|
@machine.communicate.upload(file.path, target_recipe_path)
|
||||||
@machine.communicate.upload(file.path, destination)
|
|
||||||
ensure
|
ensure
|
||||||
# Delete our template
|
# Delete our template
|
||||||
file.close
|
file.close
|
||||||
|
|
|
@ -18,6 +18,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def provision
|
def provision
|
||||||
|
install_chef
|
||||||
verify_binary(chef_binary_path("chef-client"))
|
verify_binary(chef_binary_path("chef-client"))
|
||||||
chown_provisioning_folder
|
chown_provisioning_folder
|
||||||
create_client_key_folder
|
create_client_key_folder
|
||||||
|
|
|
@ -35,6 +35,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def provision
|
def provision
|
||||||
|
install_chef
|
||||||
# Verify that the proper shared folders exist.
|
# Verify that the proper shared folders exist.
|
||||||
check = []
|
check = []
|
||||||
@shared_folders.each do |type, local_path, remote_path|
|
@shared_folders.each do |type, local_path, remote_path|
|
||||||
|
|
|
@ -87,6 +87,14 @@ en:
|
||||||
CFEngine running in "single run" mode. Will execute one file.
|
CFEngine running in "single run" mode. Will execute one file.
|
||||||
cfengine_single_run_execute: |-
|
cfengine_single_run_execute: |-
|
||||||
Executing run file for CFEngine...
|
Executing run file for CFEngine...
|
||||||
|
chef_cant_detect: |-
|
||||||
|
Vagrant does not support detecting whether Chef is installed
|
||||||
|
for the guest OS running in the machine. Vagrant will assume it is
|
||||||
|
installed and attempt to continue.
|
||||||
|
chef_already_installed: |-
|
||||||
|
Detected Chef (%{version}) is already installed
|
||||||
|
chef_installing: |-
|
||||||
|
Installing Chef (%{version})...
|
||||||
chef_client_cleanup_failed: |-
|
chef_client_cleanup_failed: |-
|
||||||
Cleaning up the '%{deletable}' for Chef failed. The stdout and
|
Cleaning up the '%{deletable}' for Chef failed. The stdout and
|
||||||
stderr are shown below. Vagrant will continue destroying the machine,
|
stderr are shown below. Vagrant will continue destroying the machine,
|
||||||
|
@ -1754,6 +1762,16 @@ en:
|
||||||
"The cookbook path '%{path}' doesn't exist. Ignoring..."
|
"The cookbook path '%{path}' doesn't exist. Ignoring..."
|
||||||
json: "Generating chef JSON and uploading..."
|
json: "Generating chef JSON and uploading..."
|
||||||
client_key_folder: "Creating folder to hold client key..."
|
client_key_folder: "Creating folder to hold client key..."
|
||||||
|
install_failed: |-
|
||||||
|
Vagrant could not detect Chef on the guest! Even after Vagrant
|
||||||
|
attempted to install Chef, it could still not find Chef on the system.
|
||||||
|
Please make sure you are connected to the Internet and can access
|
||||||
|
Chef's package distribution servers. If you already have Chef
|
||||||
|
installed on this guest, you can disable the automatic Chef detection
|
||||||
|
by setting the 'install' option in the Chef configuration section of
|
||||||
|
your Vagrantfile:
|
||||||
|
|
||||||
|
chef.install = false
|
||||||
log_level_empty: |-
|
log_level_empty: |-
|
||||||
The Chef provisioner requires a log level. If you did not set a
|
The Chef provisioner requires a log level. If you did not set a
|
||||||
log level, this is probably a bug and should be reported.
|
log level, this is probably a bug and should be reported.
|
||||||
|
@ -1765,7 +1783,7 @@ en:
|
||||||
guest.
|
guest.
|
||||||
running_client: "Running chef-client..."
|
running_client: "Running chef-client..."
|
||||||
running_client_again: "Running chef-client again (failed to converge)..."
|
running_client_again: "Running chef-client again (failed to converge)..."
|
||||||
running_client_apply: "Running chef-apply..."
|
running_apply: "Running chef-apply..."
|
||||||
running_solo: "Running chef-solo..."
|
running_solo: "Running chef-solo..."
|
||||||
running_solo_again: "Running chef-solo again (failed to converge)..."
|
running_solo_again: "Running chef-solo again (failed to converge)..."
|
||||||
missing_shared_folders: |-
|
missing_shared_folders: |-
|
||||||
|
|
|
@ -28,6 +28,12 @@ describe VagrantPlugins::Chef::Config::Base do
|
||||||
subject.finalize!
|
subject.finalize!
|
||||||
expect(subject.install).to be(true)
|
expect(subject.install).to be(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "is converted to a symbol" do
|
||||||
|
subject.install = "force"
|
||||||
|
subject.finalize!
|
||||||
|
expect(subject.install).to eq(:force)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#log_level" do
|
describe "#log_level" do
|
||||||
|
@ -43,6 +49,13 @@ describe VagrantPlugins::Chef::Config::Base do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#prerelease" do
|
||||||
|
it "defaults to true" do
|
||||||
|
subject.finalize!
|
||||||
|
expect(subject.prerelease).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#version" do
|
describe "#version" do
|
||||||
it "defaults to :latest" do
|
it "defaults to :latest" do
|
||||||
subject.finalize!
|
subject.finalize!
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
require_relative "../../../base"
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/provisioners/chef/omnibus")
|
||||||
|
|
||||||
|
describe VagrantPlugins::Chef::Omnibus, :focus do
|
||||||
|
let(:prefix) { "curl -sL #{described_class.const_get(:OMNITRUCK)}" }
|
||||||
|
|
||||||
|
let(:version) { :latest }
|
||||||
|
let(:prerelease) { false }
|
||||||
|
|
||||||
|
let(:build_command) { described_class.build_command(version, prerelease) }
|
||||||
|
|
||||||
|
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")
|
||||||
|
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")
|
||||||
|
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 are given" do
|
||||||
|
let(:version) { "1.2.3" }
|
||||||
|
let(:prerelease) { true }
|
||||||
|
|
||||||
|
it "returns the correct command" do
|
||||||
|
expect(build_command).to eq("#{prefix} | sudo bash -s -- -p -v \"1.2.3\"")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue