[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, master, updated. debian/0.24.6-1-356-g5718585

James Turnbull james at lovedthanlost.net
Fri Jan 23 14:20:45 UTC 2009


The following commit has been merged in the master branch:
commit 03c76deb60927375e9b35c74a903130930ffddf2
Author: Daniel Pittman <daniel at rimspace.net>
Date:   Fri Jul 18 15:21:57 2008 +1000

    Expose all puppet variables as instance member variables of the template wrapper.
    This helps resolve redmine #1427, by providing a safe mechanism to access variables.
    
     * Implement Puppet::Parser::Scope#to_hash, which returns a hash containing all the
       variable bindings in the current and, optionally, parent scope.
     * Use that to set instance member variables into Puppet::Parser::Templatewrapper
     * Report the time taken for variable binding at debug level, to help identify any
       performance regression that is encountered in the real world.
     * Rename the @scope and @file members of the template wrapper, to avoid clashing
       with a scope variable exposed within puppet.
    
    Signed-off-by: Daniel Pittman <daniel at rimspace.net>
    (cherry picked from commit ba220b41e4f509f2632e2664d332e49b20a70ea7)

diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index a6e43e7..32b127a 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -183,6 +183,25 @@ class Puppet::Parser::Scope
         end
     end
 
+    # Return a hash containing our variables and their values, optionally (and
+    # by default) including the values defined in our parent.  Local values
+    # shadow parent values.
+    def to_hash(recursive = true)
+        if recursive and parent then
+            target = parent.to_hash(recursive)
+        end
+        target ||= Hash.new
+        @symtable.keys.each { |name| 
+            value = @symtable[name]
+            if value == :undef then
+                target.delete(name)
+            else
+                target[name] = value 
+            end
+        }
+        return target
+    end
+
     def namespaces
         @namespaces.dup
     end
diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb
index 4790cea..298428f 100644
--- a/lib/puppet/parser/templatewrapper.rb
+++ b/lib/puppet/parser/templatewrapper.rb
@@ -5,36 +5,63 @@ class Puppet::Parser::TemplateWrapper
     include Puppet::Util
     Puppet::Util.logmethods(self)
 
-    def initialize(scope, file)
-        @scope = scope
-        @file = Puppet::Module::find_template(file, @scope.compiler.environment)
+    def initialize(scope, filename)
+        @__scope__ = scope
+        @__file__ = Puppet::Module::find_template(filename, scope.compiler.environment)
 
-        unless FileTest.exists?(@file)
+        unless FileTest.exists?(file)
             raise Puppet::ParseError,
                 "Could not find template %s" % file
         end
 
         # We'll only ever not have a parser in testing, but, eh.
-        if @scope.parser
-            @scope.parser.watch_file(@file)
+        if scope.parser
+            scope.parser.watch_file(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 #{file}") do
+            scope.to_hash.each { |name, value| 
+                instance_variable_set("@#{name}", value) 
+            }
+        end
+    end
+
+    def scope
+        @__scope__
+    end
+
+    def file
+        @__file__
     end
 
     # Should return true if a variable is defined, false if it is not
     def has_variable?(name)
-        if @scope.lookupvar(name.to_s, false) != :undefined
+        if scope.lookupvar(name.to_s, false) != :undefined
             true
         else
             false
         end
     end
 
-    # Ruby treats variables like methods, so we can cheat here and
-    # trap missing vars like they were missing methods.
+    # 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.
     def method_missing(name, *args)
         # We have to tell lookupvar to return :undefined to us when
         # appropriate; otherwise it converts to "".
-        value = @scope.lookupvar(name.to_s, false)
+        value = scope.lookupvar(name.to_s, false)
         if value != :undefined
             return value
         else
@@ -47,8 +74,8 @@ class Puppet::Parser::TemplateWrapper
 
     def result
         result = nil
-        benchmark(:debug, "Interpolated template #{@file}") do
-            template = ERB.new(File.read(@file), 0, "-")
+        benchmark(:debug, "Interpolated template #{file}") do
+            template = ERB.new(File.read(file), 0, "-")
             result = template.result(binding)
         end
 
@@ -56,7 +83,7 @@ class Puppet::Parser::TemplateWrapper
     end
 
     def to_s
-        "template[%s]" % @file
+        "template[%s]" % file
     end
 end
 

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list