Puppet provisioner can mount/configure module paths from local directory

This commit is contained in:
Mitchell Hashimoto 2011-01-13 21:02:26 -08:00
parent 28a2167dda
commit 302f9ff0bb
4 changed files with 105 additions and 14 deletions

View File

@ -1,10 +1,8 @@
## 0.7.0 (unreleased) ## 0.7.0 (unreleased)
The 0.7.0 betas will be merged into this one section upon final release. - VirtualBox 4.0 support. Support for VirtualBox 3.2 is _dropped_, since
I don't expect many changes. the API is so different. Stay with the 0.6.x series if you have VirtualBox
3.2.x.
## 0.7.0.beta2 (January 13, 2010)
- Puppet server provisioner. [GH-262] - Puppet server provisioner. [GH-262]
- Use numeric uid/gid in mounting shared folders to increase portability. [GH-252] - Use numeric uid/gid in mounting shared folders to increase portability. [GH-252]
- HTTP downloading follows redirects. [GH-163] - HTTP downloading follows redirects. [GH-163]
@ -28,17 +26,13 @@ I don't expect many changes.
change is not backwards compatible. [GH-265] change is not backwards compatible. [GH-265]
- Provisioners are now RVM-friendly, meaning if you installed chef or puppet - Provisioners are now RVM-friendly, meaning if you installed chef or puppet
with an RVM managed Ruby, Vagrant now finds then. [GH-254] with an RVM managed Ruby, Vagrant now finds then. [GH-254]
## 0.7.0.beta (December 24, 2010)
- VirtualBox 4.0 support. Support for VirtualBox 3.2 is _dropped_, since
the API is so different. Stay with the 0.6.x series if you have VirtualBox
3.2.x.
- Changed the unused host only network destroy mechanism to check for - Changed the unused host only network destroy mechanism to check for
uselessness after the VM is destroyed. This should result in more accurate uselessness after the VM is destroyed. This should result in more accurate
checks. checks.
- Networks are no longer disabled upon halt/destroy. With the above - Networks are no longer disabled upon halt/destroy. With the above
change, its unnecessary. change, its unnecessary.
- Puppet supports `module_path` configuration to mount local modules directory
as a shared folder and configure puppet with it. [GH-270]
## 0.6.9 (December 21, 2010) ## 0.6.9 (December 21, 2010)

View File

@ -10,12 +10,14 @@ module Vagrant
class Config < Vagrant::Config::Base class Config < Vagrant::Config::Base
attr_accessor :manifest_file attr_accessor :manifest_file
attr_accessor :manifests_path attr_accessor :manifests_path
attr_accessor :module_path
attr_accessor :pp_path attr_accessor :pp_path
attr_accessor :options attr_accessor :options
def initialize def initialize
@manifest_file = nil @manifest_file = nil
@manifests_path = "manifests" @manifests_path = "manifests"
@module_path = nil
@pp_path = "/tmp/vagrant-puppet" @pp_path = "/tmp/vagrant-puppet"
@options = [] @options = []
end end
@ -32,20 +34,45 @@ module Vagrant
manifest_file || "#{top.vm.box}.pp" manifest_file || "#{top.vm.box}.pp"
end end
# Returns the module paths as an array of paths expanded relative to the
# root path.
def expanded_module_paths
return [] if !module_path
# Get all the paths and expand them relative to the root path, returning
# the array of expanded paths
paths = module_path
paths = [paths] if !paths.is_a?(Array)
paths.map do |path|
Pathname.new(path).expand_path(env.root_path)
end
end
def validate(errors) def validate(errors)
super super
# Manifests path/file validation
if !expanded_manifests_path.directory? if !expanded_manifests_path.directory?
errors.add(I18n.t("vagrant.provisioners.puppet.manifests_path_missing", :path => expanded_manifests_path)) errors.add(I18n.t("vagrant.provisioners.puppet.manifests_path_missing", :path => expanded_manifests_path))
return else
if !expanded_manifests_path.join(computed_manifest_file).file?
errors.add(I18n.t("vagrant.provisioners.puppet.manifest_missing", :manifest => computed_manifest_file))
end
end end
errors.add(I18n.t("vagrant.provisioners.puppet.manifest_missing", :manifest => computed_manifest_file)) if !expanded_manifests_path.join(computed_manifest_file).file? # Module paths validation
expanded_module_paths.each do |path|
if !path.directory?
errors.add(I18n.t("vagrant.provisioners.puppet.module_path_missing", :path => path))
end
end
end end
end end
def prepare def prepare
set_module_paths
share_manifests share_manifests
share_module_paths
end end
def provision! def provision!
@ -58,6 +85,23 @@ module Vagrant
env.config.vm.share_folder("manifests", config.pp_path, config.manifests_path) env.config.vm.share_folder("manifests", config.pp_path, config.manifests_path)
end end
def share_module_paths
count = 0
@module_paths.each do |from, to|
# Sorry for the cryptic key here, but VirtualBox has a strange limit on
# maximum size for it and its something small (around 10)
env.config.vm.share_folder("v-pp-m#{count}", to, from)
count += 1
end
end
def set_module_paths
@module_paths = {}
config.expanded_module_paths.each_with_index do |path, i|
@module_paths[path] = File.join(config.pp_path, "modules-#{i}")
end
end
def verify_binary(binary) def verify_binary(binary)
vm.ssh.execute do |ssh| vm.ssh.execute do |ssh|
ssh.exec!("sudo -i which #{binary}", :error_class => PuppetError, :_key => :puppet_not_detected, :binary => binary) ssh.exec!("sudo -i which #{binary}", :error_class => PuppetError, :_key => :puppet_not_detected, :binary => binary)
@ -73,6 +117,7 @@ module Vagrant
def run_puppet_client def run_puppet_client
options = [config.options].flatten options = [config.options].flatten
options << "--modulepath '#{@module_paths.values.join(':')}'" if !@module_paths.empty?
options << config.computed_manifest_file options << config.computed_manifest_file
options = options.join(" ") options = options.join(" ")

