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:
James Turnbull 2010-11-29 12:12:31 +11:00 committed by Mitchell Hashimoto
parent 54f86f236c
commit 6548bc9324
5 changed files with 225 additions and 1 deletions

View File

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

View File

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

View File

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

View File

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

View File

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