I have a Puppet class which uses this format to create a variable for a deep merge later.
$config = {
'foo' => {
'fvar1' => 'fvar1-string',
'fvar2' => 'fvar2-string',
},
'bar' => {
'bvar1' => 'bvar1-string',
'bvar2' => 'bvar2-string',
},
}
I am working to refactor the code so that the data is managed in hiera instead of within the code itself. In doing so, I would prefer to only need a single hiera lookup for each hash (foo and bar). Is this possible?
Here is what I have attempted so far:
Hiera data:
role::fb:
foo:
fvar1: 'fvar1-string'
fvar2: 'fvar2-string'
bar:
bvar1: 'bvar1-string'
bvar2: 'bvar2-string'
Code:
class test {
$config = {
'foo' => hiera('role::fb::foo', undef),
'bar' => hiera('role::fb::bar', undef),
}
notify { "Config: ${config}": }
}
include test
Output:
[root@puppetclient1 ~]# puppet agent -t
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Retrieving locales
Info: Caching catalog for puppetclient1.home.arpa
Info: Applying configuration version '1684256670'
Notice: Config: {foo => , bar => }
Notice: /Stage[main]/Test/Notify[Config: {foo => , bar => }]/message: defined 'message' as 'Config: {foo => , bar => }'
Notice: Applied catalog in 0.01 seconds
[root@puppetclient1 ~]#
My desired output is that foo and bar contain the contents of the hiera data, including fvar{1,2} and bvar{1,2} respectively.
EDIT: John Bollinger's answer below has helped me in my understanding tremendously. I have been able to recreate the solutions in Puppet 5. However, I should have mentioned this earlier, I have a need for compatibility with Puppet 3 at the moment. When running the code against version 3.8.7, I run into a syntax error and compilation fails.
Updated code (utilizing hiera() for version compatibility here):
class fb {
$config = {
'foo' => hiera('role::fb', undef)['foo'],
'bar' => hiera('role::fb', undef)['bar'],
}
notify { "Config: ${config}": }
}
include fb
Error when using Puppet 3.8.7:
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Syntax error at '['; expected ']' at /etc/puppet/environments/production/modules/A/manifests/fb.pp:3 on node puppetclient1.home.arpa
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run
Final edit:
I spoke too soon. John's suggestion stating "promote the members to top-level keys" worked like a charm. I apparently had a syntax issue during my first attempt. Thanks!
The most natural mapping of your data from manifest code to Hiera would be this:
The most natural way to retrieve that in your manifest would be via automatic data binding to a class parameter:
Automatic data binding relies on the Hiera key having the form
module_name::class_name::param_name.If you prefer, however, then you can still perform an explicit lookup:
Explicit lookup can be performed for any key, so if this is your target case then you are not limited to keys of the
module_name::class_name::specific_nameform.If you want only one or the other member hash at a time, then you can retrieve the whole config and then select the wanted value from it:
Alternatively, if you want the ability to look up the
fooandbarmembers individually, and are ok with losing the ability to look up the whole config at once, then you can simply promote the members to top-level keys:Additional note: following @MattSchuchard's comment, if you want
lookup()to provide a default value, evenundef, when the key is not found, then you need to specify that in thelookup()call. This is different from the behavior of the legacyhiera()function. There's more than one way to do that, but if you want to default toundefashiera()did, then the simplest is to add the three optional arguments to thelookup()call, with the last of those being the wanted default value:If you do not specify a default and the requested key is not found, then catalog building will fail.