diff options
Diffstat (limited to 'lib/puppet/parser')
-rw-r--r-- | lib/puppet/parser/ast/collection.rb | 17 | ||||
-rw-r--r-- | lib/puppet/parser/ast/component.rb | 8 | ||||
-rw-r--r-- | lib/puppet/parser/ast/hostclass.rb | 3 | ||||
-rw-r--r-- | lib/puppet/parser/ast/objectdef.rb | 8 | ||||
-rw-r--r-- | lib/puppet/parser/interpreter.rb | 41 | ||||
-rw-r--r-- | lib/puppet/parser/scope.rb | 87 |
6 files changed, 131 insertions, 33 deletions
diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb index e3afbbd8f..030f1c239 100644 --- a/lib/puppet/parser/ast/collection.rb +++ b/lib/puppet/parser/ast/collection.rb @@ -13,7 +13,20 @@ class Puppet::Parser::AST count = 0 # Now perform the actual collection, yo. + + # First get everything from the export table. + + # FIXME This will only find objects that are before us in the tree, + # which is a problem. + objects = scope.exported(type) + + array = objects.values + Puppet::Rails::RailsObject.find_all_by_collectable(true).each do |obj| + if objects.include?(obj.name) + debug("%s[%s] is already exported" % [type, obj.name]) + next + end count += 1 trans = obj.to_trans @@ -30,13 +43,15 @@ class Puppet::Parser::AST args[:arguments] = {} trans.each do |p,v| args[:arguments][p] = v end - + # XXX Because the scopes don't expect objects to return values, # we have to manually add our objects to the scope. This is # uber-lame. scope.setobject(args) end + + scope.debug("Collected %s objects of type %s" % [count, type]) diff --git a/lib/puppet/parser/ast/component.rb b/lib/puppet/parser/ast/component.rb index 5cf3f5c57..317c8ced5 100644 --- a/lib/puppet/parser/ast/component.rb +++ b/lib/puppet/parser/ast/component.rb @@ -10,7 +10,7 @@ class Puppet::Parser::AST # The class name @name = :component - attr_accessor :type, :args, :code, :scope, :keyword + attr_accessor :type, :args, :code, :scope, :keyword, :collectable #def evaluate(scope,hash,objtype,objname) def evaluate(hash) @@ -19,6 +19,8 @@ class Puppet::Parser::AST objname = hash[:name] arguments = hash[:arguments] || {} + @collectable = hash[:collectable] + pscope = origscope #pscope = if ! Puppet[:lexical] or hash[:asparent] == false # origscope @@ -32,6 +34,10 @@ class Puppet::Parser::AST ) newcontext = hash[:newcontext] + if @collectable or origscope.collectable + scope.collectable = true + end + unless self.is_a? AST::HostClass and ! newcontext #scope.warning "Setting context to %s" % self.object_id scope.context = self.object_id diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb index 7f381db2a..f66078d7a 100644 --- a/lib/puppet/parser/ast/hostclass.rb +++ b/lib/puppet/parser/ast/hostclass.rb @@ -148,7 +148,8 @@ class Puppet::Parser::AST :scope => scope, :arguments => args, :name => name, - :asparent => true + :asparent => true, + :collectable => self.collectable ) else return false diff --git a/lib/puppet/parser/ast/objectdef.rb b/lib/puppet/parser/ast/objectdef.rb index f15a082e2..7ccc9851a 100644 --- a/lib/puppet/parser/ast/objectdef.rb +++ b/lib/puppet/parser/ast/objectdef.rb @@ -91,13 +91,9 @@ class Puppet::Parser::AST :name => objname, :arguments => hash, :file => @file, - :line => @line + :line => @line, + :collectable => self.collectable ) - - # Retain our collectable marking - if self.collectable - obj.collectable = true - end rescue Puppet::ParseError => except except.line = self.line except.file = self.file diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb index ee447076f..9bc1cca43 100644 --- a/lib/puppet/parser/interpreter.rb +++ b/lib/puppet/parser/interpreter.rb @@ -85,6 +85,18 @@ module Puppet @local = hash[:Local] || false + if hash.include?(:ForkSave) + @forksave = hash[:ForkSave] + else + # This is just too dangerous right now. Sorry, it's going + # to have to be slow. + @forksave = false + end + + if Puppet[:storeconfigs] + Puppet::Rails.init + end + # Create our parser object parsefiles end @@ -250,13 +262,28 @@ module Puppet Puppet::Rails.init - # We store all of the objects, even the collectable ones - benchmark(:info, "Stored configuration for #{client}") do - Puppet::Rails::Host.store( - :objects => objects, - :host => client, - :facts => facts - ) + # Fork the storage, since we don't need the client waiting + # on that. How do I avoid this duplication? + if @forksave + fork { + # We store all of the objects, even the collectable ones + benchmark(:info, "Stored configuration for #{client}") do + Puppet::Rails::Host.store( + :objects => objects, + :host => client, + :facts => facts + ) + end + } + else + # We store all of the objects, even the collectable ones + benchmark(:info, "Stored configuration for #{client}") do + Puppet::Rails::Host.store( + :objects => objects, + :host => client, + :facts => facts + ) + end end # Now that we've stored everything, we need to strip out diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb index 54f0f42ad..baef76bfa 100644 --- a/lib/puppet/parser/scope.rb +++ b/lib/puppet/parser/scope.rb @@ -20,11 +20,11 @@ module Puppet::Parser attr_accessor :parent, :level, :interp attr_accessor :name, :type, :topscope, :base, :keyword - attr_accessor :top, :context, :translated + attr_accessor :top, :context, :translated, :collectable # This is probably not all that good of an idea, but... # This way a parent can share its tables with all of its children. - attr_writer :nodetable, :classtable, :definedtable + attr_writer :nodetable, :classtable, :definedtable, :exportable # Whether we behave declaratively. Note that it's a class variable, # so all scopes behave the same. @@ -150,6 +150,12 @@ module Puppet::Parser raise Puppet::DevError, "No classtable has been defined" end + if defined? @exportable + scope.exportable = @exportable + else + raise Puppet::DevError, "No exportable has been defined" + end + if defined? @definedtable scope.definedtable = @definedtable else @@ -304,6 +310,31 @@ module Puppet::Parser return bucket end + # Return the hash of objects that we specifically exported. We return + # a hash to make it easy for the caller to deduplicate based on name. + def exported(type) + if @exportable.include?(type) + return @exportable[type].dup + else + return {} + end + end + + # Store our object in the central export table. + def exportobject(obj) + if @exportable.include?(obj.type) and + @exportable[obj.type].include?(obj.name) + raise Puppet::ParseError, "Object %s[%s] is already exported" % + [obj.type, obj.name] + end + + debug "Exporting %s[%s]" % [obj.type, obj.name] + + @exportable[obj.type][obj.name] = obj + + return obj + end + # Pull in all of the appropriate classes and evaluate them. It'd # be nice if this didn't know quite so much about how AST::Node # operated internally. This is used when a list of classes is passed in, @@ -433,6 +464,11 @@ module Puppet::Parser # A table for storing nodes. @nodetable = Hash.new(nil) + # The list of objects that will available for export. + @exportable = Hash.new { |types, type| + types[type] = {} + } + # Eventually, if we support sites, this will allow definitions # of nodes with the same name in different sites. For now # the top-level scope is always the only site scope. @@ -685,6 +721,8 @@ module Puppet::Parser file = hash[:file] line = hash[:line] + collectable = hash[:collectable] || self.collectable + # Verify that we're not overriding any already-set parameters. if localobj = @localobjectable[type][name] params.each { |var, value| @@ -703,6 +741,24 @@ module Puppet::Parser # First look for it in a parent scope obj = lookupobject(:name => name, :type => type) + if obj + unless collectable == obj.collectable + msg = nil + if collectable + msg = "Exported %s[%s] cannot override local objects" + [type, name] + else + msg = "Local %s[%s] cannot override exported objects" + [type, name] + end + + error = Puppet::ParseError.new(msg) + error.line = line + error.file = file + raise error + end + end + unless obj and obj != :undefined unless obj = @objectable[type][name] obj = self.newobject( @@ -712,6 +768,8 @@ module Puppet::Parser :file => file ) + obj.collectable = collectable + # only set these if we've created the object, # which is the most common case # FIXME we eventually need to store the file @@ -872,7 +930,9 @@ module Puppet::Parser # it is. if objecttype = lookuptype(child.type) # It's a defined type, so evaluate it. Retain whether - # the object is collectable. + # the object is collectable. If the object is collectable, + # then it will store all of its contents into the + # @exportable table, rather than returning them. result = objecttype.safeevaluate( :name => child.name, :type => child.type, @@ -880,22 +940,15 @@ module Puppet::Parser :scope => self, :collectable => child.collectable ) - - # If the child is collectable, then mark all of the - # results as collectable. This is how we retain - # collectability through components and such. + else + # If it's collectable, then store it. if child.collectable - result.delve do |object| - if object.is_a? Puppet::TransObject - debug "Collecting %s[%s]" % - [object.type, object.name] - object.collectable = true - end - end + exportobject(child) + result = nil + else + # It's a builtin type, so just return it directly + result = child end - else - # It's a builtin type, so just return it directly - result = child end else raise Puppet::DevError, |