# File lib/puppet/parser/templatewrapper.rb, line 11 def initialize(scope) @__scope__ = scope end
Allow templates to access the defined classes
# File lib/puppet/parser/templatewrapper.rb, line 40 def classes scope.catalog.classes end
# File lib/puppet/parser/templatewrapper.rb, line 15 def file @__file__ end
# File lib/puppet/parser/templatewrapper.rb, line 76 def file=(filename) unless @__file__ = Puppet::Parser::Files.find_template(filename, scope.compiler.environment.to_s) raise Puppet::ParseError, "Could not find template '#{filename}'" end # We'll only ever not have a parser in testing, but, eh. scope.known_resource_types.watch_file(@__file__) end
Should return true if a variable is defined, false if it is not
# File lib/puppet/parser/templatewrapper.rb, line 35 def has_variable?(name) scope.include?(name.to_s) end
Ruby treats variables like methods, so we used to expose variables within scope to the ERB code via method_missing. As per RedMine #1427, though, this means that conflicts between methods in our inheritance tree (Kernel#fork) and variable names (fork => “yes/no”) could arise.
Worse, /new/ conflicts could pop up when a new kernel or object method was added to Ruby, causing templates to suddenly fail mysteriously when Ruby was upgraded.
To ensure that legacy templates using unqualified names work we retain the missing_method definition here until we declare the syntax finally dead.
# File lib/puppet/parser/templatewrapper.rb, line 66 def method_missing(name, *args) if scope.include?(name.to_s) return scope[name.to_s, {:file => @__file__, :lineproc => script_line_proc}] else # Just throw an error immediately, instead of searching for # other missingmethod things or whatever. raise Puppet::ParseError.new("Could not find value for '#{name}'", @__file__, script_line) end end
# File lib/puppet/parser/templatewrapper.rb, line 85 def result(string = nil) if string template_source = "inline template" else string = File.read(@__file__) template_source = @__file__ end # Expose all the variables in our scope as instance variables of the # current object, making it possible to access them without conflict # to the regular methods. benchmark(:debug, "Bound template variables for #{template_source}") do scope.to_hash.each do |name, value| if name.kind_of?(String) realname = name.gsub(/[^\w]/, "_") else realname = name end instance_variable_set("@#{realname}", value) end end result = nil benchmark(:debug, "Interpolated template #{template_source}") do template = ERB.new(string, 0, "-") template.filename = @__file__ result = template.result(binding) end result end
# File lib/puppet/parser/templatewrapper.rb, line 19 def scope @__scope__ end
# File lib/puppet/parser/templatewrapper.rb, line 30 def script_line script_line_proc.call end
# File lib/puppet/parser/templatewrapper.rb, line 23 def script_line_proc # find which line in the template (if any) we were called from # but defer to when necessary since fetching the caller information on # every variable lookup can be quite time consuming Proc.new { (caller.find { |l| l =~ /#{@__file__}:/ }||"")[/:(\d+):/,1] } end
# File lib/puppet/parser/templatewrapper.rb, line 117 def to_s "template[#{(@__file__ ? @__file__ : "inline")}]" end