| LEFT | RIGHT | 
| (no file at all) |  | 
 |   1 #!/usr/bin/env ruby | 
 |   2 # This script is a node classifier for Puppet that operates on top of Hiera | 
 |   3 # and uses a custom hosts.yaml config to map host roles. | 
 |   4  | 
 |   5 require 'getoptlong' | 
 |   6 require 'hiera' | 
 |   7 require 'socket' | 
 |   8 require 'yaml' | 
 |   9  | 
 |  10 # Where to search for the Hiera configuration | 
 |  11 HIERA_CONFIG = ENV.fetch('PUPPET_HIERA_CONFIG', '/etc/puppet/hiera.yaml') | 
 |  12 # Where to search for the Hosts configuration | 
 |  13 HOSTS_CONFIG = ENV.fetch('PUPPET_HOSTS_CONFIG', '/etc/puppet/infrastructure/hier
    a/private/hosts.yaml') | 
 |  14  | 
 |  15 # For logging and usage hints | 
 |  16 BASENAME = File.basename($0) | 
 |  17  | 
 |  18 # There's no need for any options beside the commonly exepected ones yet | 
 |  19 GetoptLong.new( | 
 |  20   ['--help', '-h', GetoptLong::NO_ARGUMENT] | 
 |  21 ).each do |opt, arg| | 
 |  22   case opt | 
 |  23  | 
 |  24     when '--help' | 
 |  25       puts <<-END | 
 |  26 Usage:  #{BASENAME} [hostname] | 
 |  27         #{BASENAME} example.com | 
 |  28         #{BASENAME} --help | 
 |  29  | 
 |  30 Options: | 
 |  31  | 
 |  32     --help, -h | 
 |  33         Display this help message and exit gracefully. | 
 |  34  | 
 |  35 Environment: | 
 |  36  | 
 |  37     PUPPET_HIERA_CONFIG=#{HIERA_CONFIG} | 
 |  38         Where to find the hiera configuration file. | 
 |  39     PUPPET_HOSTS_CONFIG=#{HOSTS_CONFIG} | 
 |  40         Where to find the hosts configuration file. | 
 |  41  | 
 |  42 END | 
 |  43       exit 0 | 
 |  44  | 
 |  45   end | 
 |  46 end | 
 |  47  | 
 |  48 # Only one additional non-option argument is allowed, in order to explicitly | 
 |  49 # specify a hostname to use instead of the default: | 
 |  50 case ARGV.length | 
 |  51   when 0 | 
 |  52     hostname = Socket.gethostname | 
 |  53   when 1 | 
 |  54     hostname = ARGV[0][/^[^.]+/] | 
 |  55   else | 
 |  56     STDERR.puts <<-END | 
 |  57 #{BASENAME}: unknown option: #{ARGV[0]} | 
 |  58 #{BASENAME}: try #{BASENAME} --help | 
 |  59 END | 
 |  60     exit 1 | 
 |  61 end | 
 |  62  | 
 |  63 # Extract the server -> hostname -> role information from the hosts | 
 |  64 # configuration file: | 
 |  65 begin | 
 |  66   config = YAML.load_file(HOSTS_CONFIG) | 
 |  67   servers = config.fetch("servers", {}) | 
 |  68   host = servers.fetch(hostname, {}) | 
 |  69   role = host.fetch("role", "default") | 
 |  70 rescue Exception => error | 
 |  71   STDERR.puts "#{BASENAME}: #{error.message}: #{HOSTS_CONFIG}" | 
 |  72   exit 1 | 
 |  73 end | 
 |  74  | 
 |  75 # Map Hiera data into the structure Puppet expects an ENC to generate (see | 
 |  76 # https://docs.puppetlabs.com/guides/external_nodes.html for more info): | 
 |  77 begin | 
 |  78   hiera = Hiera.new(:config => HIERA_CONFIG) | 
 |  79   scope = {'::hostname' => hostname, '::role' => role} | 
 |  80   classes = hiera.lookup('classes', {}, scope, nil, :hash) | 
 |  81   parameters = hiera.lookup('parameters', {}, scope, nil, :hash) | 
 |  82   parameters['role'] = role | 
 |  83   result = { 'classes' => classes, 'parameters' => parameters } | 
 |  84 rescue Exception => error | 
 |  85   STDERR.puts "#{BASENAME}: #{error.message}: #{HIERA_CONFIG}" | 
 |  86   exit 1 | 
 |  87 end | 
 |  88  | 
 |  89 puts result.to_yaml | 
 |  90  | 
| LEFT | RIGHT |