~ubuntu-branches/ubuntu/oneiric/puppet/oneiric-security

« back to all changes in this revision

Viewing changes to lib/puppet/metatype/evaluation.rb

  • Committer: Bazaar Package Importer
  • Author(s): Micah Anderson
  • Date: 2008-07-26 15:43:45 UTC
  • mto: (3.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20080726154345-1fmgo76b4l72ulvc
ImportĀ upstreamĀ versionĀ 0.24.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
class Puppet::Type
2
 
    # this method is responsible for collecting state changes
3
 
    # we always descend into the children before we evaluate our current
4
 
    # states
5
 
    # this returns any changes resulting from testing, thus 'collect'
6
 
    # rather than 'each'
 
2
    # This method is responsible for collecting property changes we always
 
3
    # descend into the children before we evaluate our current properties.
 
4
    # This returns any changes resulting from testing, thus 'collect' rather
 
5
    # than 'each'.
7
6
    def evaluate
 
7
        if self.provider.is_a?(Puppet::Provider)
 
8
            unless provider.class.suitable?
 
9
                raise Puppet::Error, "Provider %s is not functional on this platform" % provider.class.name
 
10
            end
 
11
        end
8
12
        #Puppet.err "Evaluating %s" % self.path.join(":")
9
13
        unless defined? @evalcount
10
14
            self.err "No evalcount defined on '%s' of type '%s'" %
13
17
        end
14
18
        @evalcount += 1
15
19
 
16
 
        changes = []
 
20
        if p = self.provider and p.respond_to?(:prefetch)
 
21
            p.prefetch
 
22
        end
17
23
 
18
 
        # this only operates on states, not states + children
 
24
        # this only operates on properties, not properties + children
19
25
        # it's important that we call retrieve() on the type instance,
20
 
        # not directly on the state, because it allows the type to override
 
26
        # not directly on the property, because it allows the type to override
21
27
        # the method, like pfile does
22
 
        self.retrieve
23
 
 
24
 
        # states() is a private method, returning an ordered list
25
 
        unless self.class.depthfirst?
26
 
            changes += statechanges()
27
 
        end
28
 
 
29
 
        changes << @children.collect { |child|
30
 
            ch = child.evaluate
31
 
            child.cache(:checked, Time.now)
32
 
            ch
33
 
        }
34
 
 
35
 
        if self.class.depthfirst?
36
 
            changes += statechanges()
37
 
        end
38
 
 
39
 
        changes.flatten!
 
28
        currentvalues = self.retrieve
 
29
 
 
30
        changes = propertychanges(currentvalues).flatten
40
31
 
41
32
        # now record how many changes we've resulted in
42
33
        if changes.length > 0
43
34
            self.debug "%s change(s)" %
44
35
                [changes.length]
45
36
        end
46
 
        self.cache(:checked, Time.now)
 
37
 
 
38
        # If we're in noop mode, we don't want to store the checked time,
 
39
        # because it will result in the resource not getting scheduled if
 
40
        # someone were to apply the catalog in non-noop mode.
 
41
        # We're going to go ahead and record that we checked if there were
 
42
        # no changes, since it's unlikely it will affect the scheduling.
 
43
        noop = noop?
 
44
        if ! noop or (noop && changes.length == 0)
 
45
            self.cache(:checked, Time.now)
 
46
        end
47
47
        return changes.flatten
48
48
    end
49
49
 
50
 
    # By default, try flushing the provider.
 
50
    # Flush the provider, if it supports it.  This is called by the
 
51
    # transaction.
51
52
    def flush
52
53
        if self.provider and self.provider.respond_to?(:flush)
53
54
            self.provider.flush
57
58
    # if all contained objects are in sync, then we're in sync
58
59
    # FIXME I don't think this is used on the type instances any more,
59
60
    # it's really only used for testing
60
 
    def insync?
 
61
    def insync?(is)
61
62
        insync = true
62
 
 
63
 
        if state = @states[:ensure]
64
 
            if state.insync? and state.should == :absent
 
63
        
 
64
        if property = @parameters[:ensure]
 
65
            unless is.include? property
 
66
               raise Puppet::DevError,
 
67
                        "The is value is not in the is array for '%s'" %
 
68
                        [property.name]
 
69
            end
 
70
            ensureis = is[property]           
 
71
            if property.insync?(ensureis) and property.should == :absent
65
72
                return true
66
73
            end
67
74
        end
68
75
 
69
 
        states.each { |state|
70
 
            unless state.insync?
71
 
                state.debug("Not in sync: %s vs %s" %
72
 
                    [state.is.inspect, state.should.inspect])
 
76
        properties.each { |property|
 
77
            unless is.include? property
 
78
               raise Puppet::DevError,
 
79
                        "The is value is not in the is array for '%s'" %
 
80
                        [property.name]
 
81
            end
 
82
 
 
83
            propis = is[property]
 
84
            unless property.insync?(propis)
 
85
                property.debug("Not in sync: %s vs %s" %
 
86
                    [propis.inspect, property.should.inspect])
73
87
                insync = false
74
88
            #else
75
 
            #    state.debug("In sync")
 
89
            #    property.debug("In sync")
76
90
            end
77
91
        }
78
92
 
79
93
        #self.debug("%s sync status is %s" % [self,insync])
80
94
        return insync
81
95
    end
82
 
 
83
 
    # retrieve the current value of all contained states
 
96
        
 
97
    # retrieve the current value of all contained properties
84
98
    def retrieve
 
99
         return currentpropvalues
 
100
    end
 
101
    
 
102
    # get a hash of the current properties.  
 
103
    def currentpropvalues(override_value = nil)
85
104
        # it's important to use the method here, as it follows the order
86
105
        # in which they're defined in the object
87
 
        states().each { |state|
88
 
            state.retrieve
89
 
        }
90
 
    end
91
 
 
92
 
    # Retrieve the changes associated with all of the states.
93
 
    def statechanges
 
106
        return properties().inject({}) { | prophash, property|
 
107
                   prophash[property] = override_value.nil? ? 
 
108
                                          property.retrieve : 
 
109
                                             override_value
 
110
                   prophash
 
111
               }
 
112
    end
 
113
 
 
114
    # Are we running in noop mode?
 
115
    def noop?
 
116
        if defined?(@noop)
 
117
            @noop
 
118
        else
 
119
            Puppet[:noop]
 
120
        end
 
121
    end
 
122
 
 
123
    def noop
 
124
        noop?
 
125
    end
 
126
     
 
127
    # Retrieve the changes associated with all of the properties.
 
128
    def propertychanges(currentvalues)
94
129
        # If we are changing the existence of the object, then none of
95
 
        # the other states matter.
 
130
        # the other properties matter.
96
131
        changes = []
97
 
        if @states.include?(:ensure) and ! @states[:ensure].insync?
98
 
            #self.info "ensuring %s from %s" %
99
 
            #    [@states[:ensure].should, @states[:ensure].is]
100
 
            changes = [Puppet::StateChange.new(@states[:ensure])]
101
 
        # Else, if the 'ensure' state is correctly absent, then do
 
132
        ensureparam = @parameters[:ensure]
 
133
 
 
134
        # This allows resource types to have 'ensure' be a parameter, which allows them to
 
135
        # just pass the parameter on to other generated resources.
 
136
        ensureparam = nil unless ensureparam.is_a?(Puppet::Property)
 
137
        if ensureparam && !currentvalues.include?(ensureparam)
 
138
            raise Puppet::DevError, "Parameter ensure defined but missing from current values"
 
139
        end
 
140
 
 
141
        if ensureparam and ! ensureparam.insync?(currentvalues[ensureparam])
 
142
            changes << Puppet::Transaction::Change.new(ensureparam, currentvalues[ensureparam])
 
143
        # Else, if the 'ensure' property is correctly absent, then do
102
144
        # nothing
103
 
        elsif @states.include?(:ensure) and @states[:ensure].is == :absent
104
 
            #self.info "Object is correctly absent"
 
145
        elsif ensureparam and currentvalues[ensureparam] == :absent
105
146
            return []
106
147
        else
107
 
            #if @states.include?(:ensure)
108
 
            #    self.info "ensure: Is: %s, Should: %s" %
109
 
            #        [@states[:ensure].is, @states[:ensure].should]
110
 
            #else
111
 
            #    self.info "no ensure state"
112
 
            #end
113
 
            changes = states().find_all { |state|
114
 
                ! state.insync?
115
 
            }.collect { |state|
116
 
                Puppet::StateChange.new(state)
 
148
            changes = properties().find_all { |property|
 
149
                currentvalues[property] ||= :absent
 
150
                ! property.insync?(currentvalues[property])
 
151
            }.collect { |property|
 
152
                Puppet::Transaction::Change.new(property, currentvalues[property])
117
153
            }
118
154
        end
119
155
 
120
156
        if Puppet[:debug] and changes.length > 0
121
 
            self.debug("Changing " + changes.collect { |ch|
122
 
                    ch.state.name
123
 
                }.join(",")
124
 
            )
 
157
            self.debug("Changing " + changes.collect { |ch| ch.property.name }.join(","))
125
158
        end
126
159
 
127
160
        changes
128
161
    end
129
162
end
130
163
 
131
 
# $Id: evaluation.rb 1856 2006-11-11 07:40:16Z luke $