diff options
author | Luke Kanies <luke@madstop.com> | 2007-09-04 12:09:48 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2007-09-04 12:09:48 -0500 |
commit | 3b2efd2a4b32478b6c6a71e1421061405a0bb11e (patch) | |
tree | 72e5ada4b0eeb3c83a1f20dfb524363a3fc5db81 /lib | |
parent | 0faf76ee187c7fa7c67a7fb7e7c345897006b7d8 (diff) | |
download | puppet-3b2efd2a4b32478b6c6a71e1421061405a0bb11e.tar.gz puppet-3b2efd2a4b32478b6c6a71e1421061405a0bb11e.tar.xz puppet-3b2efd2a4b32478b6c6a71e1421061405a0bb11e.zip |
We now have a real configuration object, as a subclass of GRATR::Digraph, that has a resource graph including resources for the container objects like classes and nodes. It is apparently functional, but I have not gone through all of the other tests to fix them yet. That is next.
Diffstat (limited to 'lib')
32 files changed, 237 insertions, 535 deletions
diff --git a/lib/puppet/node/configuration.rb b/lib/puppet/node/configuration.rb new file mode 100644 index 000000000..e667007e9 --- /dev/null +++ b/lib/puppet/node/configuration.rb @@ -0,0 +1,123 @@ +require 'puppet/external/gratr/digraph' + +# This class models a node configuration. It is the thing +# meant to be passed from server to client, and it contains all +# of the information in the configuration, including the resources +# and the relationships between them. +class Puppet::Node::Configuration < GRATR::Digraph + attr_accessor :name + attr_reader :extraction_format + + # Add classes to our class list. + def add_class(*classes) + classes.each do |klass| + @classes << klass + end + + # Add the class names as tags, too. + tag(*classes) + end + + def classes + @classes.dup + end + + # Make sure we support the requested extraction format. + def extraction_format=(value) + unless respond_to?("extract_to_%s" % value) + raise ArgumentError, "Invalid extraction format %s" % value + end + @extraction_format = value + end + + # Turn our configuration graph into whatever the client is expecting. + def extract + send("extract_to_%s" % extraction_format) + end + + # Create the traditional TransBuckets and TransObjects from our configuration + # graph. This will hopefully be deprecated soon. + def extract_to_transportable + top = nil + current = nil + buckets = {} + + unless main = vertices.find { |res| res.type == "class" and res.title == :main } + raise Puppet::DevError, "Could not find 'main' class; cannot generate configuration" + end + + # Create a proc for examining edges, which we'll use to build our tree + # of TransBuckets and TransObjects. + bucket = nil + edges = proc do |edge| + # The sources are always non-builtins. + source, target = edge.source, edge.target + unless tmp = buckets[source.to_s] + if tmp = buckets[source.to_s] = source.to_trans + bucket = tmp + else + # This is because virtual resources return nil. If a virtual + # container resource contains realized resources, we still need to get + # to them. So, we keep a reference to the last valid bucket + # we returned and use that if the container resource is virtual. + end + end + bucket = tmp || bucket + if child = target.to_trans + unless bucket + raise "No bucket created for %s" % source + end + bucket.push child + + # It's important that we keep a reference to any TransBuckets we've created, so + # we don't create multiple buckets for children. + unless target.builtin? + buckets[target.to_s] = child + end + end + end + dfs(:start => main, :examine_edge => edges) + + unless main + raise Puppet::DevError, "Could not find 'main' class; cannot generate configuration" + end + + # Retrive the bucket for the top-level scope and set the appropriate metadata. + unless result = buckets[main.to_s] + raise Puppet::DevError, "Did not evaluate top scope" + end + + result.classes = classes + + # Clear the cache to encourage the GC + buckets.clear + return result + end + + def initialize(name) + super() + @name = name + @extraction_format ||= :transportable + @tags = [] + @classes = [] + end + + # Add a tag. + def tag(*names) + names.each do |name| + name = name.to_s + @tags << name unless @tags.include?(name) + if name.include?("::") + name.split("::").each do |sub| + @tags << sub unless @tags.include?(sub) + end + end + end + nil + end + + # Return the list of tags. + def tags + @tags.dup + end +end diff --git a/lib/puppet/parser/ast/astarray.rb b/lib/puppet/parser/ast/astarray.rb index c0212f919..2a8f4d4c1 100644 --- a/lib/puppet/parser/ast/astarray.rb +++ b/lib/puppet/parser/ast/astarray.rb @@ -65,21 +65,6 @@ class Puppet::Parser::AST return self end - - # Convert to a string. Only used for printing the parse tree. - def to_s - return "[" + @children.collect { |child| - child.to_s - }.join(", ") + "]" - end - - # Print the parse tree. - def tree(indent = 0) - #puts((AST.indent * indent) + self.pin) - self.collect { |child| - child.tree(indent) - }.join("\n" + (AST.midline * (indent+1)) + "\n") - end end # A simple container class, containing the parameters for an object. @@ -88,5 +73,3 @@ class Puppet::Parser::AST # meant completely different things. class ResourceInst < ASTArray; end end - -# $Id$ diff --git a/lib/puppet/parser/ast/branch.rb b/lib/puppet/parser/ast/branch.rb index 5a4d323f5..dcd09baa3 100644 --- a/lib/puppet/parser/ast/branch.rb +++ b/lib/puppet/parser/ast/branch.rb @@ -35,15 +35,5 @@ class Puppet::Parser::AST end } end - - # Pretty-print the parse tree. - def tree(indent = 0) - return ((@@indline * indent) + - self.typewrap(self.pin)) + "\n" + self.collect { |child| - child.tree(indent + 1) - }.join("\n") - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/caseopt.rb b/lib/puppet/parser/ast/caseopt.rb index 11483d082..d1d9d0e9c 100644 --- a/lib/puppet/parser/ast/caseopt.rb +++ b/lib/puppet/parser/ast/caseopt.rb @@ -56,16 +56,5 @@ class Puppet::Parser::AST def evaluate(hash) return @statements.safeevaluate(hash) end - - def tree(indent = 0) - rettree = [ - @value.tree(indent + 1), - ((@@indline * indent) + self.typewrap(self.pin)), - @statements.tree(indent + 1) - ] - return rettree.flatten.join("\n") - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/casestatement.rb b/lib/puppet/parser/ast/casestatement.rb index c56e33bc9..3c6f9c7e2 100644 --- a/lib/puppet/parser/ast/casestatement.rb +++ b/lib/puppet/parser/ast/casestatement.rb @@ -51,20 +51,8 @@ class Puppet::Parser::AST return retvalue end - def tree(indent = 0) - rettree = [ - @test.tree(indent + 1), - ((@@indline * indent) + self.typewrap(self.pin)), - @options.tree(indent + 1) - ] - - return rettree.flatten.join("\n") - end - def each [@test,@options].each { |child| yield child } end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb index a7564f0c9..e05977a47 100644 --- a/lib/puppet/parser/ast/collection.rb +++ b/lib/puppet/parser/ast/collection.rb @@ -26,5 +26,3 @@ class Collection < AST::Branch end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/collexpr.rb b/lib/puppet/parser/ast/collexpr.rb index 5fb11c709..4a96d9c61 100644 --- a/lib/puppet/parser/ast/collexpr.rb +++ b/lib/puppet/parser/ast/collexpr.rb @@ -77,5 +77,3 @@ class CollExpr < AST::Branch end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/component.rb b/lib/puppet/parser/ast/component.rb index 17cfa9d61..1d7fe9cdd 100644 --- a/lib/puppet/parser/ast/component.rb +++ b/lib/puppet/parser/ast/component.rb @@ -222,5 +222,3 @@ class Puppet::Parser::AST end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/definition.rb b/lib/puppet/parser/ast/definition.rb index c350c2cdb..9ad1f539d 100644 --- a/lib/puppet/parser/ast/definition.rb +++ b/lib/puppet/parser/ast/definition.rb @@ -33,8 +33,6 @@ class Puppet::Parser::AST # Create a new scope. scope = subscope(origscope, resource) - scope.virtual = true if resource.virtual or origscope.virtual? - scope.exported = true if resource.exported or origscope.exported? # Additionally, add a tag for whatever kind of class # we are @@ -126,21 +124,16 @@ class Puppet::Parser::AST # Create a new subscope in which to evaluate our code. def subscope(scope, resource = nil) - if resource - type = resource.type - else - type = self.classname + unless resource + raise ArgumentError, "Resources are required when creating subscopes" end args = { :resource => resource, - :type => type, :keyword => self.keyword, :namespace => self.namespace, :source => self } - args[:name] = resource.title if resource - oldscope = scope scope = scope.newscope(args) scope.source = self diff --git a/lib/puppet/parser/ast/else.rb b/lib/puppet/parser/ast/else.rb index ff2f233b7..e76051372 100644 --- a/lib/puppet/parser/ast/else.rb +++ b/lib/puppet/parser/ast/else.rb @@ -16,15 +16,5 @@ class Puppet::Parser::AST scope = hash[:scope] return @statements.safeevaluate(:scope => scope) end - - def tree(indent = 0) - rettree = [ - ((@@indline * indent) + self.typewrap(self.pin)), - @statements.tree(indent + 1) - ] - return rettree.flatten.join("\n") - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb index 052b8a8b1..0cd1fff62 100644 --- a/lib/puppet/parser/ast/function.rb +++ b/lib/puppet/parser/ast/function.rb @@ -53,5 +53,3 @@ class Puppet::Parser::AST end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb index 41ca34432..0a8e33970 100644 --- a/lib/puppet/parser/ast/hostclass.rb +++ b/lib/puppet/parser/ast/hostclass.rb @@ -22,6 +22,7 @@ class Puppet::Parser::AST # Evaluate the code associated with this class. def evaluate(options) scope = options[:scope] + raise(ArgumentError, "Classes require resources") unless options[:resource] # Verify that we haven't already been evaluated. This is # what provides the singleton aspect. if existing_scope = scope.compile.class_scope(self) @@ -31,13 +32,15 @@ class Puppet::Parser::AST pnames = nil if pklass = self.parentobj - pklass.safeevaluate :scope => scope + pklass.safeevaluate :scope => scope, :resource => options[:resource] scope = parent_scope(scope, pklass) pnames = scope.namespaces end - unless options[:nosubscope] + # Don't create a subscope for the top-level class, since it already + # has its own scope. + unless options[:resource].title == :main scope = subscope(scope, options[:resource]) end diff --git a/lib/puppet/parser/ast/ifstatement.rb b/lib/puppet/parser/ast/ifstatement.rb index 300f68dab..66a07b01f 100644 --- a/lib/puppet/parser/ast/ifstatement.rb +++ b/lib/puppet/parser/ast/ifstatement.rb @@ -26,18 +26,5 @@ class Puppet::Parser::AST end end end - - def tree(indent = 0) - rettree = [ - @test.tree(indent + 1), - ((@@indline * indent) + self.typewrap(self.pin)), - @statements.tree(indent + 1), - @else.tree(indent + 1) - ] - - return rettree.flatten.join("\n") - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb index c2fd0939d..225253061 100644 --- a/lib/puppet/parser/ast/leaf.rb +++ b/lib/puppet/parser/ast/leaf.rb @@ -10,11 +10,6 @@ class Puppet::Parser::AST return @value end - # Print the value in parse tree context. - def tree(indent = 0) - return ((@@indent * indent) + self.typewrap(self.value)) - end - def to_s return @value end @@ -92,7 +87,4 @@ class Puppet::Parser::AST end end end - end - -# $Id$ diff --git a/lib/puppet/parser/ast/node.rb b/lib/puppet/parser/ast/node.rb index d46df3cff..20c03f4ce 100644 --- a/lib/puppet/parser/ast/node.rb +++ b/lib/puppet/parser/ast/node.rb @@ -7,7 +7,6 @@ class Puppet::Parser::AST @name = :node attr_accessor :name - #def evaluate(scope, facts = {}) def evaluate(options) scope = options[:scope] @@ -24,7 +23,7 @@ class Puppet::Parser::AST end scope = scope.newscope( - :type => self.name, + :resource => options[:resource], :keyword => @keyword, :source => self, :namespace => "" # nodes are always in "" diff --git a/lib/puppet/parser/ast/resourcedef.rb b/lib/puppet/parser/ast/resourcedef.rb index 7a43f6b32..02eac2b7b 100644 --- a/lib/puppet/parser/ast/resourcedef.rb +++ b/lib/puppet/parser/ast/resourcedef.rb @@ -1,88 +1,27 @@ require 'puppet/parser/ast/branch' -# Any normal puppet object declaration. Can result in a class or a -# component, in addition to builtin types. +# Any normal puppet resource declaration. Can point to a definition or a +# builtin type. class Puppet::Parser::AST class ResourceDef < AST::Branch attr_accessor :title, :type, :exported, :virtual attr_reader :params - # probably not used at all - def []=(index,obj) - @params[index] = obj - end - - # probably not used at all - def [](index) - return @params[index] - end - - # Iterate across all of our children. - def each - [@type,@title,@params].flatten.each { |param| - #Puppet.debug("yielding param %s" % param) - yield param - } - end - # Does not actually return an object; instead sets an object # in the current scope. - def evaluate(hash) - scope = hash[:scope] - @scope = scope - hash = {} - - # Get our type and name. - objtype = @type - - # Disable definition inheritance, for now. 8/27/06, luke - #if objtype == "super" - # objtype = supertype() - # @subtype = true - #else - @subtype = false - #end + def evaluate(options) + scope = options[:scope] # Evaluate all of the specified params. paramobjects = @params.collect { |param| param.safeevaluate(:scope => scope) } - # Now collect info from our parent. - parentname = nil - if @subtype - parentname = supersetup(hash) - end - - objtitles = nil - # Determine our name if we have one. - if self.title - objtitles = @title.safeevaluate(:scope => scope) - # it's easier to always use an array, even for only one name - unless objtitles.is_a?(Array) - objtitles = [objtitles] - end - else - if parentname - objtitles = [parentname] - else - # See if they specified the name as a parameter instead of - # as a normal name (i.e., before the colon). - unless object # we're a builtin - if objclass = Puppet::Type.type(objtype) - namevar = objclass.namevar + objtitles = @title.safeevaluate(:scope => scope) - tmp = hash["name"] || hash[namevar.to_s] - - if tmp - objtitles = [tmp] - end - else - # This isn't grammatically legal. - raise Puppet::ParseError, "Got a resource with no title" - end - end - end + # it's easier to always use an array, even for only one name + unless objtitles.is_a?(Array) + objtitles = [objtitles] end # This is where our implicit iteration takes place; if someone @@ -90,26 +29,26 @@ class ResourceDef < AST::Branch # many times. objtitles.collect { |objtitle| exceptwrap :type => Puppet::ParseError do - exp = self.exported || scope.exported? + exp = self.exported || scope.resource.exported? # We want virtual to be true if exported is true. We can't # just set :virtual => self.virtual in the initialization, # because sometimes the :virtual attribute is set *after* # :exported, in which case it clobbers :exported if :exported # is true. Argh, this was a very tough one to track down. - virt = self.virtual || scope.virtual? || exported + virt = self.virtual || scope.resource.virtual? || exp obj = Puppet::Parser::Resource.new( - :type => objtype, + :type => @type, :title => objtitle, :params => paramobjects, - :file => @file, - :line => @line, + :file => self.file, + :line => self.line, :exported => exp, :virtual => virt, :source => scope.source, :scope => scope ) - # And then store the resource in the scope. + # And then store the resource in the compile. # XXX At some point, we need to switch all of this to return # objects instead of storing them like this. scope.compile.store_resource(scope, obj) @@ -118,14 +57,6 @@ class ResourceDef < AST::Branch }.reject { |obj| obj.nil? } end - # Create our ResourceDef. Handles type checking for us. - def initialize(hash) - @checked = false - super - - #self.typecheck(@type.value) - end - # Set the parameters for our object. def params=(params) if params.is_a?(AST::ASTArray) @@ -138,85 +69,5 @@ class ResourceDef < AST::Branch ) end end - - def supercomp - unless defined? @supercomp - if @scope and comp = @scope.inside - @supercomp = comp - else - error = Puppet::ParseError.new( - "'super' is only valid within definitions" - ) - error.line = self.line - error.file = self.file - raise error - end - end - @supercomp - end - - # Take all of the arguments of our parent and add them into our own, - # without overriding anything. - def supersetup(hash) - comp = supercomp() - - # Now check each of the arguments from the parent. - comp.arguments.each do |name, value| - unless hash.has_key? name - hash[name] = value - end - end - - # Return the parent name, so it can be used if appropriate. - return comp.name - end - - # Retrieve our supertype. - def supertype - unless defined? @supertype - if parent = supercomp.parentclass - @supertype = parent - else - error = Puppet::ParseError.new( - "%s does not have a parent class" % comp.type - ) - error.line = self.line - error.file = self.file - raise error - end - end - @supertype - end - - # Print this object out. - def tree(indent = 0) - return [ - @type.tree(indent + 1), - @title.tree(indent + 1), - ((@@indline * indent) + self.typewrap(self.pin)), - @params.collect { |param| - begin - param.tree(indent + 1) - rescue NoMethodError => detail - Puppet.err @params.inspect - error = Puppet::DevError.new( - "failed to tree a %s" % self.class - ) - error.set_backtrace detail.backtrace - raise error - end - }.join("\n") - ].join("\n") - end - - def to_s - return "%s => { %s }" % [@title, - @params.collect { |param| - param.to_s - }.join("\n") - ] - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/resourcedefaults.rb b/lib/puppet/parser/ast/resourcedefaults.rb index df16b1b59..44ec146b0 100644 --- a/lib/puppet/parser/ast/resourcedefaults.rb +++ b/lib/puppet/parser/ast/resourcedefaults.rb @@ -6,10 +6,6 @@ class Puppet::Parser::AST class ResourceDefaults < AST::Branch attr_accessor :type, :params - def each - [@type,@params].each { |child| yield child } - end - # As opposed to ResourceDef, this stores each default for the given # object type. def evaluate(hash) @@ -21,20 +17,5 @@ class Puppet::Parser::AST scope.setdefaults(type, params) end end - - def tree(indent = 0) - return [ - @type.tree(indent + 1), - ((@@indline * 4 * indent) + self.typewrap(self.pin)), - @params.tree(indent + 1) - ].join("\n") - end - - def to_s - return "%s { %s }" % [@type,@params] - end end - end - -# $Id$ diff --git a/lib/puppet/parser/ast/resourceoverride.rb b/lib/puppet/parser/ast/resourceoverride.rb index 418c9c8e4..4232737fc 100644 --- a/lib/puppet/parser/ast/resourceoverride.rb +++ b/lib/puppet/parser/ast/resourceoverride.rb @@ -58,5 +58,3 @@ class Puppet::Parser::AST end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/resourceparam.rb b/lib/puppet/parser/ast/resourceparam.rb index d87720160..8b1e7b367 100644 --- a/lib/puppet/parser/ast/resourceparam.rb +++ b/lib/puppet/parser/ast/resourceparam.rb @@ -20,19 +20,5 @@ class Puppet::Parser::AST :add => self.add ) end - - def tree(indent = 0) - return [ - @param.tree(indent + 1), - ((@@indline * indent) + self.typewrap(self.pin)), - @value.tree(indent + 1) - ].join("\n") - end - - def to_s - return "%s => %s" % [@param,@value] - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/resourceref.rb b/lib/puppet/parser/ast/resourceref.rb index e5bb69a46..167417f13 100644 --- a/lib/puppet/parser/ast/resourceref.rb +++ b/lib/puppet/parser/ast/resourceref.rb @@ -4,6 +4,14 @@ class Puppet::Parser::AST # A reference to an object. Only valid as an rvalue. class ResourceRef < AST::Branch attr_accessor :title, :type + # Is the type a builtin type? + def builtintype?(type) + if typeklass = Puppet::Type.type(type) + return typeklass + else + return false + end + end def each [@type,@title].flatten.each { |param| @@ -21,38 +29,24 @@ class Puppet::Parser::AST objtype = @type.downcase title = @title.safeevaluate(:scope => scope) - if scope.builtintype?(objtype) - # nothing - elsif dtype = scope.finddefine(objtype) - objtype = dtype.classname - elsif objtype == "class" - # Look up the full path to the class - if classobj = scope.findclass(title) - title = classobj.classname + unless builtintype?(objtype) + if dtype = scope.finddefine(objtype) + objtype = dtype.classname + elsif objtype == "class" + # Look up the full path to the class + if classobj = scope.findclass(title) + title = classobj.classname + else + raise Puppet::ParseError, "Could not find class %s" % title + end else - raise Puppet::ParseError, "Could not find class %s" % title + raise Puppet::ParseError, "Could not find resource type %s" % objtype end - else - raise Puppet::ParseError, "Could not find resource type %s" % objtype end return Puppet::Parser::Resource::Reference.new( :type => objtype, :title => title ) end - - def tree(indent = 0) - return [ - @type.tree(indent + 1), - @title.tree(indent + 1), - ((@@indline * indent) + self.typewrap(self.pin)) - ].join("\n") - end - - def to_s - return "%s[%s]" % [@type,@title] - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/selector.rb b/lib/puppet/parser/ast/selector.rb index e5eb3b6f5..d363ab7e4 100644 --- a/lib/puppet/parser/ast/selector.rb +++ b/lib/puppet/parser/ast/selector.rb @@ -60,15 +60,5 @@ class Puppet::Parser::AST return retvalue end - - def tree(indent = 0) - return [ - @param.tree(indent + 1), - ((@@indline * indent) + self.typewrap(self.pin)), - @values.tree(indent + 1) - ].join("\n") - end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/tag.rb b/lib/puppet/parser/ast/tag.rb index 4a2015cde..e2882d2f0 100644 --- a/lib/puppet/parser/ast/tag.rb +++ b/lib/puppet/parser/ast/tag.rb @@ -24,5 +24,3 @@ class Puppet::Parser::AST end end end - -# $Id$ diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/vardef.rb index ecc10bd14..1e7f874bc 100644 --- a/lib/puppet/parser/ast/vardef.rb +++ b/lib/puppet/parser/ast/vardef.rb @@ -22,20 +22,6 @@ class Puppet::Parser::AST def each [@name,@value].each { |child| yield child } end - - def tree(indent = 0) - return [ - @name.tree(indent + 1), - ((@@indline * 4 * indent) + self.typewrap(self.pin)), - @value.tree(indent + 1) - ].join("\n") - end - - def to_s - return "%s => %s" % [@name,@value] - end end end - -# $Id$ diff --git a/lib/puppet/parser/compile.rb b/lib/puppet/parser/compile.rb index 0ae712e57..a8e80eb9d 100644 --- a/lib/puppet/parser/compile.rb +++ b/lib/puppet/parser/compile.rb @@ -6,6 +6,7 @@ require 'puppet/external/gratr/import' require 'puppet/external/gratr/dot' require 'puppet/node' +require 'puppet/node/configuration' require 'puppet/util/errors' # Maintain a graph of scopes, along with a bunch of data @@ -14,7 +15,6 @@ class Puppet::Parser::Compile include Puppet::Util include Puppet::Util::Errors attr_reader :topscope, :parser, :node, :facts, :collections - attr_accessor :extraction_format attr_writer :ast_nodes @@ -39,7 +39,7 @@ class Puppet::Parser::Compile end end @class_scopes[name] = scope - tag(name) + @configuration.add_class(name) unless name == "" end # Return the scope associated with a class. This is just here so @@ -57,7 +57,7 @@ class Puppet::Parser::Compile # Return a list of all of the defined classes. def classlist - return @class_scopes.keys.reject { |k| k == "" } + return @configuration.classes end # Compile our configuration. This mostly revolves around finding and evaluating classes. @@ -82,7 +82,7 @@ class Puppet::Parser::Compile store() end - return extract() + return @configuration.extract end # FIXME There are no tests for this. @@ -93,8 +93,6 @@ class Puppet::Parser::Compile # FIXME There are no tests for this. def delete_resource(resource) @resource_table.delete(resource.ref) if @resource_table.include?(resource.ref) - - @resource_graph.remove_vertex!(resource) if @resource_graph.vertex?(resource) end # Return the node's environment. @@ -122,27 +120,23 @@ class Puppet::Parser::Compile found = [] classes.each do |name| # If we can find the class, then make a resource that will evaluate it. - if klass = @parser.findclass("", name) - # This will result in class_set getting called, which - # will in turn result in tags. Yay. - klass.safeevaluate(:scope => scope) + if klass = scope.findclass(name) + # Create a resource to model this class, and then add it to the list + # of resources. + unless scope.source + raise "No source for %s" % scope.to_s + end + resource = Puppet::Parser::Resource.new(:type => "class", :title => klass.classname, :scope => scope, :source => scope.source) + store_resource(scope, resource) found << name else Puppet.info "Could not find class %s for %s" % [name, node.name] - tag(name) + @configuration.tag(name) end end found end - # Make sure we support the requested extraction format. - def extraction_format=(value) - unless respond_to?("extract_to_%s" % value) - raise ArgumentError, "Invalid extraction format %s" % value - end - @extraction_format = value - end - # Return a resource by either its ref or its type and title. def findresource(string, name = nil) if name @@ -168,9 +162,8 @@ class Puppet::Parser::Compile end end - @extraction_format ||= :transportable - initvars() + init_main() end # Create a new scope, with either a specified parent scope or @@ -230,7 +223,7 @@ class Puppet::Parser::Compile # And in the resource graph. At some point, this might supercede # the global resource table, but the table is a lot faster # so it makes sense to maintain for now. - @resource_graph.add_edge!(scope, resource) + @configuration.add_edge!(scope.resource, resource) end private @@ -310,71 +303,19 @@ class Puppet::Parser::Compile # Find and evaluate our main object, if possible. def evaluate_main - if klass = @parser.findclass("", "") - # Set the source, so objects can tell where they were defined. - topscope.source = klass - klass.safeevaluate :scope => topscope, :nosubscope => true - end - end + @main = @parser.findclass("", "") || @parser.newclass("") + @topscope.source = @main + @main_resource = Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => @topscope, :source => @main) + @topscope.resource = @main_resource - # Turn our configuration graph into whatever the client is expecting. - def extract - send("extract_to_%s" % extraction_format) - end + @configuration.add_vertex!(@main_resource) - # Create the traditional TransBuckets and TransObjects from our configuration - # graph. This will hopefully be deprecated soon. - def extract_to_transportable - top = nil - current = nil - buckets = {} - - # I'm *sure* there's a simple way to do this using a breadth-first search - # or something, but I couldn't come up with, and this is both fast - # and simple, so I'm not going to worry about it too much. - @scope_graph.vertices.each do |scope| - # For each scope, we need to create a TransBucket, and then - # put all of the scope's resources into that bucket, translating - # each resource into a TransObject. - - # Unless the bucket's already been created, make it now and add - # it to the cache. - unless bucket = buckets[scope] - bucket = buckets[scope] = scope.to_trans - end - - # First add any contained scopes - @scope_graph.adjacent(scope, :direction => :out).each do |vertex| - # If there's not already a bucket, then create and cache it. - unless child_bucket = buckets[vertex] - child_bucket = buckets[vertex] = vertex.to_trans - end - bucket.push child_bucket - end - - # Then add the resources. - if @resource_graph.vertex?(scope) - @resource_graph.adjacent(scope, :direction => :out).each do |vertex| - # Some resources don't get translated, e.g., virtual resources. - if obj = vertex.to_trans - bucket.push obj - end - end - end - end - - # Retrive the bucket for the top-level scope and set the appropriate metadata. - result = buckets[topscope] - - result.copy_type_and_name(topscope) - - unless classlist.empty? - result.classes = classlist - end - - # Clear the cache to encourage the GC - buckets.clear - return result + @resource_table["Class[main]"] = @main_resource + #if klass = @parser.findclass("", "") + # # Set the source, so objects can tell where they were defined. + # topscope.source = klass + # klass.safeevaluate :scope => topscope, :nosubscope => true + #end end # Make sure the entire configuration is evaluated. @@ -431,6 +372,13 @@ class Puppet::Parser::Compile @resource_table.each { |name, resource| resource.finish if resource.respond_to?(:finish) } end + # Initialize the top-level scope, class, and resource. + def init_main + # Create our initial scope and a resource that will evaluate main. + @topscope = Puppet::Parser::Scope.new(:compile => self, :parser => self.parser) + @scope_graph.add_vertex!(@topscope) + end + # Set up all of our internal variables. def initvars # The table for storing class singletons. This will only actually @@ -456,18 +404,12 @@ class Puppet::Parser::Compile # A list of tags we've generated; most class names. @tags = [] - # Create our initial scope, our scope graph, and add the initial scope to the graph. - @topscope = Puppet::Parser::Scope.new(:compile => self, :type => "main", :name => "top", :parser => self.parser) - #@main = @parser.findclass("", "") - #@main_resource = Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => @topscope, :source => @main) - #@topscope.resource = @main_resource - - # For maintaining scope relationships. + # A graph for maintaining scope relationships. @scope_graph = GRATR::Digraph.new @scope_graph.add_vertex!(@topscope) # For maintaining the relationship between scopes and their resources. - @resource_graph = GRATR::Digraph.new + @configuration = Puppet::Node::Configuration.new(@node.name) end # Set the node's parameters into the top-scope as variables. @@ -510,20 +452,6 @@ class Puppet::Parser::Compile end end - # Add a tag. - def tag(*names) - names.each do |name| - name = name.to_s - @tags << name unless @tags.include?(name) - end - nil - end - - # Return the list of tags. - def tags - @tags.dup - end - # Return an array of all of the unevaluated resources. These will be definitions, # which need to get evaluated into native resources. def unevaluated_resources diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb index 05d694310..cbb7f4e2d 100644 --- a/lib/puppet/parser/functions.rb +++ b/lib/puppet/parser/functions.rb @@ -1,4 +1,3 @@ -# Grr require 'puppet/util/autoload' require 'puppet/parser/scope' diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb index be1d73047..8cf0dcfe8 100644 --- a/lib/puppet/parser/parser_support.rb +++ b/lib/puppet/parser/parser_support.rb @@ -125,7 +125,7 @@ class Puppet::Parser::Parser # The recursive method used to actually look these objects up. def fqfind(namespace, name, table) namespace = namespace.downcase - name = name.downcase + name = name.to_s.downcase if name =~ /^::/ or namespace == "" classname = name.sub(/^::/, '') unless table[classname] diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb index 0fdb25748..3f5ca78ae 100644 --- a/lib/puppet/parser/resource.rb +++ b/lib/puppet/parser/resource.rb @@ -211,7 +211,7 @@ class Puppet::Parser::Resource def tags unless defined? @tags @tags = scope.tags - @tags << self.type + @tags << self.type unless @tags.include?(self.type) end @tags end @@ -251,12 +251,26 @@ class Puppet::Parser::Resource # Translate our object to a transportable object. def to_trans - unless builtin? - devfail "Tried to translate a non-builtin resource" + return nil if virtual? + + if builtin? + to_transobject + else + to_transbucket end + end - return nil if virtual? + def to_transbucket + bucket = Puppet::TransBucket.new([]) + + bucket.type = self.type + bucket.name = self.title + + # TransBuckets don't support parameters, which is why they're being deprecated. + return bucket + end + def to_transobject # Now convert to a transobject obj = Puppet::TransObject.new(@ref.title, @ref.type) to_hash.each do |p, v| diff --git a/lib/puppet/parser/resource/reference.rb b/lib/puppet/parser/resource/reference.rb index 0c3b61930..0bc732558 100644 --- a/lib/puppet/parser/resource/reference.rb +++ b/lib/puppet/parser/resource/reference.rb @@ -34,7 +34,11 @@ class Puppet::Parser::Resource::Reference name = self.title case type when "class": # look for host classes - tmp = @scope.findclass(self.title) + if self.title == :main + tmp = @scope.findclass("") + else + tmp = @scope.findclass(self.title) + end when "node": # look for node definitions tmp = @scope.parser.nodes[self.title] else # normal definitions diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb index 5f6f15ba6..4516715e1 100644 --- a/lib/puppet/parser/scope.rb +++ b/lib/puppet/parser/scope.rb @@ -19,20 +19,6 @@ class Puppet::Parser::Scope attr_accessor :base, :keyword, :nodescope attr_accessor :top, :translated, :compile - # Temporary accessors. - attr_accessor :name, :type, :title, :exported, :virtual - def exported? - exported - end - def virtual? - virtual - end - #[:name, :type, :title, :exported?, :virtual].each do |method| - # define_method(method) do - # @resource.send(method) - # end - #end - # Proxy accessors def host @compile.node.name @@ -62,15 +48,6 @@ class Puppet::Parser::Scope end end - # Is the type a builtin type? - def builtintype?(type) - if typeklass = Puppet::Type.type(type) - return typeklass - else - return false - end - end - # Are we the top scope? def topscope? @level == 1 @@ -379,27 +356,7 @@ class Puppet::Parser::Scope # Used mainly for logging def to_s - if self.name - return "%s[%s]" % [@type, @name] - else - return self.type.to_s - end - end - - # Convert our resource to a TransBucket. - def to_trans - bucket = Puppet::TransBucket.new([]) - - case self.type - when "": bucket.type = "main" - when nil: devfail "A Scope with no type" - else - bucket.type = @type - end - if self.name - bucket.name = self.name - end - return bucket + "Scope(%s)" % @resource.to_s end # Undefine a variable; only used for testing. diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb index acd69fb0c..aa7eb92f7 100644 --- a/lib/puppet/transportable.rb +++ b/lib/puppet/transportable.rb @@ -100,19 +100,6 @@ module Puppet end } - # Copy a scope's type and name. - def copy_type_and_name(scope) - case scope.type - when "": self.type = "main" - when nil: devfail "A Scope with no type" - else - self.type = scope.type - end - if scope.name - self.name = scope.name - end - end - # Remove all collectable objects from our tree, since the client # should not see them. def collectstrip! diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb index 6366c7f24..5905d85ab 100644 --- a/lib/puppet/type/component.rb +++ b/lib/puppet/type/component.rb @@ -152,19 +152,21 @@ Puppet::Type.newtype(:component) do # Component paths are special because they function as containers. def pathbuilder tmp = [] - if defined? @parent and @parent - tmp += [@parent.pathbuilder, self.title] - else - # The top-level name is always main[top], so we don't bother with - # that. - if self.title == "main[top]" - tmp << "" # This empty field results in "//" in the path - else - tmp << self.title + myname = "" + if self.title =~ /^class\[(.+)\]$/ + # 'main' is the top class, so we want to see '//' instead of + # its name. + unless $1 == "main" + myname = $1 end + else + myname = self.title + end + if self.parent + return [@parent.pathbuilder, myname] + else + return [myname] end - - tmp end # Remove an object. The argument determines whether the object's diff --git a/lib/puppet/util/methodhelper.rb b/lib/puppet/util/methodhelper.rb index 63158ab67..32fca1877 100644 --- a/lib/puppet/util/methodhelper.rb +++ b/lib/puppet/util/methodhelper.rb @@ -33,5 +33,3 @@ module Puppet::Util::MethodHelper end end end - -# $Id$ |