#!/usr/bin/ruby require 'pathname' require 'optparse' trap("QUIT"){ exit(-1)} trap("INT"){ exit(-1)} module Constants Puppet_conf_tmpl = " [main] vardir = /var/lib/puppet logdir = /var/log/puppet rundir = /var/run/puppet ssldir = $vardir/ssl templatedir = $vardir/templates statedir = $vardir/state node_terminus = plain noop = true [puppet] localconfig = $vardir/localconfig factsync = false report = false graph = false pluginsync = false " end options = {} optparse = OptionParser.new do |opts| # Set a banner, displayed at the top # of the help screen. opts.define_head "Manitest compiles a manifest using another hosts facts." opts.banner = "Usage: #{$0}" opts.separator "" # Define the options, and what they do options[:verbose] = false opts.on( '-v', '--verbose', 'Output more information' ) do options[:verbose] = true end options[:debug] = false opts.on( '-d', '--debug', 'Output the full puppet debug' ) do options[:debug] = true end opts.on( '-e', '--environment ENV', 'Override node environment' ) do |env| options[:environment] = env end options[:confdir] = "/etc/puppet" opts.on( '-c', '--confdir DIR', 'Where to find puppet config - defaults to /etc/puppet' ) do |dir| options[:confdir] = dir end options[:tmpdir] = "/tmp/" opts.on( '-t', '--tmpdir DIR', 'Where to write temp files - defaults to /tmp' ) do |tmp| options[:tmpdir] = tmp # Ensure that tmpdir has a trailing slash options[:tmpdir] += "/" unless options[:tmpdir]=~/\/$/ end options[:node] = "" opts.on( '-n', '--node FILE', 'YAML node file to use' ) do |file| options[:node] = file end opts.on( '-h', '--help', 'Display this screen' ) do puts opts exit end end optparse.parse! if options[:node].empty? puts optparse exit 1 end options[:node] += ".yaml" unless options[:node]=~/yaml$/ unless File.exists? options[:node] warn "Unable to find file #{options[:node]}" unless File.exists? options[:node] exit 1 end # load puppet infrastructure only after we've got some command line arguments require 'puppet' Puppet[:config] = "#{options[:confdir]}/puppet.conf" Puppet.parse_config node = YAML.load_file options[:node] unless node.is_a?(Puppet::Node) warn "Invalid node file - you should use something from /var/lib/puppet/yaml/node directory" exit 1 end environment=(options[:environment] || node.environment).to_sym puts "Setting up environment: #{environment}" if options[:verbose] or options[:debug] # export all parameters as facter env - overriding our real system values # this also works for external nodes parameters puts "Setting up facts:" if options[:verbose] or options[:debug] node.parameters.each do |k,v| begin ENV["facter_#{k}"]=v puts "%s=>%s" % [k,v] if options[:debug] rescue warn "failed to set fact #{k} => #{v}" if options[:debug] end end # find env module path conf = Puppet.settings.instance_variable_get(:@values) unless conf[environment][:modulepath].nil? modulepath = conf[environment][:modulepath] else Puppet.settings.eachsection do |p| path=conf[p][:modulepath] modulepath = path and break unless path.nil? end end # if no module path is defined, use the default one modulepath = Puppet.settings[:modulepath] if modulepath.nil? or modulepath.empty? modulepath = "#{options[:confdir]}/modules" # Set the dummy puppet.conf puppet_conf = Constants::Puppet_conf_tmpl.dup puppet_conf << "\tmodulepath = #{modulepath}\n" # Write out a puppet.conf and a node.conf. conf = Pathname.new(options[:tmpdir]) + ".tmp_puppet.conf" nodefile = options[:confdir] + "/manifests/site.pp" conf.open(File::CREAT|File::WRONLY|File::TRUNC) {|f| f.write puppet_conf} cmd = "/usr/bin/puppet --environment #{environment} --config #{conf} --certname #{node.name} --debug --color false #{nodefile} 2>&1" puts cmd if options[:debug] default_schedule = false status = "broken" IO.popen(cmd) do |puppet| while not puppet.eof? line = puppet.readline if options[:debug] puts line elsif line !~ /^(debug|info|notice):/ # this should be an error message puts line end if line =~ /Creating default schedules/ default_schedule = true end if line =~ /Finishing transaction/ and default_schedule status = "OK" break elsif line =~ /Finishing transaction/ break end end end if options[:verbose] or options[:debug] puts "The manifest compilation for #{node.name} is #{status}" end conf.unlink unless options[:debug] exit(status == "OK" ? 0 : -1)