vagrant/plugins/provisioners/puppet/provisioner/puppet.rb

179 lines
6.1 KiB
Ruby

require "log4r"
module VagrantPlugins
module Puppet
module Provisioner
class PuppetError < Vagrant::Errors::VagrantError
error_namespace("vagrant.provisioners.puppet")
end
class Puppet < Vagrant.plugin("2", :provisioner)
class Config < Vagrant.plugin("2", :config)
attr_accessor :manifest_file
attr_accessor :manifests_path
attr_accessor :module_path
attr_accessor :pp_path
attr_accessor :options
attr_accessor :facter
def manifest_file; @manifest_file || "default.pp"; end
def manifests_path; @manifests_path || "manifests"; end
def pp_path; @pp_path || "/tmp/vagrant-puppet"; end
def options; @options ||= []; end
def facter; @facter ||= {}; end
# Returns the manifests path expanded relative to the root path of the
# environment.
def expanded_manifests_path(root_path)
Pathname.new(manifests_path).expand_path(root_path)
end
# Returns the module paths as an array of paths expanded relative to the
# root path.
def expanded_module_paths(root_path)
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(root_path)
end
end
def validate(env, errors)
# Calculate the manifests and module paths based on env
this_expanded_manifests_path = expanded_manifests_path(env.root_path)
this_expanded_module_paths = expanded_module_paths(env.root_path)
# Manifests path/file validation
if !this_expanded_manifests_path.directory?
errors.add(I18n.t("vagrant.provisioners.puppet.manifests_path_missing",
:path => this_expanded_manifests_path))
else
expanded_manifest_file = this_expanded_manifests_path.join(manifest_file)
if !expanded_manifest_file.file?
errors.add(I18n.t("vagrant.provisioners.puppet.manifest_missing",
:manifest => expanded_manifest_file.to_s))
end
end
# Module paths validation
this_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
def self.config_class
Config
end
def initialize(env, config)
super
@logger = Log4r::Logger.new("vagrant::provisioners::puppet")
end
def prepare
# Calculate the paths we're going to use based on the environment
@expanded_manifests_path = config.expanded_manifests_path(env[:root_path])
@expanded_module_paths = config.expanded_module_paths(env[:root_path])
@manifest_file = File.join(manifests_guest_path, config.manifest_file)
set_module_paths
share_manifests
share_module_paths
end
def provision!
# Check that the shared folders are properly shared
check = [manifests_guest_path]
@module_paths.each do |host_path, guest_path|
check << guest_path
end
verify_shared_folders(check)
# Verify Puppet is installed and run it
verify_binary("puppet")
run_puppet_apply
end
def share_manifests
env[:machine].config.vm.share_folder("manifests", manifests_guest_path, @expanded_manifests_path)
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[:machine].config.vm.share_folder("v-pp-m#{count}", to, from)
count += 1
end
end
def set_module_paths
@module_paths = []
@expanded_module_paths.each_with_index do |path, i|
@module_paths << [path, File.join(config.pp_path, "modules-#{i}")]
end
end
def manifests_guest_path
File.join(config.pp_path, "manifests")
end
def verify_binary(binary)
env[:machine].communicate.sudo("which #{binary}",
:error_class => PuppetError,
:error_key => :not_detected,
:binary => binary)
end
def run_puppet_apply
options = [config.options].flatten
module_paths = @module_paths.map { |_, to| to }
options << "--modulepath '#{module_paths.join(':')}'" if !@module_paths.empty?
options << @manifest_file
options = options.join(" ")
# Build up the custom facts if we have any
facter = ""
if !config.facter.empty?
facts = []
config.facter.each do |key, value|
facts << "FACTER_#{key}='#{value}'"
end
facter = "#{facts.join(" ")} "
end
command = "cd #{manifests_guest_path} && #{facter}puppet apply #{options} --detailed-exitcodes || [ $? -eq 2 ]"
env[:ui].info I18n.t("vagrant.provisioners.puppet.running_puppet",
:manifest => @manifest_file)
env[:machine].communicate.sudo(command) do |type, data|
data.chomp!
env[:ui].info(data, :prefix => false) if !data.empty?
end
end
def verify_shared_folders(folders)
folders.each do |folder|
@logger.debug("Checking for shared folder: #{folder}")
if !env[:machine].communicate.test("test -d #{folder}")
raise PuppetError, :missing_shared_folders
end
end
end
end
end
end
end