diff options
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/node/catalog.rb | 29 | ||||
-rw-r--r-- | lib/puppet/pgraph.rb | 121 | ||||
-rw-r--r-- | lib/puppet/simple_graph.rb | 103 | ||||
-rw-r--r-- | lib/puppet/transaction.rb | 4 | ||||
-rw-r--r-- | lib/puppet/util/graph.rb | 4 |
5 files changed, 114 insertions, 147 deletions
diff --git a/lib/puppet/node/catalog.rb b/lib/puppet/node/catalog.rb index 39b3fdfdc..0138fd8cb 100644 --- a/lib/puppet/node/catalog.rb +++ b/lib/puppet/node/catalog.rb @@ -1,5 +1,5 @@ require 'puppet/indirector' -require 'puppet/pgraph' +require 'puppet/simple_graph' require 'puppet/transaction' require 'puppet/util/tagging' @@ -8,7 +8,7 @@ require 'puppet/util/tagging' # meant to be passed from server to client, and it contains all # of the information in the catalog, including the resources # and the relationships between them. -class Puppet::Node::Catalog < Puppet::PGraph +class Puppet::Node::Catalog < Puppet::SimpleGraph extend Puppet::Indirector indirects :catalog, :terminus_class => :compiler @@ -321,17 +321,13 @@ class Puppet::Node::Catalog < Puppet::PGraph # Create a graph of all of the relationships in our catalog. def relationship_graph - raise(Puppet::DevError, "Tried get a relationship graph for a relationship graph") if self.is_relationship_graph - unless defined? @relationship_graph and @relationship_graph # It's important that we assign the graph immediately, because # the debug messages below use the relationships in the # relationship graph to determine the path to the resources # spitting out the messages. If this is not set, # then we get into an infinite loop. - @relationship_graph = Puppet::Node::Catalog.new - @relationship_graph.host_config = host_config? - @relationship_graph.is_relationship_graph = true + @relationship_graph = Puppet::SimpleGraph.new # First create the dependency graph self.vertices.each do |vertex| @@ -355,12 +351,12 @@ class Puppet::Node::Catalog < Puppet::PGraph end end - @relationship_graph.write_graph(:relationships) + @relationship_graph.write_graph(:relationships) if host_config? # Then splice in the container information @relationship_graph.splice!(self, Puppet::Type::Component) - @relationship_graph.write_graph(:expanded_relationships) + @relationship_graph.write_graph(:expanded_relationships) if host_config? end @relationship_graph end @@ -391,11 +387,7 @@ class Puppet::Node::Catalog < Puppet::PGraph # Reference class canonizes for us. ref = Puppet::ResourceReference.new(nil, type).to_s end - if resource = @resource_table[ref] - return resource - elsif defined?(@relationship_graph) and @relationship_graph - @relationship_graph.resource(ref) - end + @resource_table[ref] end # Return an array of all resources. @@ -417,15 +409,8 @@ class Puppet::Node::Catalog < Puppet::PGraph def write_graph(name) # We only want to graph the main host catalog. return unless host_config? - - return unless Puppet[:graph] - - Puppet.settings.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) - } + super end # LAK:NOTE We cannot yaml-dump the class in the edgelist_class, because classes cannot be diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb deleted file mode 100644 index 55ad7d2c1..000000000 --- a/lib/puppet/pgraph.rb +++ /dev/null @@ -1,121 +0,0 @@ -# Created by Luke A. Kanies on 2006-11-24. -# Copyright (c) 2006. All rights reserved. - -require 'puppet/relationship' -require 'puppet/simple_graph' - -# This class subclasses a graph class in order to handle relationships -# among resources. -class Puppet::PGraph < Puppet::SimpleGraph - include Puppet::Util - - def add_edge(*args) - @reversal = nil - super - end - - def add_vertex(*args) - @reversal = nil - super - end - - # Which resources a given resource depends upon. - def dependents(resource) - tree_from_vertex(resource).keys - end - - # Which resources depend upon the given resource. - def dependencies(resource) - # Cache the reversal graph, because it's somewhat expensive - # to create. - unless defined? @reversal and @reversal - @reversal = reversal - end - # Strangely, it's significantly faster to search a reversed - # tree in the :out direction than to search a normal tree - # in the :in direction. - @reversal.tree_from_vertex(resource, :out).keys - end - - # Determine all of the leaf nodes below a given vertex. - def leaves(vertex, direction = :out) - tree = tree_from_vertex(vertex, direction) - l = tree.keys.find_all { |c| adjacent(c, :direction => direction).empty? } - return l - end - - # Collect all of the edges that the passed events match. Returns - # an array of edges. - def matching_edges(events, base = nil) - events.collect do |event| - source = base || event.source - - unless vertex?(source) - Puppet.warning "Got an event from invalid vertex %s" % source.ref - next - end - # Get all of the edges that this vertex should forward events - # to, which is the same thing as saying all edges directly below - # This vertex in the graph. - adjacent(source, :direction => :out, :type => :edges).find_all do |edge| - edge.match?(event.name) - end - end.compact.flatten - end - - # Take container information from another graph and use it - # to replace any container vertices with their respective leaves. - # This creates direct relationships where there were previously - # indirect relationships through the containers. - def splice!(other, type) - # We have to get the container list via a topological sort on the - # configuration graph, because otherwise containers that contain - # other containers will add those containers back into the - # graph. We could get a similar affect by only setting relationships - # to container leaves, but that would result in many more - # relationships. - containers = other.topsort.find_all { |v| v.is_a?(type) and vertex?(v) } - containers.each do |container| - # Get the list of children from the other graph. - children = other.adjacent(container, :direction => :out) - - # Just remove the container if it's empty. - if children.empty? - remove_vertex!(container) - next - end - - # First create new edges for each of the :in edges - [:in, :out].each do |dir| - edges = adjacent(container, :direction => dir, :type => :edges) - edges.each do |edge| - children.each do |child| - if dir == :in - s = edge.source - t = child - else - s = child - t = edge.target - end - - add_edge(s, t, edge.label) - end - - # Now get rid of the edge, so remove_vertex! works correctly. - remove_edge!(edge) - end - end - remove_vertex!(container) - end - end - - # A different way of walking a tree, and a much faster way than the - # one that comes with GRATR. - def tree_from_vertex(start, direction = :out) - predecessor={} - walk(start, direction) do |parent, child| - predecessor[child] = parent - end - predecessor - end -end diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb index c926258ca..73a6bdfed 100644 --- a/lib/puppet/simple_graph.rb +++ b/lib/puppet/simple_graph.rb @@ -94,10 +94,47 @@ class Puppet::SimpleGraph @edges.clear end + # Which resources a given resource depends upon. + def dependents(resource) + tree_from_vertex(resource).keys + end + + # Which resources depend upon the given resource. + def dependencies(resource) + # Cache the reversal graph, because it's somewhat expensive + # to create. + unless defined? @reversal and @reversal + @reversal = reversal + end + # Strangely, it's significantly faster to search a reversed + # tree in the :out direction than to search a normal tree + # in the :in direction. + @reversal.tree_from_vertex(resource, :out).keys + end + # Whether our graph is directed. Always true. Used to produce dot files. def directed? true end + + # Collect all of the edges that the passed events match. Returns + # an array of edges. + def matching_edges(events, base = nil) + events.collect do |event| + source = base || event.source + + unless vertex?(source) + Puppet.warning "Got an event from invalid vertex %s" % source.ref + next + end + # Get all of the edges that this vertex should forward events + # to, which is the same thing as saying all edges directly below + # This vertex in the graph. + adjacent(source, :direction => :out, :type => :edges).find_all do |edge| + edge.match?(event.name) + end + end.compact.flatten + end # Return a reversed version of this graph. def reversal @@ -154,6 +191,7 @@ class Puppet::SimpleGraph # Add a new vertex to the graph. def add_vertex(vertex) + @reversal = nil return false if vertex?(vertex) setup_vertex(vertex) true # don't return the VertexWrapper instance. @@ -180,6 +218,7 @@ class Puppet::SimpleGraph # Add a new edge. The graph user has to create the edge instance, # since they have to specify what kind of edge it is. def add_edge(source, target = nil, label = nil) + @reversal = nil if target edge = Puppet::Relationship.new(source, target, label) else @@ -250,6 +289,52 @@ class Puppet::SimpleGraph # induced_subgraph(gv).write_to_graphic_file('jpg', name) # end # end + + # Take container information from another graph and use it + # to replace any container vertices with their respective leaves. + # This creates direct relationships where there were previously + # indirect relationships through the containers. + def splice!(other, type) + # We have to get the container list via a topological sort on the + # configuration graph, because otherwise containers that contain + # other containers will add those containers back into the + # graph. We could get a similar affect by only setting relationships + # to container leaves, but that would result in many more + # relationships. + containers = other.topsort.find_all { |v| v.is_a?(type) and vertex?(v) } + containers.each do |container| + # Get the list of children from the other graph. + children = other.adjacent(container, :direction => :out) + + # Just remove the container if it's empty. + if children.empty? + remove_vertex!(container) + next + end + + # First create new edges for each of the :in edges + [:in, :out].each do |dir| + edges = adjacent(container, :direction => dir, :type => :edges) + edges.each do |edge| + children.each do |child| + if dir == :in + s = edge.source + t = child + else + s = child + t = edge.target + end + + add_edge(s, t, edge.label) + end + + # Now get rid of the edge, so remove_vertex! works correctly. + remove_edge!(edge) + end + end + remove_vertex!(container) + end + end def to_yaml_properties instance_variables @@ -263,6 +348,16 @@ class Puppet::SimpleGraph end end + # A different way of walking a tree, and a much faster way than the + # one that comes with GRATR. + def tree_from_vertex(start, direction = :out) + predecessor={} + walk(start, direction) do |parent, child| + predecessor[child] = parent + end + predecessor + end + # LAK:FIXME This is just a paste of the GRATR code with slight modifications. # Return a DOT::DOTDigraph for directed graphs or a DOT::DOTSubgraph for an @@ -304,6 +399,14 @@ class Puppet::SimpleGraph system('dotty', dotfile) end + # Just walk the tree and pass each edge. + def walk(source, direction, &block) + adjacent(source, :direction => direction).each do |target| + yield source, target + walk(target, direction, &block) + end + end + # Use +dot+ to create a graphical representation of the graph. Returns the # filename of the graphics file. def write_to_graphic_file (fmt='png', dotfile='graph') diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index e6dc60681..86467a5b4 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -431,8 +431,8 @@ class Transaction def initialize(resources) if resources.is_a?(Puppet::Node::Catalog) @catalog = resources - elsif resources.is_a?(Puppet::PGraph) - raise "Transactions should get catalogs now, not PGraph" + elsif resources.is_a?(Puppet::SimpleGraph) + raise "Transactions should get catalogs now, not SimpleGraph" else raise "Transactions require catalogs" end diff --git a/lib/puppet/util/graph.rb b/lib/puppet/util/graph.rb index d1ef36f8e..fc05cafd9 100644 --- a/lib/puppet/util/graph.rb +++ b/lib/puppet/util/graph.rb @@ -2,7 +2,7 @@ # Copyright (c) 2006. All rights reserved. require 'puppet' -require 'puppet/pgraph' +require 'puppet/simple_graph' # A module that handles the small amount of graph stuff in Puppet. module Puppet::Util::Graph @@ -12,7 +12,7 @@ module Puppet::Util::Graph def to_graph(graph = nil, &block) # Allow our calling function to send in a graph, so that we # can call this recursively with one graph. - graph ||= Puppet::PGraph.new + graph ||= Puppet::SimpleGraph.new self.each do |child| unless block_given? and ! yield(child) |