diff --git a/lib/vagrant/action/vm/provision.rb b/lib/vagrant/action/vm/provision.rb index 662cc9a68..1f059ebff 100644 --- a/lib/vagrant/action/vm/provision.rb +++ b/lib/vagrant/action/vm/provision.rb @@ -32,9 +32,10 @@ module Vagrant elsif provisioner.is_a?(Symbol) # We have a few hard coded provisioners for built-ins mapping = { - :chef_solo => Provisioners::ChefSolo, - :chef_server => Provisioners::ChefServer, - :puppet => Provisioners::Puppet + :chef_solo => Provisioners::ChefSolo, + :chef_server => Provisioners::ChefServer, + :puppet => Provisioners::Puppet, + :puppet_server => Provisioners::PuppetServer } provisioner_klass = mapping[provisioner] diff --git a/lib/vagrant/provisioners/puppet_server.rb b/lib/vagrant/provisioners/puppet_server.rb new file mode 100644 index 000000000..1afa916b8 --- /dev/null +++ b/lib/vagrant/provisioners/puppet_server.rb @@ -0,0 +1,59 @@ +module Vagrant + module Provisioners + + class PuppetServerError < Vagrant::Errors::VagrantError + error_namespace("vagrant.provisioners.puppet_server") + end + + class PuppetServerConfig < Vagrant::Config::Base + configures :puppet_server + + attr_accessor :puppet_server + attr_accessor :puppet_node + attr_accessor :options + + def initialize + @puppet_server = "puppet" + @puppet_node = "puppet_node" + @options = [] + end + end + + class PuppetServer < Base + + def provision! + verify_binary("puppetd") + run_puppetd_client + end + + def verify_binary(binary) + vm.ssh.execute do |ssh| + # Checks for the existence of puppetd binary and error if it + # doesn't exist. + ssh.exec!("which #{binary}", :error_class => PuppetServerError, :_key => :puppetd_not_detected, :binary => binary) + end + end + + def run_puppetd_client + options = env.config.puppet_server.options + options = options.join(" ") if options.is_a?(Array) + if env.config.puppet_server.puppet_node + cn = env.config.puppet_server.puppet_node + else + cn = env.config.vm.box + end + + command = "sudo -E puppetd #{options} --server #{env.config.puppet_server.puppet_server} --certname #{cn}" + + env.ui.info I18n.t("vagrant.provisioners.puppet_server.running_puppetd") + + 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 diff --git a/templates/locales/en.yml b/templates/locales/en.yml index aedcfef98..664e2efcc 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -16,6 +16,9 @@ en: 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. + puppetd_not_detected: |- + The `puppetd` binary was not found on the VM is required for Puppet Server 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) @@ -453,6 +456,14 @@ en: 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." + puppet_server: + 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_puppetd: "Running Puppet agent..." + systems: linux: attempting_halt: "Attempting graceful shutdown of linux..." diff --git a/test/vagrant/action/vm/provision_test.rb b/test/vagrant/action/vm/provision_test.rb index 45e4f43b0..442611c0c 100644 --- a/test/vagrant/action/vm/provision_test.rb +++ b/test/vagrant/action/vm/provision_test.rb @@ -107,6 +107,10 @@ class ProvisionVMActionTest < Test::Unit::TestCase should "set :puppet to the Puppet provisioner" do provisioner_expectation(:puppet, Vagrant::Provisioners::Puppet) end + + should "set :puppet_server to the Puppet Server provisioner" do + provisioner_expectation(:puppet_server, Vagrant::Provisioners::PuppetServer) + end end end diff --git a/test/vagrant/provisioners/puppet_server_test.rb b/test/vagrant/provisioners/puppet_server_test.rb new file mode 100644 index 000000000..b72fa3bf2 --- /dev/null +++ b/test/vagrant/provisioners/puppet_server_test.rb @@ -0,0 +1,64 @@ +require "test_helper" + +class PuppetServerProvisionerTest < Test::Unit::TestCase + setup do + @action_env = Vagrant::Action::Environment.new(vagrant_env.vms[:default].env) + + @action = Vagrant::Provisioners::PuppetServer.new(@action_env) + @env = @action.env + @vm = @action.vm + end + + context "provisioning" do + should "run the proper sequence of methods in order" do + prov_seq = sequence("prov_seq") + @action.expects(:verify_binary).with("puppetd").once.in_sequence(prov_seq) + @action.expects(:run_puppetd_client).once.in_sequence(prov_seq) + @action.provision! + 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 "running puppetd client" do + setup do + @cn = "puppet_node" + @ssh = mock("ssh") + @vm.ssh.stubs(:execute).yields(@ssh) + end + + should "run the puppetd client" do + @ssh.expects(:exec!).with("sudo -E puppetd --server #{@env.config.puppet_server.puppet_server} --certname #{@cn}").once + @action.run_puppetd_client + end + + should "run puppetd with given options when given as an array" do + @env.config.puppet_server.options = ["--modulepath", "modules", "--verbose"] + @ssh.expects(:exec!).with("sudo -E puppetd --modulepath modules --verbose --server #{@env.config.puppet_server.puppet_server} --certname #{@cn}").once + @action.run_puppetd_client + end + + should "run puppetd with the options when given as a string" do + @env.config.puppet_server.options = "--modulepath modules --verbose" + @ssh.expects(:exec!).with("sudo -E puppetd --modulepath modules --verbose --server #{@env.config.puppet_server.puppet_server} --certname #{@cn}").once + @action.run_puppetd_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_puppetd_client + end + end +end