1
# Created by Luke A. Kanies on 2006-11-24.
2
# Copyright (c) 2006. All rights reserved.
4
require 'puppet/relationship'
5
require 'puppet/simple_graph'
7
# This class subclasses a graph class in order to handle relationships
9
class Puppet::PGraph < Puppet::SimpleGraph
22
# Which resources a given resource depends upon.
23
def dependents(resource)
24
tree_from_vertex(resource).keys
27
# Which resources depend upon the given resource.
28
def dependencies(resource)
29
# Cache the reversal graph, because it's somewhat expensive
31
unless defined? @reversal and @reversal
34
# Strangely, it's significantly faster to search a reversed
35
# tree in the :out direction than to search a normal tree
36
# in the :in direction.
37
@reversal.tree_from_vertex(resource, :out).keys
40
# Determine all of the leaf nodes below a given vertex.
41
def leaves(vertex, direction = :out)
42
tree = tree_from_vertex(vertex, direction)
43
l = tree.keys.find_all { |c| adjacent(c, :direction => direction).empty? }
47
# Collect all of the edges that the passed events match. Returns
49
def matching_edges(events, base = nil)
50
events.collect do |event|
51
source = base || event.source
53
unless vertex?(source)
54
Puppet.warning "Got an event from invalid vertex %s" % source.ref
57
# Get all of the edges that this vertex should forward events
58
# to, which is the same thing as saying all edges directly below
59
# This vertex in the graph.
60
adjacent(source, :direction => :out, :type => :edges).find_all do |edge|
61
edge.match?(event.name)
66
# Take container information from another graph and use it
67
# to replace any container vertices with their respective leaves.
68
# This creates direct relationships where there were previously
69
# indirect relationships through the containers.
70
def splice!(other, type)
71
# We have to get the container list via a topological sort on the
72
# configuration graph, because otherwise containers that contain
73
# other containers will add those containers back into the
74
# graph. We could get a similar affect by only setting relationships
75
# to container leaves, but that would result in many more
77
containers = other.topsort.find_all { |v| v.is_a?(type) and vertex?(v) }
78
containers.each do |container|
79
# Get the list of children from the other graph.
80
children = other.adjacent(container, :direction => :out)
82
# Just remove the container if it's empty.
84
remove_vertex!(container)
88
# First create new edges for each of the :in edges
89
[:in, :out].each do |dir|
90
edges = adjacent(container, :direction => dir, :type => :edges)
92
children.each do |child|
101
add_edge(s, t, edge.label)
104
# Now get rid of the edge, so remove_vertex! works correctly.
108
remove_vertex!(container)
112
# A different way of walking a tree, and a much faster way than the
113
# one that comes with GRATR.
114
def tree_from_vertex(start, direction = :out)
116
walk(start, direction) do |parent, child|
117
predecessor[child] = parent