diff options
| author | Luke Kanies <luke@madstop.com> | 2007-09-17 15:21:44 -0700 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2007-09-17 15:21:44 -0700 |
| commit | 9fa2628a844c75b8f554f283dfece01667f20594 (patch) | |
| tree | 7c1b57c56879b2b083063895bae6423f2b94dc9c /lib/puppet/node | |
| parent | b3c8cdb67d9a423a1d14764f1e58f677d7ef8d41 (diff) | |
| download | puppet-9fa2628a844c75b8f554f283dfece01667f20594.tar.gz puppet-9fa2628a844c75b8f554f283dfece01667f20594.tar.xz puppet-9fa2628a844c75b8f554f283dfece01667f20594.zip | |
This is basically another intermediate commit. I feel like
I've gone too far down the rabbit hole to turn back now, but the
code is clearly getting more centralized around the Configuration
class, which is the goal.
Things are currently a bit muddy between recursion, dynamic resource
generation, transactions, and the configuration, and I don't expect
to be able to clear it up much until we rewrite all of the tests
for the Transaction class, since that is when we'll actually be
setting its behaviour.
At this point, Files (which are currently the only resources that
generate other resources) are responsible for adding their edges
to the relationship graph. This puts them knowing more than I would
like about how the relationship graph works, but it'll have to do for now.
There are still failing tests, but files seem to work again. Now to
go through the rest of the tests and make them work.
Diffstat (limited to 'lib/puppet/node')
| -rw-r--r-- | lib/puppet/node/configuration.rb | 164 |
1 files changed, 147 insertions, 17 deletions
diff --git a/lib/puppet/node/configuration.rb b/lib/puppet/node/configuration.rb index 9cd23926e..c882e0ee1 100644 --- a/lib/puppet/node/configuration.rb +++ b/lib/puppet/node/configuration.rb @@ -35,20 +35,22 @@ class Puppet::Node::Configuration < Puppet::PGraph tag(*classes) end - # Add a resource to our graph and to our resource table. - def add_resource(resource) - unless resource.respond_to?(:ref) - raise ArgumentError, "Can only add objects that respond to :ref" - end + # Add one or more resources to our graph and to our resource table. + def add_resource(*resources) + resources.each do |resource| + unless resource.respond_to?(:ref) + raise ArgumentError, "Can only add objects that respond to :ref" + end - ref = resource.ref - if @resource_table.include?(ref) - raise ArgumentError, "Resource %s is already defined" % ref - else - @resource_table[ref] = resource + ref = resource.ref + if @resource_table.include?(ref) + raise ArgumentError, "Resource %s is already defined" % ref + else + @resource_table[ref] = resource + end + resource.configuration = self + add_vertex!(resource) end - resource.configuration = self - add_vertex!(resource) end # Apply our configuration to the local host. @@ -58,6 +60,8 @@ class Puppet::Node::Configuration < Puppet::PGraph transaction.addtimes :config_retrieval => @retrieval_duration + @applying = true + begin transaction.evaluate rescue Puppet::Error => detail @@ -83,22 +87,62 @@ class Puppet::Node::Configuration < Puppet::PGraph return transaction ensure + @applying = false + cleanup() if defined? transaction and transaction transaction.cleanup end end + + # Are we in the middle of applying the configuration? + def applying? + @applying + end def clear(remove_resources = true) super() # We have to do this so that the resources clean themselves up. @resource_table.values.each { |resource| resource.remove } if remove_resources @resource_table.clear + + if defined?(@relationship_graph) and @relationship_graph + @relationship_graph.clear(false) + @relationship_graph = nil + end end def classes @classes.dup end + # Create an implicit resource, meaning that it will lose out + # to any explicitly defined resources. This method often returns + # nil. + def create_implicit_resource(type, options) + unless options.include?(:implicit) + options[:implicit] = true + end + if resource = create_resource(type, options) + resource.implicit = true + + return resource + else + return nil + end + end + + # Create a new resource and register it in the configuration. + def create_resource(type, options) + unless klass = Puppet::Type.type(type) + raise ArgumentError, "Unknown resource type %s" % type + end + return unless resource = klass.create(options) + + @transient_resources << resource if applying? + add_resource(resource) + resource + end + # Make sure we support the requested extraction format. def extraction_format=(value) unless respond_to?("extract_to_%s" % value) @@ -174,6 +218,12 @@ class Puppet::Node::Configuration < Puppet::PGraph # Make sure all of our resources are "finished". def finalize @resource_table.values.each { |resource| resource.finish } + + write_graph(:resources) + end + + def host_config? + host_config || false end def initialize(name = nil) @@ -183,20 +233,76 @@ class Puppet::Node::Configuration < Puppet::PGraph @tags = [] @classes = [] @resource_table = {} + @transient_resources = [] + @applying = false if block_given? yield(self) finalize() end end + + # Create a graph of all of the relationships in our configuration. + def relationship_graph + unless defined? @relationship_graph and @relationship_graph + relationships = self.class.new + + # First create the dependency graph + self.vertices.each do |vertex| + relationships.add_resource vertex + vertex.builddepends.each do |edge| + relationships.add_edge!(edge) + end + end + + # Lastly, add in any autorequires + relationships.vertices.each do |vertex| + vertex.autorequire.each do |edge| + unless relationships.edge?(edge) + unless relationships.edge?(edge.target, edge.source) + vertex.debug "Autorequiring %s" % [edge.source] + relationships.add_edge!(edge) + else + vertex.debug "Skipping automatic relationship with %s" % (edge.source == vertex ? edge.target : edge.source) + end + end + end + end + + relationships.write_graph(:relationships) + + # Then splice in the container information + relationships.splice!(self, Puppet::Type::Component) + + relationships.write_graph(:expanded_relationships) + @relationship_graph = relationships + end + @relationship_graph + end - # Look a resource up by its reference (e.g., File[/etc/passwd]). - def resource(ref) - @resource_table[ref] + # Remove the resource from our configuration. Notice that we also call + # 'remove' on the resource, at least until resource classes no longer maintain + # references to the resource instances. + def remove_resource(*resources) + resources.each do |resource| + @resource_table.delete(resource.ref) if @resource_table.include?(resource.ref) + remove_vertex!(resource) if vertex?(resource) + resource.remove + end end - def host_config? - host_config || false + # Look a resource up by its reference (e.g., File[/etc/passwd]). + def resource(type, title = nil) + if title + ref = "%s[%s]" % [type.to_s.capitalize, title] + else + ref = type + end + if resource = @resource_table[ref] + return resource + elsif defined?(@relationship_graph) and @relationship_graph + @relationship_graph.resource(ref) + end end # Add a tag. @@ -217,4 +323,28 @@ class Puppet::Node::Configuration < Puppet::PGraph def tags @tags.dup end + + # Produce the graph files if requested. + def write_graph(name) + # We only want to graph the main host configuration. + return unless host_config? + + return unless Puppet[:graph] + + Puppet.config.use(:graphing) + + file = File.join(Puppet[:graphdir], "%s.dot" % name.to_s) + File.open(file, "w") { |f| + f.puts to_dot("name" => name.to_s.capitalize) + } + end + + private + + def cleanup + unless @transient_resources.empty? + remove_resource(*@transient_resources) + @transient_resources.clear + end + end end |
