summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/parser')
-rw-r--r--lib/puppet/parser/ast/collection.rb17
-rw-r--r--lib/puppet/parser/ast/component.rb8
-rw-r--r--lib/puppet/parser/ast/hostclass.rb3
-rw-r--r--lib/puppet/parser/ast/objectdef.rb8
-rw-r--r--lib/puppet/parser/interpreter.rb41
-rw-r--r--lib/puppet/parser/scope.rb87
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,