[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, upstream, updated. 0.25.5-639-g8f94f35

test branch puppet-dev at googlegroups.com
Wed Jul 14 10:34:33 UTC 2010


The following commit has been merged in the upstream branch:
commit ccc869ea48397235d7ba2a5695424eee4923cb9d
Author: Markus Roberts <Markus at reality.com>
Date:   Thu Jun 10 22:51:12 2010 -0700

    Part 2 of fix for #1175 (functions in environments)
    
    Jesse and I are shooting for the minimal viable fix here, with the idea that
    a great deal of refactoring is needed but isn't appropriate at this time.  The
    changes in this commit are:
    
    * Index the function-holding modules by environment
    
    * We need to know the "current environment" when we're defining a function so
    we can attach it to the proper module, and this information isn't dynamically
    available when user-defined functions are being created (we're being called by
    user written code that doesn't "know" about environments) so we cheat and
    stash the value in Puppet::Node::Environment
    
    * since we must do this anyway, it turns out to be cleaner & safer to do the
    same when we are evaluating a functon.  This is the main change from the prior
    version of this patch.
    
    * Add a special *root* environment for the built in functions, and extend all
    scopes with it.
    
    * Index the function characteristics (name, type, docstring, etc.) by environment
    
    * Make the autoloader environment aware, so that it uses the modulepath for the
    specified environment rather than the default
    
    * Turn off caching of the modulepath since it potentially changes for each node
    
    * Tweak tests that weren't environment aware

diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb
index d1a126a..4363eea 100644
--- a/lib/puppet/node/environment.rb
+++ b/lib/puppet/node/environment.rb
@@ -41,6 +41,18 @@ class Puppet::Node::Environment
         @seen[symbol] = obj
     end
 
+    def self.current
+        @current || root
+    end
+
+    def self.current=(env)
+        @current = new(env)
+    end
+
+    def self.root
+        @root ||= new(:'*root*') 
+    end
+
     # This is only used for testing.
     def self.clear
         @seen.clear
diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb
index 4c3a5dc..ba49779 100644
--- a/lib/puppet/parser/ast/function.rb
+++ b/lib/puppet/parser/ast/function.rb
@@ -13,7 +13,7 @@ class Puppet::Parser::AST
         def evaluate(scope)
 
             # Make sure it's a defined function
-            unless @fname
+            unless @fname = Puppet::Parser::Functions.function(@name)
                 raise Puppet::ParseError, "Unknown function %s" % @name
             end
 
@@ -48,7 +48,6 @@ class Puppet::Parser::AST
 
             super(hash)
 
-             @fname = Puppet::Parser::Functions.function(@name)
             # Lastly, check the parity
         end
 
diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb
index f869383..4357a3a 100644
--- a/lib/puppet/parser/compiler.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -127,6 +127,7 @@ class Puppet::Parser::Compiler
                 @environment = nil
             end
         end
+        Puppet::Node::Environment.current = @environment
         @environment
     end
 
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
index 6ba3669..e0973c1 100644
--- a/lib/puppet/parser/functions.rb
+++ b/lib/puppet/parser/functions.rb
@@ -6,7 +6,7 @@ require 'puppet/parser/scope'
 # class.
 module Puppet::Parser::Functions
 
-    @functions = {}
+    @functions = Hash.new { |h,k| h[k] = {} }
     @modules = {}
 
     class << self
@@ -24,15 +24,17 @@ module Puppet::Parser::Functions
         @autoloader
     end
 
+    Environment = Puppet::Node::Environment
+
     def self.environment_module(env = nil)
-        @module ||= Module.new
+        @modules[ env || Environment.current || Environment.root ] ||= Module.new
     end
 
     # Create a new function type.
     def self.newfunction(name, options = {}, &block)
         name = symbolize(name)
 
-        if @functions.include? name
+        if functions.include?(name)
             raise Puppet::DevError, "Function %s already defined" % name
         end
 
@@ -46,10 +48,10 @@ module Puppet::Parser::Functions
         environment_module.send(:define_method, fname, &block)
 
         # Someday we'll support specifying an arity, but for now, nope
-        #@functions[name] = {:arity => arity, :type => ftype}
-        @functions[name] = {:type => ftype, :name => fname}
+        #functions[name] = {:arity => arity, :type => ftype}
+        functions[name] = {:type => ftype, :name => fname}
         if options[:doc]
-            @functions[name][:doc] = options[:doc]
+            functions[name][:doc] = options[:doc]
         end
     end
 
@@ -57,11 +59,11 @@ module Puppet::Parser::Functions
     def self.rmfunction(name)
         name = symbolize(name)
 
-        unless @functions.include? name
+        unless functions.include? name
             raise Puppet::DevError, "Function %s is not defined" % name
         end
 
-        @functions.delete(name)
+        functions.delete name
 
         fname = "function_" + name.to_s
         environment_module.send(:remove_method, fname)
@@ -71,15 +73,11 @@ module Puppet::Parser::Functions
     def self.function(name)
         name = symbolize(name)
 
-        unless @functions.include? name
-            autoloader.load(name)
+        unless functions.include?(name) or functions(Puppet::Node::Environment.root).include?(name)
+            autoloader.load(name,Environment.current || Environment.root)
         end
 
-        if @functions.include? name
-            return @functions[name][:name]
-        else
-            return false
-        end
+        ( functions(Environment.root)[name] || functions[name] || {:name => false} )[:name]
     end
 
     def self.functiondocs
@@ -87,7 +85,7 @@ module Puppet::Parser::Functions
 
         ret = ""
 
-        @functions.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, hash|
+        functions.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, hash|
             #ret += "%s\n%s\n" % [name, hash[:type]]
             ret += "%s\n%s\n" % [name, "-" * name.to_s.length]
             if hash[:doc]
@@ -102,22 +100,13 @@ module Puppet::Parser::Functions
         return ret
     end
 
-    def self.functions
-        @functions.keys
+    def self.functions(env = nil)
+        @functions[ env || Environment.current || Environment.root ]
     end
 
     # Determine if a given function returns a value or not.
     def self.rvalue?(name)
-        name = symbolize(name)
-
-        if @functions.include? name
-            case @functions[name][:type]
-            when :statement; return false
-            when :rvalue; return true
-            end
-        else
-            return false
-        end
+        (functions[symbolize(name)] || {})[:type] == :rvalue
     end
 
     # Runs a newfunction to create a function for each of the log levels
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 991e123..140c8c1 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -505,6 +505,7 @@ class Puppet::Parser::Scope
     private
 
     def extend_with_functions_module
-        extend Puppet::Parser::Functions.environment_module(compiler ? environment : nil)
+        extend Puppet::Parser::Functions.environment_module(Puppet::Node::Environment.root)
+        extend Puppet::Parser::Functions.environment_module(compiler ? environment : nil )
     end
 end
diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb
index 3268eae..bcb7fa3 100644
--- a/lib/puppet/parser/type_loader.rb
+++ b/lib/puppet/parser/type_loader.rb
@@ -114,7 +114,7 @@ class Puppet::Parser::TypeLoader
     end
 
     def parse_file(file)
-        Puppet.debug("importing '#{file}'")
+        Puppet.debug("importing '#{file}' in environment #{environment}")
         parser = Puppet::Parser::Parser.new(environment)
         parser.file = file
         parser.parse
diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb
index 7358618..4a687bf 100644
--- a/lib/puppet/util/autoload.rb
+++ b/lib/puppet/util/autoload.rb
@@ -73,12 +73,12 @@ class Puppet::Util::Autoload
 
     # Load a single plugin by name.  We use 'load' here so we can reload a
     # given plugin.
-    def load(name)
+    def load(name,env=nil)
         return false if named_file_missing?(name)
 
         path = name.to_s + ".rb"
 
-        searchpath.each do |dir|
+        searchpath(env).each do |dir|
             file = File.join(dir, path)
             next unless file_exist?(file)
             begin
@@ -130,25 +130,22 @@ class Puppet::Util::Autoload
     end
 
     # The list of directories to search through for loadable plugins.
-    # We have to hard-code the ttl because this library is used by
-    # so many other classes it's hard to get the load-order such that
-    # the defaults load before this.
-    cached_attr(:searchpath, :ttl => 15) do
-        search_directories.collect { |d| File.join(d, @path) }.find_all { |d| FileTest.directory?(d) }
+    def searchpath(env=nil)
+        search_directories(env).collect { |d| File.join(d, @path) }.find_all { |d| FileTest.directory?(d) }
     end
 
-    def module_directories
+    def module_directories(env=nil)
         # We have to require this late in the process because otherwise we might have
         # load order issues.
         require 'puppet/node/environment'
-        Puppet::Node::Environment.new.modulepath.collect do |dir|
+        Puppet::Node::Environment.new(env).modulepath.collect do |dir|
             Dir.entries(dir).reject { |f| f =~ /^\./ }.collect { |f| File.join(dir, f) }
         end.flatten.collect { |d| [File.join(d, "plugins"), File.join(d, "lib")] }.flatten.find_all do |d|
             FileTest.directory?(d)
         end
     end
 
-    def search_directories(dummy_argument=:work_arround_for_ruby_GC_bug)
-        [module_directories, Puppet[:libdir].split(File::PATH_SEPARATOR), $:].flatten
+    def search_directories(env=nil)
+        [module_directories(env), Puppet[:libdir].split(File::PATH_SEPARATOR), $:].flatten
     end
 end
diff --git a/spec/unit/parser/functions/defined.rb b/spec/unit/parser/functions/defined.rb
index 0da8c4a..03b0ef9 100755
--- a/spec/unit/parser/functions/defined.rb
+++ b/spec/unit/parser/functions/defined.rb
@@ -5,9 +5,9 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
 describe "the 'defined' function" do
 
     before :each do
-        @scope = Puppet::Parser::Scope.new()
+        Puppet::Node::Environment.stubs(:current).returns(nil)
         @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo"))
-        @scope.compiler = @compiler
+        @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
     end
 
     it "should exist" do
diff --git a/spec/unit/parser/scope.rb b/spec/unit/parser/scope.rb
index 7093279..b14b2d3 100755
--- a/spec/unit/parser/scope.rb
+++ b/spec/unit/parser/scope.rb
@@ -59,10 +59,12 @@ describe Puppet::Parser::Scope do
     end
 
     describe "when initializing" do
-        it "should extend itself with its environment's Functions module" do
+        it "should extend itself with its environment's Functions module as well as the default" do
             env = Puppet::Node::Environment.new("myenv")
             compiler = stub 'compiler', :environment => env
-            mod = Module.new
+            mod      = Module.new
+            root_mod = Module.new
+            Puppet::Parser::Functions.expects(:environment_module).with(Puppet::Node::Environment.root).returns root_mod
             Puppet::Parser::Functions.expects(:environment_module).with(env).returns mod
 
             Puppet::Parser::Scope.new(:compiler => compiler).metaclass.ancestors.should be_include(mod)
@@ -70,7 +72,7 @@ describe Puppet::Parser::Scope do
 
         it "should extend itself with the default Functions module if it has no environment" do
             mod = Module.new
-            Puppet::Parser::Functions.expects(:environment_module).with(nil).returns mod
+            Puppet::Parser::Functions.expects(:environment_module).with(Puppet::Node::Environment.root).returns(mod)
 
             Puppet::Parser::Scope.new().metaclass.ancestors.should be_include(mod)
         end
diff --git a/spec/unit/util/autoload.rb b/spec/unit/util/autoload.rb
index 220cb5f..5862073 100755
--- a/spec/unit/util/autoload.rb
+++ b/spec/unit/util/autoload.rb
@@ -15,10 +15,6 @@ describe Puppet::Util::Autoload do
         Puppet::Util::Autoload.ancestors.should be_include(Puppet::Util::Cacher)
     end
 
-    it "should use a ttl of 15 for the search path" do
-        Puppet::Util::Autoload.attr_ttl(:searchpath).should == 15
-    end
-
     describe "when building the search path" do
         it "should collect all of the plugins and lib directories that exist in the current environment's module path" do
             Puppet.settings.expects(:value).with(:environment).returns "foo"

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list