summaryrefslogtreecommitdiffstats
path: root/lib/puppet/pgraph.rb
blob: bf156ed2d9fa27e96f9b80cbb8678a42cfa2b2fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env ruby
#
#  Created by Luke A. Kanies on 2006-11-24.
#  Copyright (c) 2006. All rights reserved.

require 'puppet/gratr/digraph'
require 'puppet/gratr/import'
require 'puppet/gratr/dot'
require 'puppet/relationship'

# This class subclasses a graph class in order to handle relationships
# among resources.
class Puppet::PGraph < GRATR::Digraph
    # This is the type used for splicing.
    attr_accessor :container_type
    
    # The dependencies for a given resource.
    def dependencies(resource)
        tree_from_vertex(resource, :dfs).keys
    end
    
    # Override this method to use our class instead.
    def edge_class()
        Puppet::Relationship
    end
    
    # Determine all of the leaf nodes below a given vertex.
    def leaves(vertex, type = :dfs)
        tree = tree_from_vertex(vertex, type)
        leaves = tree.keys.find_all { |c| adjacent(c, :direction => :out).empty? }
        return leaves
    end
    
    # Collect all of the edges that the passed events match.  Returns
    # an array of edges.
    def matching_edges(events)
        events.collect do |event|
            source = 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.event)
            end.each { |edge|
                target = edge.target
                if target.respond_to?(:ref)
                    source.info "Scheduling %s of %s" %
                        [edge.callback, target.ref]
                end
            }
        end.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)
        vertices.each do |vertex|
            # Go through each vertex and replace the edges with edges
            # to the leaves instead
            next unless vertex.is_a?(type)
            
            leaves = other.leaves(vertex)
            if leaves.empty?
                remove_vertex!(vertex)
                next
            end
            
            # First create new edges for each of the :in edges
            adjacent(vertex, :direction => :in, :type => :edges).each do |edge|
                leaves.each do |leaf|
                    add_edge!(edge.source, leaf, edge.label)
                    if cyclic?
                        raise ArgumentError,
                            "%s => %s results in a loop" %
                            [up, leaf]
                    end
                end
            end
            
            # Then for each of the out edges
            adjacent(vertex, :direction => :out, :type => :edges).each do |edge|
                leaves.each do |leaf|
                    add_edge!(leaf, edge.target, edge.label)
                    if cyclic?
                        raise ArgumentError,
                            "%s => %s results in a loop" %
                            [leaf, down]
                    end
                end
            end
            
            # And finally, remove the vertex entirely.
            remove_vertex!(vertex)
        end
    end
    
    # For some reason, unconnected vertices do not show up in
    # this graph.
    def to_jpg(name)
        gv = vertices()
        Dir.chdir("/Users/luke/Desktop/pics") do
            induced_subgraph(gv).write_to_graphic_file('jpg', name)
        end
    end
end

# $Id$