Index: hiera/puppet-node-classifier.rb |
=================================================================== |
new file mode 100755 |
--- /dev/null |
+++ b/hiera/puppet-node-classifier.rb |
@@ -0,0 +1,93 @@ |
+#!/usr/bin/env ruby |
+# This script is a node classifier for Puppet that operates on top of Hiera |
+# and uses a custom hosts.yaml config to map host roles. |
+ |
+require 'getoptlong' |
+require 'hiera' |
+require 'socket' |
+require 'yaml' |
+ |
+# Where to search for the Hiera configuration |
+HIERA_CONFIG = ENV.fetch('PUPPET_HIERA_CONFIG', '/etc/puppet/hiera.yaml') |
+# Where to search for the Hosts configuration |
+HOSTS_CONFIG = ENV.fetch('PUPPET_HOSTS_CONFIG', '/etc/puppet/infrastructure/hiera/environment/hosts.yaml') |
Wladimir Palant
2014/11/17 16:43:36
I don't think hardcoding /etc/puppet/infrastructur
mathias
2014/11/27 00:30:18
It would work in this case, indeed. Yet I don't be
|
+ |
+# The current script name, used for logging and usage hints |
+BASENAME = File.basename($0) |
+ |
+# Although there's no need for any options in particular yet, the script |
+# still recognizes a --help option, which is considered the bare minimum by |
+# convention. Nonetheless, future options may become integrated here (see |
+# also http://ruby-doc.org/stdlib/libdoc/getoptlong/rdoc/GetoptLong.html): |
+GetoptLong.new( |
+ ['--help', '-h', GetoptLong::NO_ARGUMENT] |
+).each do |opt, arg| |
+ case opt |
+ |
+ when '--help' |
+ puts <<-END |
+Usage: #{BASENAME} [hostname] |
+ #{BASENAME} example.com |
+ #{BASENAME} --help |
+ |
+Options: |
+ |
+ --help, -h |
+ Display this help message and exit gracefully. |
+ |
+Environment: |
+ |
+ PUPPET_HIERA_CONFIG=#{HIERA_CONFIG} |
+ Where to find the hiera configuration file. |
+ PUPPET_HOSTS_CONFIG=#{HOSTS_CONFIG} |
+ Where to find the hosts configuration file. |
+ |
+END |
+ exit 0 |
+ |
+ end |
+end |
+ |
+# Only one additional non-option argument is allowed, in order to explicitly |
+# specify a hostname to use instead of the default: |
+case ARGV.length |
+ when 0 |
+ hostname = Socket.gethostname |
+ when 1 |
+ hostname = ARGV[0][/^[^.]+/] |
+ else |
+ STDERR.puts <<-END |
+#{BASENAME}: unknown option: #{ARGV[0]} |
+#{BASENAME}: try #{BASENAME} --help |
+END |
+ exit 1 |
+end |
+ |
+# Extract the server -> hostname -> role information from the hosts |
+# configuration file: |
+begin |
+ config = YAML.load_file(HOSTS_CONFIG) |
+ servers = config.fetch("servers", {}) |
+ host = servers.fetch(hostname, {}) |
+ role = host.fetch("role", "default") |
+rescue Exception => error |
+ STDERR.puts "#{BASENAME}: #{error.message}: #{HOSTS_CONFIG}" |
+ exit 1 |
+end |
+ |
+# Map Hiera data into the structure Puppet expects an ENC to generate (see |
+# https://docs.puppetlabs.com/guides/external_nodes.html for more info): |
+begin |
+ hiera = Hiera.new(:config => HIERA_CONFIG) |
+ scope = {'::hostname'=> hostname, '::role'=> role} |
+ result = { |
+ 'classes'=> hiera.lookup('classes', {}, scope, nil, :hash), |
+ 'parameters'=> hiera.lookup('parameters', {}, scope, nil, :hash), |
+ } |
+rescue Exception => error |
+ STDERR.puts "#{BASENAME}: #{error.message}: #{HIERA_CONFIG}" |
+ exit 1 |
+end |
+ |
+puts result.to_yaml |
+ |