summaryrefslogtreecommitdiffstats
path: root/lib/puppet/event.rb
blob: d01863de244517f5fa98ce5a61fadd31048dc526 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/local/bin/ruby -w

# $Id$

# included so we can test object types
require 'puppet'
require 'puppet/type'

module Puppet
    # events are transient packets of information; they result in one or more (or none)
    # subscriptions getting triggered, and then they get cleared
    # eventually, these will be passed on to some central event system
	class Event
        include Puppet
        # subscriptions are permanent associations determining how different
        # objects react to an event
        class Subscription
            include Puppet
            attr_accessor :source, :event, :target

            def initialize(hash)
                @triggered = false

                hash.each { |param,value|
                    # assign each value appropriately
                    # this is probably wicked-slow
                    self.send(param.to_s + "=",value)
                }
                #Puppet.debug "New Subscription: '%s' => '%s'" %
                #    [@source,@event]
            end

            # the transaction is passed in so that we can notify it if
            # something fails
            def trigger(transaction)
                # this is potentially incomplete, because refreshing an object
                # could theoretically kick off an event, which would not get run
                # or, because we're executing the first subscription rather than
                # the last, a later-refreshed object could somehow be connected
                # to the "old" object rather than "new"
                # but we're pretty far from that being a problem
                event = nil

                if @event == :NONE
                    # just ignore these subscriptions
                    return
                end

                if transaction.triggercount(self) > 0
                    Puppet.debug "%s has already run" % self
                else
                    Puppet.debug "'%s' matched '%s'; triggering '%s' on '%s'" %
                        [@source,@event,@method,@target]
                    begin
                        if @target.respond_to?(@method)
                            event = @target.send(@method)
                        else
                            Puppet.debug "'%s' of type '%s' does not respond to '%s'" %
                                [@target,@target.class,@method.inspect]
                        end
                    rescue => detail
                        # um, what the heck do i do when an object fails to refresh?
                        # shouldn't that result in the transaction rolling back?
                        # the 'onerror' metaparam will be used to determine
                        # behaviour in that case
                        Puppet.err "'%s' failed to %s: '%s'" %
                            [@target,@method,detail]
                        raise
                        #raise "We need to roll '%s' transaction back" %
                            #transaction
                    end
                    transaction.triggered(self)
                end
                return event
            end
        end

		attr_accessor :event, :source, :transaction

        @@events = []

        @@subscriptions = []

        # I think this method is obsolete
        def self.process
            Puppet.debug "Processing events"
            @@events.each { |event|
                @@subscriptions.find_all { |sub|
                    #debug "Sub source: '%s'; event object: '%s'" %
                    #    [sub.source.inspect,event.object.inspect]
                    sub.source == event.object and
                        (sub.event == event.event or
                         sub.event == :ALL_EVENTS)
                }.each { |sub|
                    Puppet.debug "Found subscription to %s" % event
                    sub.trigger(event.transaction)
                }
            }

            @@events.clear
        end

        # I think this method is obsolete
        def self.subscribe(hash)
            if hash[:event] == '*'
                hash[:event] = :ALL_EVENTS
            end
            sub = Subscription.new(hash)

            # add to the correct area
            @@subscriptions.push sub
        end

		def initialize(args)
            unless args.include?(:event) and args.include?(:source)
				raise Puppet::DevError, "Event.new called incorrectly"
			end

			@change = args[:change]
			@event = args[:event]
			@source = args[:source]
			@transaction = args[:transaction]

            #Puppet.info "%s: %s(%s)" %
            #Puppet.info "%s: %s changed from %s to %s" %
            #    [@object,@state.name, @state.is,@state.should]

            # initially, just stuff all instances into a central bucket
            # to be handled as a batch
            #@@events.push self
		end

        def to_s
            self.event.to_s
        end
	end
end