summaryrefslogtreecommitdiffstats
path: root/lib/puppet/simple_graph.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/simple_graph.rb')
-rw-r--r--lib/puppet/simple_graph.rb103
1 files changed, 103 insertions, 0 deletions
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')