This post probably describes a bug, but I haven’t had the time yet to determine if this still exists in Puppet 2.6.x. Instead, here’s a post that will hopefully help out someone else having the same problem.
The other day, I was writing some custom parser functions for our Puppet 0.25.x install. In the interest of reusability, the idea was to keep the functions small and composable, and have them call each other in a nice, maintainable way in order to prevent code duplication.
As per the Puppet documentation, Puppet functions are called from Ruby by prefixing the function name with function_:
module Puppet::Parser::Functions newfunction(:my_function) do |args| # Puppet functions expect an array containing all of the arguments, # so we have to wrap our single string argument function_notice(["Called notice() from my_function()"]) end end
This worked great for calling built-in functions, but when I tried to call one of my own functions from another of my own functions, Puppet would just hang:
my_function.rb:
module Puppet::Parser::Functions newfunction(:my_function) do |args| function_my_other_function(args) end end
my_other_function.rb:
module Puppet::Parser::Functions newfunction(:my_other_function) # Never get here end end
After a bunch of debugging, I found that the Puppet autoloader seemed to be spinning itself into an infinite loop trying to locate and load my_other_function when it was called from my_function.rb. The solution was to manually require the file containing that function:
require File.join([File.expand_path(File.dirname(__FILE__)), 'my_other_function.rb']) module Puppet::Parser::Functions newfunction(:my_function) do |args| function_my_other_function(args) end end
The above assumes, of course, that the functions are in the same directory as one another.
With the dependency loaded, the custom function should work the same as any other parser function.