Sometimes it’s very difficult to see how hiera works and what values it might return. To help with troubleshooting, you can use the hiera cli to do lookups yourself. You obviously need to do this on a puppet master, or a node that’s configured to have all the hiera data in the same place the masters do. Here’s the hiera.yaml configuration:
# managed by puppet --- :backends: - yaml :logger: console :hierarchy: - "clientcert/%{clientcert}" - "puppet_role/%{puppet_role}" - global :yaml: :datadir: /etc/puppet/environments/%{environment}/hiera
Tier 1: global
Let’s look up the ntp::servers key from the global tier. One thing to note here is that the datadir includes the variable environment, so we will need to provide that tuple to the cli, like so:
[rnelson0@puppet ~]$ hiera ntp::servers environment=production ["0.pool.ntp.org", "2.centos.pool.ntp.org", "1.rhel.pool.ntp.org"]
It is important to note that the variables MUST match how they are referred to in hiera.yaml as there is no normalization. Thus, environment=production and ::environment=product are entirely different. Ensure you match the usage in your configuration.
Tier 2: puppet_role
Next, let’s look at the classes key, which exists at the puppet_role tier. Using the same command with a different key won’t work:
[rnelson0@puppet ~]$ hiera classes environment=production nil
Let’s turn on debug to see why:
[rnelson0@puppet ~]$ hiera classes environment=production --debug DEBUG: Tue Nov 17 01:42:27 +0000 2015: Hiera YAML backend starting DEBUG: Tue Nov 17 01:42:27 +0000 2015: Looking up classes in YAML backend DEBUG: Tue Nov 17 01:42:27 +0000 2015: Looking for data source global nil
It didn’t even look at the puppet_role tier! This is by design, because we did not provide that value. Let’s try it while specifying a puppet_role:
[rnelson0@puppet ~]$ hiera classes environment=production puppet_role=mysql role::mysql_server
Tier 3: clientcert
Now let’s take a look at the mysql::override_options hash:
[rnelson0@puppet ~]$ hiera mysql::server::override_options environment=production puppet_role=mysql nil
Dang, that’s apparently not found at that tier, it’s at the clientcert tier! We’ll have to add that to the arguments:
[rnelson0@puppet ~]$ hiera mysql::server::override_options environment=production puppet_role=mysql clientcert=mysql.nelson.va {"mysqld"=> {"log-bin"=>"/data/mysql/replog/mysql-bin.log", "relay-log"=>"/data/mysql/replog/slave-relay.log", "server-id"=>1, "bind-address"=>"0.0.0.0", "log_bin_index"=>"/data/mysql/replog/mysql-bin.log.index", "datadir"=>"/data/mysql", "auto-increment-increment"=>2, "auto-increment-offset"=>1, "socket"=>"/data/mysql/mysql.sock", "relay-log-index"=>"/data/mysql/replog/slave-relay-log.index"}, "mysqld_safe"=>{"socket"=>"/data/mysql/mysql.sock"}, "client"=>{"socket"=>"/data/mysql/mysql.sock"}}
Simplified arguments : Providing facts to hiera
That command line is getting pretty long, though. Let’s find another way to provide the variables and values that the command expects. A quick look at the possible arguments is promising:
[rnelson0@puppet ~]$ hiera --help Usage: hiera [options] key [default value] [variable='text'...] The default value will be used if no value is found for the key. Scope variables will be interpolated into %{variable} placeholders in the hierarchy and in returned values. -V, --version Version information -d, --debug Show debugging information -a, --array Return all values as an array -h, --hash Return all values as a hash -c, --config CONFIG Configuration file -j, --json SCOPE JSON format file to load scope from -y, --yaml SCOPE YAML format file to load scope from -m, --mcollective IDENTITY Use facts from a node (via mcollective) as scope -i, --inventory_service IDENTITY Use facts from a node (via Puppet's inventory service) as scope
We can load scope from a file! We need to create one first, though. Thankfully, facter has what we need:
[rnelson0@mysql ~]$ facter --help facter(8) -- Gather system information ====== SYNOPSIS -------- Collect and display facts about the system. USAGE ----- facter [-h|--help] [-t|--timing] [-d|--debug] [-p|--puppet] [-v|--version] [-y|--yaml] [-j|--json] [--plaintext] [--external-dir DIR] [--no-external-dir] [fact] [fact] [...]
Run facter with the puppet and yaml|json flags and save it in a file:
[rnelson0@mysql ~]$ sudo facter -py > mysql.yaml [rnelson0@mysql ~]$ grep role mysql.yaml puppet_role: mysql
Transfer the file to your puppet master. Before you use it, add any variables you need, like environment or clientcert, that aren’t part of the facter output but are important to your hierarchy:
[rnelson0@puppet ~]$ scp mysql:mysql.yaml ./ This server is intended for use by the Nelson family. All other use is unauthorized. rnelson0@mysql's password: mysql.yaml 100% 4808 4.7KB/s 00:00 [rnelson0@puppet ~]$ cat >>mysql.yaml environment: production clientcert: mysql.nelson.va
Remember that not all variables in your hierarchy, like clientcert, are considered facts. In this case, the configuration directive clientcert remains the same over time whereas the similar fact fqdn can vary. Though we generated the list using facter, we can add whatever we want to it.
You can now make a much simpler call to hiera that only varies by the key you’re looking up:
[rnelson0@puppet ~]$ hiera -y mysql.yaml ntp::servers ["0.pool.ntp.org", "2.centos.pool.ntp.org", "1.rhel.pool.ntp.org"] [rnelson0@puppet ~]$ hiera -y mysql.yaml classes role::mysql_server [rnelson0@puppet ~]$ hiera -y mysql.yaml mysql::server::override_options {"client"=>{"socket"=>"/data/mysql/mysql.sock"}, "mysqld"=> {"bind-address"=>"0.0.0.0", "log_bin_index"=>"/data/mysql/replog/mysql-bin.log.index", "relay-log"=>"/data/mysql/replog/slave-relay.log", "server-id"=>1, "datadir"=>"/data/mysql", "auto-increment-increment"=>2, "socket"=>"/data/mysql/mysql.sock", "log-bin"=>"/data/mysql/replog/mysql-bin.log", "relay-log-index"=>"/data/mysql/replog/slave-relay-log.index", "auto-increment-offset"=>1}, "mysqld_safe"=>{"socket"=>"/data/mysql/mysql.sock"}}
Summary
You now have a good idea of how to use hiera at the cli and how to do repeated lookups without excessive typing and with the actual facts from a node. Enjoy!