Search code examples
yamlpuppethiera

Accessing multiple nested hiera values from puppet code (or "puppet lookup" cmd)


This is probably a very easy question, but it seems to be hard to search for the answer on the internet, or at least I spend too much time with this.

How can I access or directly make a list from all foo::bar values from hieradata file (below) in the Puppet module with lookup() or better way?

---
foo::bar:
    'some uniq name':
        baz: 12345
        ...

    'another uniq name':
        baz: 54321
        ...

So if it would be possible to use wildcards the key path would look like this -> foo::bar::*::baz.


Solution

  • This requires the use of the lookup function, a lambda iterator, and hash syntax notation, so it actually is not that easy, although the code may make it seem that way.

    We need to iterate over the values for the keys inside the foo::bar hash. We can start off with that via:

    lookup(foo::bar, Hash).each |String $key, Hash $value| {
      # first $key is 'some uniq name' string
      # first $value is 'some uniq name' hash
    }
    

    Now we need to access the values for the bar key inside each nested hash. We can do that by the normal syntax for accessing values of keys inside a hash:

    lookup(foo::bar, Hash).each |String $key, Hash $value| {
      $value['baz'] # first value is 12345
    }
    

    However, we need to store these values inside a variable so they are retained instead of being discarded after exiting the lambda scope. Therefore, we need to have a variable store the return value of the lambda iterator and use a lambda iterator that returns a modified array:

    $bazes = lookup(foo::bar, Hash).map |String $key, Hash $value| {
      $value['baz']
    }
    

    Thus achieving the goal of storing an array (or list as you put it) of all the baz values inside the hieradata. Although the code is short, it is arguably not that simple.

    Helpful Documentation -

    lookup: https://puppet.com/docs/puppet/5.2/hiera_use_function.html
    lambda iterator map: https://puppet.com/docs/puppet/5.3/function.html#map
    accessing hash values: https://puppet.com/docs/puppet/5.3/lang_data_hash.html#accessing-values