Puppet: v4.2.1
Hiera: v3.0.1
Facter: v3.0.2
Ruby: 2.1.6p336
Platform: Windows.
Came across an interesting behaviour when using hiera that was unexpected (to me anyway). I don't necessarily think its a bug, but I thought it worth sharing for others who may come across it. Keep in mind that this is just an example to illustrate the behaviour and not a recommendation about how to write Puppet/Hiera (maybe its even an anti-pattern !)
Lets say you have a class :
class hiera_binding_test (
$version,
$install_folder) {
notice("version is: ${version}")
notice("install_folder is: ${install_folder}")
}
a hiera.yaml :-
:hierarchy:
- common
:backends:
- yaml
:yaml:
:datadir: E:/Temp/puppetTests/hiera_binding_test/hiera
and a hiera common.yaml :-
hiera_binding_test::version: '1.0'
hiera_binding_test::install_folder: "c:/apps/myapp/%{hiera_binding_test::version}/bin"
Note that in common.yaml that the 'install_folder' makes use of the 'version' class param.
If when the hiera_binding_test class is called the 'version' param is passed explicitly (regardless of whether 'install_folder' is or not), the outcome is as expected :-
Notice: Scope(Class[Hiera_binding_test]): version is: 1.0
Notice: Scope(Class[Hiera_binding_test]): install_folder is: c:/apps/myapp/1.0/bin
However, if we just use 'include' (which is obviously the patern we want to use by preference) :-
include hiera_binding_test
the outcome is NOT correct (version is not available) :-
Notice: Scope(Class[Hiera_binding_test]): version is: 1.0
Notice: Scope(Class[Hiera_binding_test]): install_folder is: c:/apps/myapp//bin
So, even though the 'version' param was resolved by automatic parameter binding (as we can see from the first line) that value is NOT available to the the hiera expression for install_folder:
c:/apps/myapp/%{hiera_binding_test::version}/binInterestingly, if I had implemented an inherited params.pp class, like this :-
class hiera_binding_test (
$version,
$install_folder) inherits hiera_binding_test::params {
notice("version is: ${version}")
notice("install_folder is: ${install_folder}")
}
class hiera_binding_test::params {
$version = '1.1'
$install_folder = 'c:/apps/someotherapp/1.0/bin'
}
a value for 'version' *would* be available (1.1) to the install_folder expression in hiera :-
Notice: Scope(Class[Hiera_binding_test]): version is: 1.0
Notice: Scope(Class[Hiera_binding_test]): install_folder is: c:/apps/myapp/1.1/bin
Note that params.pp ONLY supplied the 'version' value for the hiera expression
%{hiera_binding_test::version}. Values for the class params 'version' and 'install_folder' STILL came from hiera, as we can see from the output.
Finally, if you are one of those people that prefer to NOT provide defaults for class params (so you can catch mis-configured classes at compile time), if you accidentally left out [say] 'install_folder' from common.yaml, you will still get the expected error despite the fact that it is declared in params.pp :
Error: Evaluation Error: Error while evaluating a Function Call, Must pass install_folder to Class[Hiera_binding_test] at E:/Temp/puppetTests/hiera_binding_test/modules/hiera_binding_test/examples/init.pp:1:1 on node xxx
I'm not 100% sure why this behaviour is as it is (maybe something to do with precedence and/or the order of evaulation of classes (including inherited) versus when hiera comes in), not sure. But if anyone knows for certain why I would be interested.
Kind Regards
Fraser.