summaryrefslogtreecommitdiffstats
path: root/lib/puppet/type/state.rb
blob: c30a4f4d1628935319d602c41b4051bee5a15cd7 (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# The virtual base class for states, which are the self-contained building
# blocks for actually doing work on the system.

require 'puppet'
require 'puppet/element'
require 'puppet/statechange'

module Puppet
class State < Puppet::Element
    attr_accessor :is, :parent

    # Because 'should' uses an array, we have a special method for handling
    # it.  We also want to keep copies of the original values, so that
    # they can be retrieved and compared later when merging.
    attr_reader :shouldorig

    @virtual = true

    class << self
        attr_accessor :unmanaged
        attr_reader :name
    end

    # initialize our state
    def initialize(hash)
        @is = nil

        unless hash.include?(:parent)
            raise Puppet::DevError, "State %s was not passed a parent" % self
        end
        @parent = hash[:parent]

        if hash.include?(:should)
            self.should = hash[:should]
        end

        if hash.include?(:is)
            self.is = hash[:is]
        end
    end

    # Determine whether the state is in-sync or not.  If @should is
    # not defined or is set to a non-true value, then we do not have
    # a valid value for it and thus consider the state to be in-sync
    # since we cannot fix it.  Otherwise, we expect our should value
    # to be an array, and if @is matches any of those values, then
    # we consider it to be in-sync.
    def insync?
        #debug "%s value is '%s', should be '%s'" %
        #    [self,self.is.inspect,self.should.inspect]
        unless defined? @should and @should
            return true
        end

        unless @should.is_a?(Array)
            raise Puppet::DevError, "%s's should is not array" % self.class.name
        end

        # an empty array is analogous to no should values
        if @should.empty?
            return true
        end

        # Look for a matching value
        @should.each { |val|
            if @is == val
                return true
            end
        }

        # otherwise, return false
        return false
    end

    # each state class must define the name() method, and state instances
    # do not change that name
    # this implicitly means that a given object can only have one state
    # instance of a given state class
    def name
        return self.class.name
    end

    # for testing whether we should actually do anything
    def noop
        unless defined? @noop
            @noop = false
        end
        tmp = @noop || self.parent.noop || Puppet[:noop] || false
        #debug "noop is %s" % tmp
        return tmp
    end

    # return the full path to us, for logging and rollback; not currently
    # used
    def path
        return [@parent.path, self.name].flatten
    end

    # Only return the first value
    def should
        if defined? @should
            unless @should.is_a?(Array)
                self.warning @should.inspect
                raise Puppet::DevError, "should for %s on %s is not an array" %
                    [self.class.name, @parent.name]
            end
            return @should[0]
        else
            return nil
        end
    end

    # Set the should value.
    def should=(values)
        unless values.is_a?(Array)
            values = [values]
        end

        @shouldorig = values

        if self.respond_to?(:shouldprocess)
            @should = values.collect { |val|
                self.shouldprocess(val)
            }
        else
            @should = values
        end
    end


    # How should a state change be printed as a string?
    def change_to_s
        if @is == :notfound
            return "%s: defined '%s' as '%s'" %
                [@parent, self.name, self.should_to_s]
        elsif self.should == :notfound
            return "%s: undefined %s from '%s'" %
                [self.parent, self.name, self.is_to_s]
        else
            return "%s changed '%s' to '%s'" %
                [self.name, self.is_to_s, self.should_to_s]
        end
    end

    # because the @should and @is vars might be in weird formats,
    # we need to set up a mechanism for pretty printing of the values
    # default to just the values, but this way individual states can
    # override these methods
    def is_to_s
        @is
    end

    def should_to_s
        @should
    end

    def to_s
        return "%s(%s)" % [@parent.name,self.name]
    end
end
end

# $Id$