View File

@ -475,6 +475,7 @@ en:
running_puppet: "Running Puppet with %{manifest}..." running_puppet: "Running Puppet with %{manifest}..."
manifest_missing: "The Puppet %{manifest} manifest is missing. You cannot configure this box." manifest_missing: "The Puppet %{manifest} manifest is missing. You cannot configure this box."
manifests_path_missing: "The manifests path specified for Puppet does not exist: %{path}" manifests_path_missing: "The manifests path specified for Puppet does not exist: %{path}"
module_path_missing: "The configured module path doesn't exist: %{path}"
puppet_server: puppet_server:
not_detected: |- not_detected: |-

View File

@ -41,6 +41,20 @@ class PuppetProvisionerTest < Test::Unit::TestCase
assert_equal "woot.pp", @config.computed_manifest_file assert_equal "woot.pp", @config.computed_manifest_file
end end
should "return an empty array if no module path is set" do
@config.module_path = nil
assert_equal [], @config.expanded_module_paths
end
should "return array of module paths expanded relative to root path" do
@config.module_path = "foo"
result = @config.expanded_module_paths
assert result.is_a?(Array)
assert_equal 1, result.length
assert_equal File.expand_path(@config.module_path, @env.root_path), result[0].to_s
end
should "be valid" do should "be valid" do
@config.validate(@errors) @config.validate(@errors)
assert @errors.errors.empty? assert @errors.errors.empty?
@ -63,11 +77,27 @@ class PuppetProvisionerTest < Test::Unit::TestCase
@config.validate(@errors) @config.validate(@errors)
assert !@errors.errors.empty? assert !@errors.errors.empty?
end end
should "be invalid if a specified module path doesn't exist" do
@config.module_path = "foo"
@config.validate(@errors)
assert !@errors.errors.empty?
end
should "be valid if all module paths exist" do
@config.module_path = "foo"
@config.expanded_module_paths.first.mkdir
@config.validate(@errors)
assert @errors.errors.empty?
end
end end
context "preparing" do context "preparing" do
should "share manifests" do should "share manifests" do
@action.expects(:share_manifests).once pre_seq = sequence("prepare")
@action.expects(:set_module_paths).once.in_sequence(pre_seq)
@action.expects(:share_manifests).once.in_sequence(pre_seq)
@action.expects(:share_module_paths).once.in_sequence(pre_seq)
@action.prepare @action.prepare
end end
end end
@ -96,6 +126,18 @@ class PuppetProvisionerTest < Test::Unit::TestCase
end end
end end
context "sharing module paths" do
should "share all the module paths" do
@config.module_path = ["foo", "bar"]
@config.expanded_module_paths.each_with_index do |path, i|
@env.config.vm.expects(:share_folder).with("v-pp-m#{i}", File.join(@config.pp_path, "modules-#{i}"), path)
end
@action.set_module_paths
@action.share_module_paths
end
end
context "verifying binary" do context "verifying binary" do
setup do setup do
@ssh = mock("ssh") @ssh = mock("ssh")
@ -124,6 +166,7 @@ class PuppetProvisionerTest < Test::Unit::TestCase
setup do setup do
@ssh = mock("ssh") @ssh = mock("ssh")
@vm.ssh.stubs(:execute).yields(@ssh) @vm.ssh.stubs(:execute).yields(@ssh)
@action.set_module_paths
end end
def expect_puppet_command(command) def expect_puppet_command(command)
@ -146,5 +189,13 @@ class PuppetProvisionerTest < Test::Unit::TestCase
expect_puppet_command("puppet --modulepath modules --verbose #{@config.computed_manifest_file}") expect_puppet_command("puppet --modulepath modules --verbose #{@config.computed_manifest_file}")
@action.run_puppet_client @action.run_puppet_client
end end
should "cd into the pp_path and run puppet with module paths if set" do
@config.module_path = "foo"
expect_puppet_command("puppet --modulepath '#{File.join(@config.pp_path, 'modules-0')}' #{@config.computed_manifest_file}")
@action.set_module_paths
@action.run_puppet_client
end
end end
end end