Thank you for your detailed response. It appears the primary problem could be in the hiera documentation, then, as it still refers to calling conventions that are apparently now completely outdated. I've read your blog before but didn't pick up on the meaning of the article about epp templates.
On Tuesday, May 26, 2015 at 8:16:23 PM UTC-4, Henrik Lindberg wrote: > > On 2015-23-05 24:39, Maura Dailey wrote: > > Yes, I know this practice is discouraged in the documentation, but the > > updated hiera 2.0 documentation also assures me that it's supported and > > implies no changes to puppet 3.x manifests or templates are required. > > > > This networking.erb file used to work in puppet 3.8 (this is a cruddy > > example, I use callouts to hiera data EXTENSIVELY in dozens of much more > > complicated configuration templates): > > | > > NETWORKING=yes > > NETWORKING_IPV6=no > > HOSTNAME=<%=@fqdn%> > > GATEWAY=<%=scope.function_hiera(['gateway'])%> > > NOZEROCONF=yes > > | > > > > Now in puppet 4.1, I get the following: > > | > > Info:Retrievingpluginfacts > > Info:Retrievingplugin > > Info:Loadingfacts > > Error:Couldnotretrieve catalog fromremote server:Error400on > > SERVER:EvaluationError:Errorwhileevaluating a FunctionCall,Failedto > > parse templatenetworking/network.erb: > > > Filepath:/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/parser/functions/fail.rb > > > > Line:3 > > Detail:hiera()has been converted to 4xAPI > > | > > > > I checked the hiera 2.0 documentation on the names of functions > > here: > http://docs.puppetlabs.com/hiera/latest/puppet.html#hiera-lookup-functions > > > > and the hiera 2.0 documention on how to call them from inside templates > > here: > > > http://docs.puppetlabs.com/hiera/latest/puppet.html#using-the-lookup-functions-from-templates > > > > > What am I missing? I tried to read the Ruby source for hints, but I'm > > more of a Python person and couldn't find any documentation on how to > > call the 4x API functions correctly. Thanks in advance for any > assistance. > > You have unfortunately run into a problem with a puppet 3.x function > (template()) making a call to a function that have been migrated to the > 4.x function API. In the new API functions are not called via scope, and > a 3x function does not have the needed information to do so easily. > > You can get around the problem by using the new templating system EPP > where the logic is written in the Puppet Language. This is also the long > term direction (The more safe, and better specified EPP over ERB where > you are exposed to the internals of the puppet runtime). > > The snippet you showed can be written like this in EPP: > > NETWORKING=yes > NETWORKING_IPV6=no > HOSTNAME=<%= $fqdn %> > GATEWAY=<%= hiera('gateway') %> > NOZEROCONF=yes > > I understand this may be a bit of work when you have many and > complicated templates esp. if you rely on the internals of Puppet. > For regular templates that only access variables, it should be as easy > as replacing a @varname with $varname). > I did a quick test using this syntax, and this appears to work perfectly. This will work for 99% of my existing templates, I think. (I had to switch the calling convention inside the pp file to call epp instead of template before it stopped giving me errors. Oops.) > I think a ticket should be logged regarding the difficulty of calling a > 4x function (this has popped up in other contexts (where it was possible > to work around the issue more easily)). > > What is needed is a calling mechanism that is agnostic; a function that > is written with the 4.x. API simply uses the method > 'call_function(<NAME>, <ARG1>, <ARG2>, ...)' and it calls either a 3.x > or a 4.x function. A similar thing is needed in an accessible way from > within a 3.x. function or template (e.g. scope.call_function with the > same signature as in the 4.x API). The fix would entail something like > what I am describing below... > > Alternatively, to get past the problem if you do not want to move to EPP > right away here is how to call a 4.x function (but this is not > considered API, as we are planning refactoring how calls are made - they > are done in several different ways atm): > > # Note that this requires >= 3.8.1 with future parser or 4.1.0. > # > def call_function(name, args, scope, &block) > # Get the loader that serves the environment - i.e for a call that > # comes from within the environment. This makes all functions in the > # environment (all modules, and environment private function) visible) > # to the caller. (This is somewhat cheating wrt. visibility - i.e. > # 'private' functions which will be supported in a later version). > # > loader = scope.compiler.loaders.private_environment_loader > if loader && func = loader.load(:function, name) > return func.call(scope, *args, &block) > end > # the function was not found... deal with it > end > > The above is a modified version of what is used in the puppet runtime, > and should be possible to use in a template - even as a one-liner (in > your case: > > scope.compiler.loaders.private_environment_loader.load(:function, > 'hiera').call(scope, 'gateway') > > Thanks for the extra details here. Obviously, this is fairly low level, and I don't want to find things breaking out from under me in a future puppet release! I've gone over my existing templates and the EPP format should be sufficient to meet my needs without more programmatic changes. > Note that the real implementation is also able to call 3.x functions, > and is written to support visibility rules (i.e. handling private > functions. See the method 'call_function' defined in > puppet/pops/evaluator/runtime3_support.rb) if you want to look at the > complete implementation). > > Regards > - henrik > -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/7f7b4d1b-0299-4925-9298-39dcc36d372e%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.