Iterate over a deeply nested hiera hash in puppet manifest

h3r2on picture h3r2on · Nov 15, 2016 · Viewed 10k times · Source

I'm working on building a structure for my webservers. I have my setup in hiera, but I can't seem to get puppet to give back the correct types.

In common.yaml

vhosts:
  hostname:
    sitename:
      app_url: value
      app_type: value

I have multiple sites per vhost and multiple vhosts. In my manifest I'm going to be creating the folder structure and other setup tasks, but for for now I can't even get it to iterate over the sites.

Current manifest:

define application($app_name, $app_url) {
  notice("App Type: ${app_type}")
  notice("App Url: ${app_url}")
}

$vhosts = hiera('vhosts')

$vhosts.each |$vhost| {
  create_resources(application, $vhost)
}

The error I get is that create_resources requires a Hash. However, if I type cast $vhost I get that it's not a Hash but a Tuple.

How did I get a Tuple out of my yaml hash? Is there a better way to iterate over this data set to get what I need?

Answer

Matt Schuchard picture Matt Schuchard · Nov 15, 2016

Why you had a tuple is explained at https://docs.puppet.com/puppet/latest/reference/function.html#each in the second example.

Given a Hiera hash like:

vhosts:
  hostname:
    sitename:
      app_url: value
      app_type: value

You can iterate over it like the following:

hiera_hash('vhosts').each |String $hostname, Hash $hostname_hash| {
  # $hostname is 'hostname'
  # $hostname_hash is { hostname => { sitename => { app_url => value, app_type => value } } }
  $hostname_hash.each |String $sitename, Hash $sitename_hash| {
    # $sitename is 'sitename'
    # $sitename_hash is { sitename => { app_url => value, app_type => value } }
    $sitename_hash.each |String $key, String $value| {
      # first loop $key is app_url and $value is 'value'
      # second loop $key is app_type and $value is 'value'
    }
  }
}

You can, of course, access hash values at any point like

hiera_hash('vhosts')['hostname']['sitename']['app_url']

which will result in value.

If you are trying to do create_resources(), then you probably want to construct the hash as a hash of resource hashes. For example, Hiera:

packages:
  gcc:
    ensure: installed
  gfortran:
    ensure: absent

with Puppet:

create_resources(hiera_hash('packages'))