summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-11-26 09:55:04 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-11-26 09:55:04 +0000
commitccd7b581bf990df618d410441c1f8d349aa225d9 (patch)
tree768e134483b5ed8f82adc69eebba7e8a7146b55e /lib/puppet
parentc301b1b8f7fb417cf61b6ad4975eaa3714100306 (diff)
downloadpuppet-ccd7b581bf990df618d410441c1f8d349aa225d9.tar.gz
puppet-ccd7b581bf990df618d410441c1f8d349aa225d9.tar.xz
puppet-ccd7b581bf990df618d410441c1f8d349aa225d9.zip
Intermediate commit -- I am ready to start pushing the graph stuff into the types and transactions, which will break everything for a little while.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1894 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/pgraph.rb170
-rw-r--r--lib/puppet/relationship.rb51
-rw-r--r--lib/puppet/transaction.rb8
-rw-r--r--lib/puppet/type/component.rb19
-rw-r--r--lib/puppet/util/graph.rb23
5 files changed, 248 insertions, 23 deletions
diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb
new file mode 100644
index 000000000..fba93d20c
--- /dev/null
+++ b/lib/puppet/pgraph.rb
@@ -0,0 +1,170 @@
+#!/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
+ # Collect all of the targets for the list of events. Basically just iterates
+ # over the sources of the events and returns all of the targets of them.
+ def collect_targets(events)
+ events.collect do |event|
+ source = event.source
+ start = source
+
+ # Get all of the edges that this vertex points at
+ adjacent(source, :direction => :out, :type => :edges).find_all do |edge|
+ edge.match?(event.event)
+ end.collect { |event|
+ target = event.target
+ if target.respond_to?(:ref)
+ source.info "Scheduling %s of %s" %
+ [event.callback, target.ref]
+ end
+ target
+ }
+ end.flatten
+ end
+
+ # 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
+
+ # 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)
+ next if leaves.empty?
+
+ # First create new edges for each of the :in edges
+ adjacent(vertex, :direction => :in).each do |up|
+ leaves.each do |leaf|
+ add_edge!(up, leaf)
+ 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).each do |down|
+ leaves.each do |leaf|
+ add_edge!(leaf, down)
+ 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
+
+ # Trigger any subscriptions to a child. This does an upwardly recursive
+ # search -- it triggers the passed object, but also the object's parent
+ # and so on up the tree.
+ def trigger(child)
+ obj = child
+ callbacks = Hash.new { |hash, key| hash[key] = [] }
+ sources = Hash.new { |hash, key| hash[key] = [] }
+
+ trigged = []
+ while obj
+ if @targets.include?(obj)
+ callbacks.clear
+ sources.clear
+ @targets[obj].each do |event, sub|
+ # Collect all of the subs for each callback
+ callbacks[sub.callback] << sub
+
+ # And collect the sources for logging
+ sources[event.source] << sub.callback
+ end
+
+ sources.each do |source, callbacklist|
+ obj.debug "%s[%s] results in triggering %s" %
+ [source.class.name, source.name, callbacklist.join(", ")]
+ end
+
+ callbacks.each do |callback, subs|
+ message = "Triggering '%s' from %s dependencies" %
+ [callback, subs.length]
+ obj.notice message
+ # At this point, just log failures, don't try to react
+ # to them in any way.
+ begin
+ obj.send(callback)
+ @resourcemetrics[:restarted] += 1
+ rescue => detail
+ obj.err "Failed to call %s on %s: %s" %
+ [callback, obj, detail]
+
+ @resourcemetrics[:failed_restarts] += 1
+
+ if Puppet[:debug]
+ puts detail.backtrace
+ end
+ end
+
+ # And then add an event for it.
+ trigged << Puppet::Event.new(
+ :event => :triggered,
+ :transaction => self,
+ :source => obj,
+ :message => message
+ )
+
+ triggered(obj, callback)
+ end
+ end
+
+ obj = obj.parent
+ end
+
+ if trigged.empty?
+ return nil
+ else
+ return trigged
+ end
+ end
+
+ 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$
diff --git a/lib/puppet/relationship.rb b/lib/puppet/relationship.rb
new file mode 100644
index 000000000..cbd15b2af
--- /dev/null
+++ b/lib/puppet/relationship.rb
@@ -0,0 +1,51 @@
+#!/usr/bin/env ruby
+#
+# Created by Luke A. Kanies on 2006-11-24.
+# Copyright (c) 2006. All rights reserved.
+
+require 'puppet/gratr'
+
+# subscriptions are permanent associations determining how different
+# objects react to an event
+
+class Puppet::Relationship < GRATR::Edge
+ # Return the callback
+ def callback
+ label[:callback]
+ end
+
+ # Return our event.
+ def event
+ label[:event]
+ end
+
+ def initialize(source, target, label = nil)
+ if label
+ unless label.is_a?(Hash)
+ raise Puppet::DevError, "The label must be a hash"
+ end
+
+ if label[:event] and label[:event] != :NONE and ! label[:callback]
+ raise Puppet::DevError, "You must pass a callback for non-NONE events"
+ end
+ else
+ label = {}
+ end
+
+ super(source, target, label)
+ end
+
+ # Does the passed event match our event? This is where the meaning
+ # of :NONE comes from.
+ def match?(event)
+ if event == :NONE or self.event == :NONE
+ return false
+ elsif self.event == :ALL_EVENTS or event == :ALL_EVENTS or event == self.event
+ return true
+ else
+ return false
+ end
+ end
+end
+
+# $Id$
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index a7ea48a19..1551acbb6 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -29,7 +29,7 @@ class Transaction
# First make sure there are no failed dependencies
child.eachdependency do |dep|
skip = false
- if @failures[dep] > 0
+ if fails = failed?(dep)
child.notice "Dependency %s[%s] has %s failures" %
[dep.class.name, dep.name, @failures[dep]]
skip = true
@@ -209,7 +209,11 @@ class Transaction
# Determine whether a given object has failed.
def failed?(obj)
- @failures[obj] > 0
+ if @failures[obj] > 0
+ return @failures[obj]
+ else
+ return false
+ end
end
# this should only be called by a Puppet::Container object now
diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb
index c159ccc83..3165d9e11 100644
--- a/lib/puppet/type/component.rb
+++ b/lib/puppet/type/component.rb
@@ -5,6 +5,7 @@
require 'puppet'
require 'puppet/type'
require 'puppet/transaction'
+require 'puppet/pgraph'
module Puppet
newtype(:component) do
@@ -149,6 +150,24 @@ module Puppet
end
}
end
+
+ # Convert to a graph object with all of the container info.
+ def to_graph
+ graph = Puppet::PGraph.new
+
+ delver = proc do |obj|
+ obj.each do |child|
+ if child.is_a?(Puppet::Type)
+ graph.add_edge!(obj, child)
+ delver.call(child)
+ end
+ end
+ end
+
+ delver.call(self)
+
+ return graph
+ end
def to_s
return "component(%s)" % self.title
diff --git a/lib/puppet/util/graph.rb b/lib/puppet/util/graph.rb
index c32d15cb4..d9e122c7b 100644
--- a/lib/puppet/util/graph.rb
+++ b/lib/puppet/util/graph.rb
@@ -2,18 +2,7 @@
# Copyright (c) 2006. All rights reserved.
require 'puppet'
-require 'puppet/gratr/digraph'
-require 'puppet/gratr/import'
-require 'puppet/gratr/dot'
-
-class GRATR::Digraph
- # 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
-end
+require 'puppet/pgraph'
# A module that handles the small amount of graph stuff in Puppet.
module Puppet::Util::Graph
@@ -23,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 ||= GRATR::Digraph.new
+ graph ||= Puppet::PGraph.new
self.each do |child|
unless block_given? and ! yield(child)
@@ -45,14 +34,6 @@ module Puppet::Util::Graph
graph
end
-
- def to_jpg(graph = nil)
- graph ||= to_graph
- gv = graph.vertices
- Dir.chdir("/Users/luke/Desktop/pics") do
- graph.induced_subgraph(gv).write_to_graphic_file('jpg', 'graph')
- end
- end
end
# $Id$ \ No newline at end of file