Hiera: Node Data

Length: 00:21:02

Lesson Summary:

Now we're going to see how we can move down the hierarchy and provide node-specific values for a module. For this, we're going create a vhosts.pp file. Use pdk to generate a new class from the nginx directory:

# pdk new class vhosts

Open the manifests/vhosts.pp file that was just generated. We're not using any new resource types here, so feel free to copy and paste this in:

# Generate a virtual hosts file for nginx. Requires node-specific Hiera data
# @summary Generate a virtual hosts file for nginx
# @example
#   include nginx::vhosts
class nginx::vhosts (
  $vhosts_dir = $nginx::params::vhosts_dir,
) inherits nginx::params {
  file { "${nginx::vhosts_name}.conf":
    content => epp('nginx/vhosts.conf.epp'),
    ensure  => $nginx::vhosts_ensure,
    path    => "${vhosts_dir}/${nginx::vhosts_name}.conf",

  file { "$nginx::vhosts_root":
    ensure => 'directory',

Notice how we have one parameter to add to params.pp: the vhosts_dir value. We also have a couple of Hiera values in nginx::vhosts_name and vhosts_ensure. Pay attention, too, to how variables are provided when they're in larger double-quoted strings: instead of using $nginx::vhosts_server we use ${nginx::vhosts_server}.

What we want to focus on right now, however, is the content => epp('nginx/vhosts.conf.epp') line. What this does is populate a new file based on the given Puppet template, epp('nginx/vhosts.conf.epp'), which we need to add to the templates directory of our nginx module. Let's go ahead and do that:

# $EDITOR templates/vhosts.conf.epp

From here, we can copy in the virtual hosts template:

# This file is managed by Puppet; do not make changes by hand
server {
listen <%= $nginx::vhosts_port %>;
  listen [::]:<%= $nginx::vhostsvhosts_port %>;

  root <%= $nginx::vhosts_root %>;
  vhosts_name <%= $nginx::vhosts_server %> www.<%= $nginx::vhosts_server %>;

This is an .epp file, which means it uses Puppet's templating language. If you're familiar with Ruby, you also have the option to create an .erb file, but that is outside the scope of this quick start.

Notice how we don't have to do anything special to reference what will be our future Hiera values at the start of the file. We just need to call them with the <%= $variable_name %> format.

Save and exit when done.

We now want to go ahead and update our manifests/init.pp, manifests/params.pp, and data/common.yaml files:


  $vhosts_dir    = $nginx::params::vhosts_dir,
  String $package_ensure,
  String $config_ensure,
  String $service_ensure,
  Boolean $service_enable,
  Boolean $service_hasrestart,
  String $vhosts_port,
  String $vhosts_root,
  String $vhosts_name,
) inherits nginx::params {


    'RedHat': {
      $config_path = '/etc/nginx/nginx.conf'
      $config_source = 'puppet:///modules/nginx/rh-nginx.conf'
      $vhosts_dir = '/etc/nginx/conf.d/'
    'Debian': {
      $config_path = '/etc/nginx/nginx.conf'
      $config_source = 'puppet:///modules/nginx/deb-nginx.conf'
      $vhosts_dir = '/etc/nginx/sites-available/'


nginx::package_ensure: 'present'
nginx::config_ensure: 'present'
nginx::service_ensure: 'running'
nginx::service_enable: true
nginx::service_hasrestart: true
nginx::vhosts_ensure: 'present'

You may have noticed that we're still missing some Hiera data. But that's because we're going to be dropping back down into our production environment directory, and adding our Hiera data to a node-specific configuration. Move back down to production:

# cd ../..

Let's first check out our heira.yaml file in this directory:

# cat hiera.yaml

Like our nginx/hiera.yaml file, we have default data directory in the same directory as this file. If we were to use ls here we would see it. However, what we want to focus on is these lines:

  - name: "Per-node data (yaml version)"
    path: "nodes/%{::trusted.certname}.yaml"

These define where we'll be placing our per-node data, especially in the data/nodes/ directory in our production environment. The name of the file should be the trusted certname that Puppet uses to talk to the server, ending in .yaml. The hiera.yaml file defines this using the trusted.certname fact, referenced in the path.

Let's go ahead and add these files:

# mkdir data/nodes
# $EDITOR data/notes/AGENTLABSERVER.mylabserver.com.yaml

From here, we can add the Hiera values that aren't relevant to our common.yaml file, because they would be specific to the node or role:


nginx::vhosts_port: '80'
nginx::vhosts_root: '/var/www'
nginx::vhosts_name: 'the-puppet-project.com'
nginx::vhosts_ensure: 'present'

When we apply this module, the nginx::vhosts_ensure variable will take this value, not the one in the common.yaml file, although at this point they are the same.

Save and exit. We can now force a Puppet run on the agent node:

# puppet agent -t

Looking for some added challenge after this lesson? Think about how you would write an if state in the vhosts manifest so that the nginx::vhosts class would only be run if the nginx::vhosts_name value is provided.

This lesson is only available to Linux Academy members.

Sign Up To View This Lesson
Or Log In

Looking For Team Training?

Learn More