Adds a basic Puppet provisioner to Vagrant
This uses the Puppet binary and assumes a .pp file will be present on the host machine. By default it looks for manifests in the `manifests` directory (in the same root as wherever your Vagrantfile is located). The default file uses the name of the box being configured, for example `lucid.pp`. Both options are configurable.
This commit is contained in:
parent
54f86f236c
commit
6548bc9324
|
@ -33,7 +33,8 @@ module Vagrant
|
|||
# We have a few hard coded provisioners for built-ins
|
||||
mapping = {
|
||||
:chef_solo => Provisioners::ChefSolo,
|
||||
:chef_server => Provisioners::ChefServer
|
||||
:chef_server => Provisioners::ChefServer,
|
||||
:puppet => Provisioners::Puppet
|
||||
}
|
||||
|
||||
provisioner_klass = mapping[provisioner]
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
module Vagrant
|
||||
module Provisioners
|
||||
|
||||
class PuppetError < Vagrant::Errors::VagrantError
|
||||
error_namespace("vagrant.provisioners.puppet")
|
||||
end
|
||||
|
||||
class PuppetConfig < Vagrant::Config::Base
|
||||
configures :puppet
|
||||
|
||||
attr_accessor :manifest_file
|
||||
attr_accessor :manifests_path
|
||||
attr_accessor :pp_path
|
||||
|
||||
def initialize
|
||||
@manifest_file = ""
|
||||
@manifests_path = "manifests"
|
||||
@pp_path = "/tmp/vagrant-puppet"
|
||||
end
|
||||
end
|
||||
|
||||
class Puppet < Base
|
||||
|
||||
def prepare
|
||||
check_manifest_dir
|
||||
share_manifests
|
||||
end
|
||||
|
||||
def provision!
|
||||
verify_binary("puppet")
|
||||
create_pp_path
|
||||
set_manifest
|
||||
run_puppet_client
|
||||
end
|
||||
|
||||
def check_manifest_dir
|
||||
Dir.mkdir(env.config.puppet.manifests_path) unless File.directory?(env.config.puppet.manifests_path)
|
||||
end
|
||||
|
||||
def share_manifests
|
||||
env.config.vm.share_folder("manifests", env.config.puppet.pp_path, env.config.puppet.manifests_path)
|
||||
end
|
||||
|
||||
def verify_binary(binary)
|
||||
vm.ssh.execute do |ssh|
|
||||
ssh.exec!("which #{binary}", :error_class => PuppetError, :_key => :puppet_not_detected, :binary => binary)
|
||||
end
|
||||
end
|
||||
|
||||
def create_pp_path
|
||||
vm.ssh.execute do |ssh|
|
||||
ssh.exec!("sudo mkdir -p #{env.config.puppet.pp_path}")
|
||||
ssh.exec!("sudo chown #{env.config.ssh.username} #{env.config.puppet.pp_path}")
|
||||
end
|
||||
end
|
||||
|
||||
def set_manifest
|
||||
@manifest = !env.config.puppet.manifest_file.empty? ? env.config.puppet.manifest_file : "#{env.config.vm.box}.pp"
|
||||
|
||||
if File.exists?("#{env.config.puppet.manifests_path}/#{@manifest}")
|
||||
env.ui.info I18n.t("vagrant.provisioners.puppet.manifest_to_run", :manifest => @manifest)
|
||||
return @manifest
|
||||
else
|
||||
raise PuppetError.new(:_key => :manifest_missing, :manifest => @manifest)
|
||||
end
|
||||
end
|
||||
|
||||
def run_puppet_client
|
||||
command = "cd #{env.config.puppet.pp_path} && sudo -E puppet #{@manifest}"
|
||||
|
||||
env.ui.info I18n.t("vagrant.provisioners.puppet.running_puppet")
|
||||
|
||||
vm.ssh.execute do |ssh|
|
||||
ssh.exec!(command) do |channel, type, data|
|
||||
ssh.check_exit_status(data, command) if type == :exit_status
|
||||
env.ui.info("#{data}: #{type}") if type != :exit_status
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,6 +13,9 @@ en:
|
|||
The chef (either `chef-solo` or `chef-client`) binary was not found on
|
||||
the VM and is required for chef provisioning. Please verify that chef
|
||||
is installed and that the binary is available on the PATH.
|
||||
puppet_not_detected: |-
|
||||
The `puppet` binary was not found on the VM and is required for Puppet provisioning.
|
||||
Please verify that Puppet is installed and that the binary is available on the PATH.
|
||||
cli_missing_env: This command requires that a Vagrant environment be properly passed in as the last parameter.
|
||||
config_validation: |-
|
||||
There was a problem with the configuration of Vagrant. The error message(s)
|
||||
|
@ -416,6 +419,16 @@ en:
|
|||
The validation key set for `config.chef.validation_key_path` does not exist! This
|
||||
file needs to exist so it can be uploaded to the virtual machine.
|
||||
|
||||
puppet:
|
||||
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 Puppet is not
|
||||
installed on this guest. Puppet provisioning can not continue without
|
||||
Puppet properly installed.
|
||||
running_puppet: "Running Puppet..."
|
||||
manifest_to_run: "Puppet will use the %{manifest} manifest to configure your box."
|
||||
manifest_missing: "The Puppet %{manifest} manifest is missing. You cannot configure this box."
|
||||
|
||||
systems:
|
||||
linux:
|
||||
attempting_halt: "Attempting graceful shutdown of linux..."
|
||||
|
|
|
@ -103,6 +103,10 @@ class ProvisionVMActionTest < Test::Unit::TestCase
|
|||
should "set :chef_server to the ChefServer provisioner" do
|
||||
provisioner_expectation(:chef_server, Vagrant::Provisioners::ChefServer)
|
||||
end
|
||||
|
||||
should "set :puppet to the Puppet provisioner" do
|
||||
provisioner_expectation(:puppet, Vagrant::Provisioners::Puppet)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
require "test_helper"
|
||||
|
||||
class PuppetProvisionerTest < Test::Unit::TestCase
|
||||
setup do
|
||||
@action_env = Vagrant::Action::Environment.new(vagrant_env.vms[:default].env)
|
||||
|
||||
@action = Vagrant::Provisioners::Puppet.new(@action_env)
|
||||
@env = @action.env
|
||||
@vm = @action.vm
|
||||
end
|
||||
|
||||
context "preparing" do
|
||||
should "share manifests" do
|
||||
@action.expects(:check_manifest_dir).once
|
||||
@action.expects(:share_manifests).once
|
||||
@action.prepare
|
||||
end
|
||||
end
|
||||
|
||||
context "provisioning" do
|
||||
should "run the proper sequence of methods in order" do
|
||||
prov_seq = sequence("prov_seq")
|
||||
@action.expects(:verify_binary).with("puppet").once.in_sequence(prov_seq)
|
||||
@action.expects(:create_pp_path).once.in_sequence(prov_seq)
|
||||
@action.expects(:set_manifest).once.in_sequence(prov_seq)
|
||||
@action.expects(:run_puppet_client).once.in_sequence(prov_seq)
|
||||
@action.provision!
|
||||
end
|
||||
end
|
||||
|
||||
context "check manifest_dir" do
|
||||
setup do
|
||||
@env.config.puppet.manifests_path = "manifests"
|
||||
end
|
||||
|
||||
should "should not create the manifest directory if it exists" do
|
||||
File.expects(:directory?).with(@env.config.puppet.manifests_path).returns(true)
|
||||
@action.check_manifest_dir
|
||||
end
|
||||
|
||||
should "create the manifest directory if it does not exist" do
|
||||
File.stubs(:directory?).with(@env.config.puppet.manifests_path).returns(false)
|
||||
Dir.expects(:mkdir).with(@env.config.puppet.manifests_path).once
|
||||
@action.check_manifest_dir
|
||||
end
|
||||
end
|
||||
|
||||
context "share manifests folder" do
|
||||
setup do
|
||||
@manifests_path = "manifests"
|
||||
@pp_path = "/tmp/vagrant-puppet"
|
||||
@action.stubs(:manifests_path).returns(@manifests_path)
|
||||
@action.stubs(:pp_path).returns(@pp_path)
|
||||
end
|
||||
|
||||
should "share manifest folder" do
|
||||
@env.config.vm.expects(:share_folder).with("manifests", @pp_path, @manifests_path)
|
||||
@action.share_manifests
|
||||
end
|
||||
end
|
||||
|
||||
context "verifying binary" do
|
||||
setup do
|
||||
@ssh = mock("ssh")
|
||||
@vm.ssh.stubs(:execute).yields(@ssh)
|
||||
end
|
||||
|
||||
should "verify binary exists" do
|
||||
binary = "foo"
|
||||
@ssh.expects(:exec!).with("which #{binary}", anything)
|
||||
@action.verify_binary(binary)
|
||||
end
|
||||
end
|
||||
|
||||
context "create pp path" do
|
||||
should "create and chown the folder to the ssh user" do
|
||||
ssh_seq = sequence("ssh_seq")
|
||||
ssh = mock("ssh")
|
||||
ssh.expects(:exec!).with("sudo mkdir -p #{@env.config.puppet.pp_path}").once.in_sequence(ssh_seq)
|
||||
ssh.expects(:exec!).with("sudo chown #{@env.config.ssh.username} #{@env.config.puppet.pp_path}").once.in_sequence(ssh_seq)
|
||||
@vm.ssh.expects(:execute).yields(ssh)
|
||||
@action.create_pp_path
|
||||
end
|
||||
end
|
||||
|
||||
context "setting the manifest" do
|
||||
setup do
|
||||
@env.config.puppet.stubs(:manifests_path).returns("manifests")
|
||||
@env.config.puppet.stubs(:manifest_file).returns("foo.pp")
|
||||
@env.config.vm.stubs(:box).returns("base")
|
||||
end
|
||||
|
||||
should "set the manifest if it exists" do
|
||||
File.stubs(:exists?).with("#{@env.config.puppet.manifests_path}/#{@env.config.puppet.manifest_file}").returns(true)
|
||||
@action.set_manifest
|
||||
end
|
||||
|
||||
should "raise an error if the manifest does not exist" do
|
||||
File.stubs(:exists?).with("#{@env.config.puppet.manifests_path}/#{@env.config.puppet.manifest_file}").returns(false)
|
||||
assert_raises(Vagrant::Provisioners::PuppetError) {
|
||||
@action.set_manifest
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "running puppet client" do
|
||||
setup do
|
||||
@ssh = mock("ssh")
|
||||
@vm.ssh.stubs(:execute).yields(@ssh)
|
||||
end
|
||||
|
||||
should "cd into the pp_path directory and run puppet" do
|
||||
@ssh.expects(:exec!).with("cd #{@env.config.puppet.pp_path} && sudo -E puppet #{@manifest}").once
|
||||
@action.run_puppet_client
|
||||
end
|
||||
|
||||
should "check the exit status if that is given" do
|
||||
@ssh.stubs(:exec!).yields(nil, :exit_status, :foo)
|
||||
@ssh.expects(:check_exit_status).with(:foo, anything).once
|
||||
@action.run_puppet_client
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue