Using Hiera in Puppet

The data stored in Hiera can be retrieved by the Puppet Master while compiling the catalog using the Hiera functions. In our manifests, we can have something like the following:

$dns_servers = hiera("dns_servers")

Note that the name of the Puppet variable need not be the same as the Hiera one, so the preceding command can also be something like this:

$my_dns_servers = hiera("dns_servers")

This assigns the top value to the $my_dns_servers variable (the first one found while crossing the hierarchy of data sources) retrieved by Hiera for the key dns_servers.

We can also merge arrays and hashes here, so, in order to retrieve an array of all the values in the hierarchy's data sources of a given key and not just the first one, we can use hiera_array():

$my_dns_servers = hiera_array("dns_servers")

If we expect a hash value for a given key, we can use the hiera() function to retrieve the top value found, or hiera_hash() to merge all the found values in a single hash:

$openssh_settings = hiera_hash("openssh_settings")

All these Hiera functions may receive additional parameters, as follows:

  • Second argument: If present and not blank, then this is the default value to use if no value is found for the given key.
  • Third argument: This overrides the configured hierarchy adding a custom data source at the top of it. This might be useful in cases where we need to evaluate data using a logic not contemplated by the current hierarchy and for which it isn't worth the effort to add an extra layer in the global configuration.

The following code shows the usage of additional parameters:

$my_dns_servers = hiera("dns_servers","8.8.8.8","$country")

Dealing with hashes in Puppet code

With a hash, it is possible to express complex and structured data that has to be managed inside the Puppet code.

Remember that Hiera always returns the value of the first defined level keys, for example, we have a hash with nested hashes, as shown in the following code:

  network::interfaces_hash:
    eth0:
      ipaddress: 10.0.0.193
      netmask: 255.255.255.0
      network: 10.0.0.0
      broadcast: 10.0.0.255
      gateway: 10.0.0.1
      post_up:
        - '/sbin/ifconfig eth3 up'
        - '/sbin/ifconfig eth4 up'
    eth2:
      enable_dhcp: true
    eth3:
      auto: false
      method: manual
    eth4:
      auto: false
      method: manual

We can create a variable inside our Puppet code that loads it:

$int_hash = hiera('network::interfaces_hash')

Then, refer to single values inside its data structure with the following code:

$ip_eth0 = $int_hash['eth0']['ipaddress']

If we need to access this value from a template, we can directly write it in our erb file:

ipaddress <%= @int_hash['eth0']['ipaddress'] %>

Note

A complex hash like the preceding is typically used with a create_resources function as follows:

create_resources('network::interface', $interfaces_hash)

Here the custom network::interface defined is expected to accept as argument a hash to configure one or more network interfaces.

Puppet 3 automatic parameter lookup

With Puppet 3 Hiera is shipped directly within the core code, but the integration goes far beyond: an automatic Hiera lookup is done for each class' parameter using the $class::$argument key; this functionality is called data bindings or automatic parameter lookup.

An example is the following class definition:

class openssh (
  $template = 'openssh/sshd.config.erb',
) { . . . }

The value of $template will be evaluated according to the following logic:

  • If the user directly and explicitly passes the template argument, then its value is used:
    class { 'openssh':
      template => 'site/openssh/sshd_config.erb',
    }
  • If no value is explicitly set, Puppet 3 automatically looks for the Hiera key openssh::template.
  • Finally, if no value is found on Hiera, then the default 'openssh/sshd.config.erb' is used.

To emulate a similar behavior on Puppet versions earlier than version 3, we would write something like the following:

class openssh (
 $template = hiera("openssh::template",'openssh/sshd.config.erb'),
) { . . . }

Evolving usage patterns for class parameters

This strong integration has definitively boosted the adoption of Hiera and is changing the way Puppet code is organized and classes are declared.

Before Puppet 2.6, we could declare classes by just including them, optionally more than once in our catalog, using the following code:

include openssh

And, we could manage the behavior of the class just by setting variables and having them dynamically evaluated inside the class with something like the following code:

class openssh {
  file { 'sshd_config':
    content => template($openssh_template),
  }
}

This approach suffered the risks of having inconsistent values due to dynamic scoping of variables and parse ordering. Also, when using variables inside the module's code, it wasn't easy to understand which variables could affect the class's behavior, and there was not a public API, which is easily accessible.

The introduction of parameterized classes in Puppet 2.6 allowed classes to expose their arguments in a clear way using the following code:

class openssh (
  $template = 'openssh/sshd.config.erb',
) { . . . }

In order to pass them explicitly and consistently in a class declaration, use the following code:

class { 'openssh':
  template => 'site/openssh/sshd_config.erb',
}

But the fact that we can declare a specific class, using parameters, only once in a node's catalog presented new challenges on how our custom code had to be organized. We could not include classes wherever needed but we had to reorganize our manifests in order to avoid duplicate declarations.

From Puppet 3 onwards, it is possible to have the best of both worlds, we can use the original way to include classes:

include openssh

But we can also be sure that the template parameter is always and consistently evaluated according to the value of the Hiera key openssh::template.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.171.52