| 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 | 
|---|