Class: Puppet::Parser::TemplateWrapper

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/puppet/parser/templatewrapper.rb

Constant Summary

Constants included from Util

Util::AbsolutePathPosix, Util::AbsolutePathWindows, Util::DEFAULT_POSIX_MODE, Util::DEFAULT_WINDOWS_MODE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util

absolute_path?, activerecord_version, benchmark, binread, chuser, classproxy, #execfail, #execpipe, execute, execute_posix, execute_windows, logmethods, memory, path_to_uri, proxy, replace_file, safe_posix_fork, symbolize, symbolizehash, symbolizehash!, synchronize_on, thinmark, #threadlock, uri_to_path, wait_for_output, which, withumask

Methods included from Util::POSIX

#get_posix_field, #gid, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid

Constructor Details

#initialize(scope) ⇒ TemplateWrapper

Returns a new instance of TemplateWrapper.



11
12
13
# File 'lib/puppet/parser/templatewrapper.rb', line 11

def initialize(scope)
  @__scope__ = scope
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

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.



60
61
62
63
64
65
66
67
68
69
# File 'lib/puppet/parser/templatewrapper.rb', line 60

def method_missing(name, *args)
  value = scope.lookupvar(name.to_s,:file => @__file__,:line => script_line)
  if value != :undefined
    return value
  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

Instance Attribute Details

#scopeObject



19
20
21
# File 'lib/puppet/parser/templatewrapper.rb', line 19

def scope
  @__scope__
end

Instance Method Details

#all_tagsObject

Allow templates to access the all the defined tags



44
45
46
# File 'lib/puppet/parser/templatewrapper.rb', line 44

def all_tags
  scope.catalog.tags
end

#classesObject

Allow templates to access the defined classes



34
35
36
# File 'lib/puppet/parser/templatewrapper.rb', line 34

def classes
  scope.catalog.classes
end

#fileObject



15
16
17
# File 'lib/puppet/parser/templatewrapper.rb', line 15

def file
  @__file__
end

#file=(filename) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/puppet/parser/templatewrapper.rb', line 71

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

#has_variable?(name) ⇒ Boolean

Should return true if a variable is defined, false if it is not

Returns:

  • (Boolean)


29
30
31
# File 'lib/puppet/parser/templatewrapper.rb', line 29

def has_variable?(name)
  scope.lookupvar(name.to_s, :file => @__file__, :line => script_line) != :undefined
end

#result(string = nil) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/puppet/parser/templatewrapper.rb', line 80

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

#script_lineObject



23
24
25
26
# File 'lib/puppet/parser/templatewrapper.rb', line 23

def script_line
  # find which line in the template (if any) we were called from
  (caller.find { |l| l =~ /#{@__file__}:/ }||"")[/:(\d+):/,1]
end

#tagsObject

Allow templates to access the tags defined in the current scope



39
40
41
# File 'lib/puppet/parser/templatewrapper.rb', line 39

def tags
  scope.tags
end

#to_sObject



112
113
114
# File 'lib/puppet/parser/templatewrapper.rb', line 112

def to_s
  "template[#{(@__file__ ? @__file__ : "inline")}]"
end