puppet 0.9.2 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +58 -0
- data/README +21 -18
- data/Rakefile +176 -36
- data/bin/puppet +34 -48
- data/bin/puppetca +41 -28
- data/bin/puppetd +87 -65
- data/bin/puppetdoc +99 -23
- data/bin/puppetmasterd +72 -91
- data/conf/redhat/client.init +80 -0
- data/conf/redhat/client.sysconfig +11 -0
- data/conf/redhat/fileserver.conf +12 -0
- data/conf/redhat/puppet.spec +130 -0
- data/conf/redhat/server.init +89 -0
- data/conf/redhat/server.sysconfig +9 -0
- data/examples/code/allatonce +2 -2
- data/examples/code/assignments +1 -1
- data/examples/code/classing +2 -2
- data/examples/code/components +2 -2
- data/examples/code/file.bl +5 -5
- data/examples/code/filedefaults +2 -2
- data/examples/code/fileparsing +1 -1
- data/examples/code/filerecursion +1 -1
- data/examples/code/functions +1 -1
- data/examples/code/groups +1 -1
- data/examples/code/importing +1 -1
- data/examples/code/nodes +1 -1
- data/examples/code/one +1 -1
- data/examples/code/relationships +2 -2
- data/examples/code/simpletests +5 -5
- data/examples/code/snippets/argumentdefaults +2 -2
- data/examples/code/snippets/casestatement +16 -8
- data/examples/code/snippets/classheirarchy.pp +4 -4
- data/examples/code/snippets/classincludes.pp +4 -4
- data/examples/code/snippets/classpathtest +2 -2
- data/examples/code/snippets/componentmetaparams.pp +11 -0
- data/examples/code/snippets/dirchmod +5 -5
- data/examples/code/snippets/emptyclass.pp +9 -0
- data/examples/code/snippets/failmissingexecpath.pp +1 -1
- data/examples/code/snippets/falsevalues.pp +1 -1
- data/examples/code/snippets/filecreate +5 -5
- data/examples/code/snippets/implicititeration +5 -5
- data/examples/code/snippets/multipleinstances +4 -4
- data/examples/code/snippets/namevartest +3 -3
- data/examples/code/snippets/scopetest +1 -1
- data/examples/code/snippets/selectorvalues.pp +3 -3
- data/examples/code/snippets/simpledefaults +2 -2
- data/examples/code/snippets/simpleselector +5 -5
- data/examples/code/snippets/singleary.pp +19 -0
- data/examples/root/etc/init.d/sleeper +3 -2
- data/ext/emacs/puppet-mode-init.el +6 -0
- data/ext/emacs/puppet-mode.el +189 -0
- data/ext/ldap/puppet.schema +17 -0
- data/ext/{module:puppet → module_puppet} +30 -31
- data/ext/vim/filetype.vim +9 -0
- data/ext/vim/puppet.vim +87 -0
- data/install.rb +63 -30
- data/lib/puppet.rb +216 -122
- data/lib/puppet/client.rb +51 -416
- data/lib/puppet/client/ca.rb +17 -0
- data/lib/puppet/client/dipper.rb +78 -0
- data/lib/puppet/client/file.rb +20 -0
- data/lib/puppet/client/log.rb +17 -0
- data/lib/puppet/client/master.rb +246 -0
- data/lib/puppet/client/proxy.rb +27 -0
- data/lib/puppet/client/status.rb +7 -0
- data/lib/puppet/config.rb +563 -13
- data/lib/puppet/daemon.rb +50 -22
- data/lib/puppet/element.rb +4 -4
- data/lib/puppet/event-loop.rb +1 -0
- data/lib/puppet/event-loop/better-definers.rb +367 -0
- data/lib/puppet/event-loop/event-loop.rb +355 -0
- data/lib/puppet/event-loop/signal-system.rb +220 -0
- data/lib/puppet/event.rb +9 -11
- data/lib/puppet/filetype.rb +195 -0
- data/lib/puppet/log.rb +35 -12
- data/lib/puppet/metric.rb +2 -2
- data/lib/puppet/networkclient.rb +145 -0
- data/lib/puppet/parameter.rb +335 -0
- data/lib/puppet/parser/ast.rb +42 -1453
- data/lib/puppet/parser/ast/astarray.rb +88 -0
- data/lib/puppet/parser/ast/branch.rb +47 -0
- data/lib/puppet/parser/ast/caseopt.rb +66 -0
- data/lib/puppet/parser/ast/casestatement.rb +78 -0
- data/lib/puppet/parser/ast/classdef.rb +78 -0
- data/lib/puppet/parser/ast/compdef.rb +111 -0
- data/lib/puppet/parser/ast/component.rb +105 -0
- data/lib/puppet/parser/ast/hostclass.rb +82 -0
- data/lib/puppet/parser/ast/leaf.rb +86 -0
- data/lib/puppet/parser/ast/node.rb +103 -0
- data/lib/puppet/parser/ast/nodedef.rb +68 -0
- data/lib/puppet/parser/ast/objectdef.rb +336 -0
- data/lib/puppet/parser/ast/objectparam.rb +30 -0
- data/lib/puppet/parser/ast/objectref.rb +76 -0
- data/lib/puppet/parser/ast/selector.rb +60 -0
- data/lib/puppet/parser/ast/typedefaults.rb +45 -0
- data/lib/puppet/parser/ast/vardef.rb +44 -0
- data/lib/puppet/parser/interpreter.rb +31 -14
- data/lib/puppet/parser/lexer.rb +2 -4
- data/lib/puppet/parser/parser.rb +332 -242
- data/lib/puppet/parser/scope.rb +55 -38
- data/lib/puppet/server.rb +43 -44
- data/lib/puppet/server/authstore.rb +3 -6
- data/lib/puppet/server/ca.rb +5 -2
- data/lib/puppet/server/filebucket.rb +2 -4
- data/lib/puppet/server/fileserver.rb +28 -12
- data/lib/puppet/server/logger.rb +15 -4
- data/lib/puppet/server/master.rb +62 -7
- data/lib/puppet/sslcertificates.rb +41 -607
- data/lib/puppet/sslcertificates/ca.rb +291 -0
- data/lib/puppet/sslcertificates/certificate.rb +283 -0
- data/lib/puppet/statechange.rb +6 -1
- data/lib/puppet/storage.rb +67 -56
- data/lib/puppet/transaction.rb +25 -9
- data/lib/puppet/transportable.rb +102 -22
- data/lib/puppet/type.rb +1096 -315
- data/lib/puppet/type/component.rb +30 -21
- data/lib/puppet/type/cron.rb +409 -448
- data/lib/puppet/type/exec.rb +234 -174
- data/lib/puppet/type/group.rb +65 -82
- data/lib/puppet/type/nameservice.rb +247 -3
- data/lib/puppet/type/nameservice/netinfo.rb +29 -40
- data/lib/puppet/type/nameservice/objectadd.rb +52 -66
- data/lib/puppet/type/nameservice/posix.rb +6 -194
- data/lib/puppet/type/package.rb +447 -295
- data/lib/puppet/type/package/apt.rb +51 -50
- data/lib/puppet/type/package/bsd.rb +82 -0
- data/lib/puppet/type/package/dpkg.rb +85 -88
- data/lib/puppet/type/package/rpm.rb +67 -63
- data/lib/puppet/type/package/sun.rb +119 -98
- data/lib/puppet/type/package/yum.rb +41 -37
- data/lib/puppet/type/parsedtype.rb +295 -0
- data/lib/puppet/type/parsedtype/host.rb +143 -0
- data/lib/puppet/type/parsedtype/port.rb +232 -0
- data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
- data/lib/puppet/type/pfile.rb +484 -460
- data/lib/puppet/type/pfile/checksum.rb +237 -181
- data/lib/puppet/type/pfile/content.rb +67 -0
- data/lib/puppet/type/pfile/ensure.rb +212 -0
- data/lib/puppet/type/pfile/group.rb +106 -105
- data/lib/puppet/type/pfile/mode.rb +98 -101
- data/lib/puppet/type/pfile/source.rb +228 -209
- data/lib/puppet/type/pfile/type.rb +18 -21
- data/lib/puppet/type/pfile/uid.rb +127 -130
- data/lib/puppet/type/pfilebucket.rb +68 -63
- data/lib/puppet/type/schedule.rb +341 -0
- data/lib/puppet/type/service.rb +351 -255
- data/lib/puppet/type/service/base.rb +9 -14
- data/lib/puppet/type/service/debian.rb +32 -38
- data/lib/puppet/type/service/init.rb +130 -130
- data/lib/puppet/type/service/smf.rb +48 -20
- data/lib/puppet/type/state.rb +229 -16
- data/lib/puppet/type/symlink.rb +51 -63
- data/lib/puppet/type/tidy.rb +105 -102
- data/lib/puppet/type/user.rb +118 -180
- data/lib/puppet/util.rb +100 -6
- data/test/certmgr/certmgr.rb +0 -1
- data/test/client/client.rb +4 -4
- data/test/executables/puppetbin.rb +7 -14
- data/test/executables/puppetca.rb +18 -24
- data/test/executables/puppetd.rb +7 -16
- data/test/executables/puppetmasterd.rb +7 -9
- data/test/executables/puppetmodule.rb +11 -16
- data/test/language/ast.rb +11 -7
- data/test/language/interpreter.rb +1 -1
- data/test/language/scope.rb +2 -0
- data/test/language/snippets.rb +30 -5
- data/test/language/transportable.rb +77 -0
- data/test/other/config.rb +316 -0
- data/test/other/events.rb +22 -21
- data/test/other/log.rb +14 -14
- data/test/other/metrics.rb +4 -8
- data/test/other/overrides.rb +5 -5
- data/test/other/relationships.rb +4 -2
- data/test/other/storage.rb +64 -3
- data/test/other/transactions.rb +20 -20
- data/test/parser/parser.rb +7 -4
- data/test/puppet/conffiles.rb +12 -12
- data/test/puppet/defaults.rb +13 -11
- data/test/puppet/utiltest.rb +14 -11
- data/test/puppettest.rb +156 -48
- data/test/server/bucket.rb +2 -2
- data/test/server/fileserver.rb +6 -6
- data/test/server/logger.rb +19 -11
- data/test/server/master.rb +33 -4
- data/test/server/server.rb +2 -7
- data/test/types/basic.rb +5 -7
- data/test/types/component.rb +22 -18
- data/test/types/cron.rb +111 -44
- data/test/types/exec.rb +116 -59
- data/test/types/file.rb +262 -137
- data/test/types/filebucket.rb +13 -15
- data/test/types/fileignoresource.rb +12 -16
- data/test/types/filesources.rb +73 -48
- data/test/types/filetype.rb +13 -15
- data/test/types/group.rb +15 -13
- data/test/types/host.rb +146 -0
- data/test/types/package.rb +74 -63
- data/test/types/port.rb +139 -0
- data/test/types/query.rb +8 -8
- data/test/types/schedule.rb +335 -0
- data/test/types/service.rb +137 -21
- data/test/types/sshkey.rb +140 -0
- data/test/types/symlink.rb +3 -5
- data/test/types/tidy.rb +5 -14
- data/test/types/type.rb +67 -11
- data/test/types/user.rb +25 -23
- metadata +186 -122
- data/lib/puppet/type/pfile/create.rb +0 -108
- data/lib/puppet/type/pprocess.rb +0 -97
- data/lib/puppet/type/typegen.rb +0 -149
- data/lib/puppet/type/typegen/filerecord.rb +0 -243
- data/lib/puppet/type/typegen/filetype.rb +0 -316
- data/test/other/state.rb +0 -106
data/lib/puppet/type.rb
CHANGED
@@ -4,15 +4,21 @@ require 'puppet/element'
|
|
4
4
|
require 'puppet/event'
|
5
5
|
require 'puppet/metric'
|
6
6
|
require 'puppet/type/state'
|
7
|
+
require 'puppet/parameter'
|
8
|
+
require 'puppet/util'
|
7
9
|
# see the bottom of the file for the rest of the inclusions
|
8
10
|
|
9
|
-
module Puppet
|
10
|
-
# This class is the abstract base class for the mechanism for organizing
|
11
|
-
# work. No work is actually done by this class or its subclasses; rather,
|
12
|
-
# the subclasses include states which do the actual work.
|
13
|
-
# See state.rb for how work is actually done.
|
11
|
+
module Puppet
|
14
12
|
class Type < Puppet::Element
|
15
|
-
|
13
|
+
# Types (which map to elements in the languages) are entirely composed of
|
14
|
+
# attribute value pairs. Generally, Puppet calls any of these things an
|
15
|
+
# 'attribute', but these attributes always take one of three specific
|
16
|
+
# forms: parameters, metaparams, or states.
|
17
|
+
|
18
|
+
# In naming methods, I have tried to consistently name the method so
|
19
|
+
# that it is clear whether it operates on all attributes (thus has 'attr' in
|
20
|
+
# the method name, or whether it operates on a specific type of attributes.
|
21
|
+
attr_accessor :children, :parent
|
16
22
|
attr_accessor :file, :line, :tags
|
17
23
|
|
18
24
|
attr_writer :implicit
|
@@ -36,123 +42,105 @@ class Type < Puppet::Element
|
|
36
42
|
# a little fakery, since Puppet itself isn't a type
|
37
43
|
# I don't think this is used any more, now that the language can't
|
38
44
|
# call methods
|
39
|
-
|
45
|
+
#@name = :puppet
|
40
46
|
|
41
47
|
# set it to something to silence the tests, but otherwise not used
|
42
|
-
|
48
|
+
#@namevar = :notused
|
43
49
|
|
44
50
|
# again, silence the tests; the :notused has to be there because it's
|
45
51
|
# the namevar
|
46
|
-
@states = []
|
47
|
-
@parameters = [:notused]
|
48
52
|
|
49
|
-
# @paramdoc = Hash.new
|
50
|
-
|
51
|
-
# the parameters that all instances will accept
|
52
|
-
@@metaparams = [
|
53
|
-
:onerror,
|
54
|
-
:noop,
|
55
|
-
:schedule,
|
56
|
-
:check,
|
57
|
-
:subscribe,
|
58
|
-
:require,
|
59
|
-
:loglevel
|
60
|
-
]
|
61
|
-
|
62
|
-
@@metaparamdoc = Hash.new { |hash,key|
|
63
|
-
if key.is_a?(String)
|
64
|
-
key = key.intern
|
65
|
-
end
|
66
|
-
if hash.include?(key)
|
67
|
-
hash[key]
|
68
|
-
else
|
69
|
-
"Metaparam Documentation for %s not found" % key
|
70
|
-
end
|
71
|
-
}
|
72
|
-
|
73
|
-
@@metaparamdoc[:onerror] = "How to handle errors -- roll back innermost
|
74
|
-
transaction, roll back entire transaction, ignore, etc. Currently
|
75
|
-
non-functional."
|
76
|
-
@@metaparamdoc[:noop] = "Boolean flag indicating whether work should actually
|
77
|
-
be done."
|
78
|
-
@@metaparamdoc[:schedule] = "On what schedule the object should be managed.
|
79
|
-
Currently non-functional."
|
80
|
-
@@metaparamdoc[:check] = "States which should have their values retrieved
|
81
|
-
but which should not actually be modified. This is currently used
|
82
|
-
internally, but will eventually be used for querying."
|
83
|
-
@@metaparamdoc[:require] = "One or more objects that this object depends on.
|
84
|
-
This is used purely for guaranteeing that changes to required objects
|
85
|
-
happen before the dependent object."
|
86
|
-
@@metaparamdoc[:subscribe] = "One or more objects that this object depends on.
|
87
|
-
Changes in the subscribed to objects result in the dependent objects being
|
88
|
-
refreshed (e.g., a service will get restarted)."
|
89
|
-
@@metaparamdoc[:loglevel] = "Sets the level that information will be logged:
|
90
|
-
debug, info, verbose, notice, warning, err, alert, emerg or crit"
|
91
|
-
|
92
53
|
# class methods dealing with Type management
|
93
54
|
|
94
55
|
public
|
95
56
|
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
57
|
+
# the Type class attribute accessors
|
58
|
+
class << self
|
59
|
+
attr_reader :name, :states
|
60
|
+
|
61
|
+
include Enumerable
|
62
|
+
|
63
|
+
def inspect
|
64
|
+
Puppet.info "inspecting class with name %s" % self.name
|
65
|
+
"Type(%s)" % self.name
|
105
66
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
67
|
+
|
68
|
+
# This class is aggregatable, meaning that instances are defined on
|
69
|
+
# one system but instantiated on another
|
70
|
+
def isaggregatable
|
71
|
+
@aggregatable = true
|
110
72
|
end
|
111
|
-
}
|
112
73
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
# Create @@typehash from @@typeary. This is meant to be run
|
119
|
-
# multiple times -- whenever it is discovered that the two
|
120
|
-
# objects have differents lengths.
|
121
|
-
def self.buildtypehash
|
122
|
-
@@typeary.each { |otype|
|
123
|
-
if @@typehash.include?(otype.name)
|
124
|
-
if @@typehash[otype.name] != otype
|
125
|
-
Puppet.warning("Object type %s is already defined (%s vs %s)" %
|
126
|
-
[otype.name,@@typehash[otype.name],otype])
|
127
|
-
end
|
74
|
+
# Is this one aggregatable?
|
75
|
+
def aggregatable?
|
76
|
+
if defined? @aggregatable
|
77
|
+
return @aggregatable
|
128
78
|
else
|
129
|
-
|
79
|
+
return false
|
130
80
|
end
|
131
|
-
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def inspect
|
85
|
+
str = "Type(%s)" % self.name
|
86
|
+
if defined? @states
|
87
|
+
str += " States(" + @states.inspect + ")"
|
88
|
+
end
|
89
|
+
if defined? @parameters
|
90
|
+
str += " Parameters(" + @parameters.inspect + ")"
|
91
|
+
end
|
92
|
+
if defined? @metaparams
|
93
|
+
str += " Metaparams(" + @metaparams.inspect + ")"
|
94
|
+
end
|
95
|
+
str
|
132
96
|
end
|
133
97
|
|
134
98
|
# iterate across all of the subclasses of Type
|
135
99
|
def self.eachtype
|
136
|
-
|
100
|
+
@types.each do |name, type|
|
101
|
+
# Only consider types that have names
|
102
|
+
#if ! type.parameters.empty? or ! type.validstates.empty?
|
103
|
+
yield type
|
104
|
+
#end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Should we add the 'ensure' state to this class?
|
109
|
+
def self.ensurable?
|
110
|
+
# If the class has all three of these methods defined, then it's
|
111
|
+
# ensurable.
|
112
|
+
#ens = [:create, :destroy].inject { |set, method|
|
113
|
+
ens = [:exists?, :create, :destroy].inject { |set, method|
|
114
|
+
set &&= self.public_method_defined?(method)
|
115
|
+
}
|
116
|
+
|
117
|
+
#puts "%s ensurability: %s" % [self.name, ens]
|
118
|
+
|
119
|
+
return ens
|
137
120
|
end
|
138
121
|
|
139
122
|
# The work that gets done for every subclass of Type
|
140
123
|
# this is an implicit method called by Ruby for us
|
141
|
-
def self.inherited(sub)
|
142
|
-
|
124
|
+
#def self.inherited(sub)
|
125
|
+
# sub.initvars
|
143
126
|
|
144
127
|
#debug("subtype %s(%s) just created" % [sub,sub.superclass])
|
145
128
|
# add it to the master list
|
146
129
|
# unfortunately we can't yet call sub.name, because the #inherited
|
147
130
|
# method gets called before any commands in the class definition
|
148
131
|
# get executed, which, um, sucks
|
149
|
-
|
150
|
-
end
|
132
|
+
#@@typeary.push(sub)
|
133
|
+
#end
|
151
134
|
|
152
135
|
# all of the variables that must be initialized for each subclass
|
153
136
|
def self.initvars
|
154
137
|
# all of the instances of this class
|
155
138
|
@objects = Hash.new
|
139
|
+
@aliases = Hash.new
|
140
|
+
|
141
|
+
unless defined? @parameters
|
142
|
+
@parameters = []
|
143
|
+
end
|
156
144
|
|
157
145
|
@validstates = {}
|
158
146
|
|
@@ -177,24 +165,93 @@ class Type < Puppet::Element
|
|
177
165
|
|
178
166
|
end
|
179
167
|
|
180
|
-
#
|
181
|
-
def self.
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
168
|
+
# Define a new type.
|
169
|
+
def self.newtype(name, parent = nil, &block)
|
170
|
+
parent ||= Puppet::Type
|
171
|
+
Puppet::Util.symbolize(name)
|
172
|
+
|
173
|
+
|
174
|
+
# Create the class, with the correct name.
|
175
|
+
t = Class.new(parent) do
|
176
|
+
@name = name
|
177
|
+
end
|
178
|
+
const_set(name.to_s.capitalize,t)
|
179
|
+
|
180
|
+
# Initialize any necessary variables.
|
181
|
+
t.initvars
|
182
|
+
|
183
|
+
# Evaluate the passed block. This should usually define all of the work.
|
184
|
+
t.class_eval(&block)
|
185
|
+
|
186
|
+
# If they've got all the necessary methods defined and they haven't
|
187
|
+
# already added the state, then do so now.
|
188
|
+
if t.ensurable? and ! t.validstate?(:ensure)
|
189
|
+
t.ensurable
|
190
|
+
end
|
191
|
+
|
192
|
+
@types ||= {}
|
193
|
+
|
194
|
+
# And add it to our bucket.
|
195
|
+
@types[name] = t
|
196
|
+
end
|
197
|
+
|
198
|
+
# Create the 'ensure' class. This is a separate method so other types
|
199
|
+
# can easily call it and create their own 'ensure' values.
|
200
|
+
def self.ensurable(&block)
|
201
|
+
if block_given?
|
202
|
+
self.newstate(:ensure, Puppet::State::Ensure, &block)
|
203
|
+
else
|
204
|
+
self.newstate(:ensure, Puppet::State::Ensure) do
|
205
|
+
self.defaultvalues
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# Return a Type instance by name.
|
211
|
+
def self.type(name)
|
212
|
+
@types ||= {}
|
213
|
+
|
214
|
+
if name.is_a?(String)
|
215
|
+
name = name.intern
|
186
216
|
end
|
187
|
-
|
217
|
+
|
218
|
+
@types[name]
|
188
219
|
end
|
189
220
|
|
190
221
|
# class methods dealing with type instance management
|
191
222
|
|
192
223
|
public
|
193
224
|
|
225
|
+
# Create an alias. We keep these in a separate hash so that we don't encounter
|
226
|
+
# the objects multiple times when iterating over them.
|
227
|
+
def self.alias(name, obj)
|
228
|
+
if @objects.include?(name)
|
229
|
+
unless @objects[name] == obj
|
230
|
+
raise Puppet::Error.new(
|
231
|
+
"Cannot create alias %s: object already exists" %
|
232
|
+
[name]
|
233
|
+
)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
if @aliases.include?(name)
|
238
|
+
unless @aliases[name] == obj
|
239
|
+
raise Puppet::Error.new(
|
240
|
+
"Object %s already has alias %s" %
|
241
|
+
[@aliases[name].name, name]
|
242
|
+
)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
@aliases[name] = obj
|
247
|
+
end
|
248
|
+
|
194
249
|
# retrieve a named instance of the current type
|
195
250
|
def self.[](name)
|
196
251
|
if @objects.has_key?(name)
|
197
252
|
return @objects[name]
|
253
|
+
elsif @aliases.has_key?(name)
|
254
|
+
return @aliases[name]
|
198
255
|
else
|
199
256
|
return nil
|
200
257
|
end
|
@@ -209,16 +266,16 @@ class Type < Puppet::Element
|
|
209
266
|
raise Puppet::DevError, "must pass a Puppet::Type object"
|
210
267
|
end
|
211
268
|
|
212
|
-
if @objects.has_key?(
|
269
|
+
if @objects.has_key?(name) and self.isomorphic?
|
213
270
|
raise Puppet::Error.new(
|
214
271
|
"Object '%s' of type '%s' already exists with id '%s' vs. '%s'" %
|
215
|
-
[
|
216
|
-
@objects[
|
272
|
+
[name, newobj.class.name,
|
273
|
+
@objects[name].object_id,newobj.object_id]
|
217
274
|
)
|
218
275
|
else
|
219
|
-
#
|
220
|
-
# [
|
221
|
-
@objects[
|
276
|
+
#Puppet.info("adding %s of type %s to class list" %
|
277
|
+
# [name,object.class])
|
278
|
+
@objects[name] = newobj
|
222
279
|
end
|
223
280
|
|
224
281
|
# and then add it to the master list
|
@@ -229,9 +286,10 @@ class Type < Puppet::Element
|
|
229
286
|
def self.allclear
|
230
287
|
@@allobjects.clear
|
231
288
|
Puppet::Event::Subscription.clear
|
232
|
-
|
233
|
-
|
289
|
+
@types.each { |name, type|
|
290
|
+
type.clear
|
234
291
|
}
|
292
|
+
@finalized = false
|
235
293
|
end
|
236
294
|
|
237
295
|
# remove all of the instances of a single type
|
@@ -239,6 +297,9 @@ class Type < Puppet::Element
|
|
239
297
|
if defined? @objects
|
240
298
|
@objects.clear
|
241
299
|
end
|
300
|
+
if defined? @aliases
|
301
|
+
@aliases.clear
|
302
|
+
end
|
242
303
|
end
|
243
304
|
|
244
305
|
# remove a specified object
|
@@ -260,6 +321,32 @@ class Type < Puppet::Element
|
|
260
321
|
}
|
261
322
|
end
|
262
323
|
|
324
|
+
# Perform any operations that need to be done between instance creation
|
325
|
+
# and instance evaluation.
|
326
|
+
def self.finalize
|
327
|
+
finished = {}
|
328
|
+
self.eachtype do |type|
|
329
|
+
type.each do |object|
|
330
|
+
unless finished.has_key?(object)
|
331
|
+
object.finish
|
332
|
+
finished[object] = true
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
self.mkdepends
|
337
|
+
|
338
|
+
@finalized = true
|
339
|
+
end
|
340
|
+
|
341
|
+
# Has the finalize method been called yet?
|
342
|
+
def self.finalized?
|
343
|
+
if defined? @finalized
|
344
|
+
return @finalized
|
345
|
+
else
|
346
|
+
return false
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
263
350
|
# does the type have an object with the given name?
|
264
351
|
def self.has_key?(name)
|
265
352
|
return @objects.has_key?(name)
|
@@ -300,6 +387,7 @@ class Type < Puppet::Element
|
|
300
387
|
unless defined? @validstates
|
301
388
|
@validstates = Hash.new(false)
|
302
389
|
end
|
390
|
+
return unless defined? @states
|
303
391
|
@states.each { |stateklass|
|
304
392
|
name = stateklass.name
|
305
393
|
if @validstates.include?(name)
|
@@ -315,19 +403,187 @@ class Type < Puppet::Element
|
|
315
403
|
}
|
316
404
|
end
|
317
405
|
|
318
|
-
#
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
param
|
325
|
-
|
326
|
-
|
327
|
-
|
406
|
+
# Find the namevar
|
407
|
+
def self.namevar
|
408
|
+
unless defined? @namevar
|
409
|
+
return nil unless defined? @parameters and ! @parameters.empty?
|
410
|
+
@namevar = @parameters.find { |name, param|
|
411
|
+
param.isnamevar?
|
412
|
+
unless param
|
413
|
+
raise Puppet::DevError, "huh? %s" % name
|
414
|
+
end
|
415
|
+
}[0].value
|
416
|
+
end
|
417
|
+
@namevar
|
418
|
+
end
|
419
|
+
|
420
|
+
# Copy an existing class parameter. This allows other types to avoid
|
421
|
+
# duplicating a parameter definition, and is mostly used by subclasses
|
422
|
+
# of the File class.
|
423
|
+
def self.copyparam(klass, name)
|
424
|
+
param = klass.attrclass(name)
|
425
|
+
|
426
|
+
unless param
|
427
|
+
raise Puppet::DevError, "Class %s has no param %s" % [klass, name]
|
428
|
+
end
|
429
|
+
@parameters ||= []
|
430
|
+
@parameters << param
|
431
|
+
|
432
|
+
@paramhash ||= {}
|
433
|
+
@parameters.each { |p| @paramhash[name] = p }
|
434
|
+
|
435
|
+
if param.isnamevar?
|
436
|
+
@namevar = param.name
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
# Create a new metaparam. Requires a block and a name, stores it in the
|
441
|
+
# @parameters array, and does some basic checking on it.
|
442
|
+
def self.newmetaparam(name, &block)
|
443
|
+
Puppet::Util.symbolize(name)
|
444
|
+
param = Class.new(Puppet::Parameter) do
|
445
|
+
@name = name
|
446
|
+
end
|
447
|
+
param.ismetaparameter
|
448
|
+
param.class_eval(&block)
|
449
|
+
const_set("MetaParam" + name.to_s.capitalize,param)
|
450
|
+
@@metaparams ||= []
|
451
|
+
@@metaparams << param
|
452
|
+
|
453
|
+
@@metaparamhash ||= {}
|
454
|
+
@@metaparams.each { |p| @@metaparamhash[name] = p }
|
455
|
+
end
|
456
|
+
|
457
|
+
def self.eachmetaparam
|
458
|
+
@@metaparams.each { |p| yield p.name }
|
459
|
+
end
|
460
|
+
|
461
|
+
# Create a new parameter. Requires a block and a name, stores it in the
|
462
|
+
# @parameters array, and does some basic checking on it.
|
463
|
+
def self.newparam(name, &block)
|
464
|
+
Puppet::Util.symbolize(name)
|
465
|
+
param = Class.new(Puppet::Parameter) do
|
466
|
+
@name = name
|
467
|
+
end
|
468
|
+
param.element = self
|
469
|
+
param.class_eval(&block)
|
470
|
+
const_set("Parameter" + name.to_s.capitalize,param)
|
471
|
+
@parameters ||= []
|
472
|
+
@parameters << param
|
473
|
+
|
474
|
+
@paramhash ||= {}
|
475
|
+
@parameters.each { |p| @paramhash[name] = p }
|
476
|
+
|
477
|
+
# These might be enabled later.
|
478
|
+
# define_method(name) do
|
479
|
+
# @parameters[name].value
|
480
|
+
# end
|
481
|
+
#
|
482
|
+
# define_method(name.to_s + "=") do |value|
|
483
|
+
# newparam(param, value)
|
484
|
+
# end
|
485
|
+
|
486
|
+
if param.isnamevar?
|
487
|
+
@namevar = param.name
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
# Create a new state.
|
492
|
+
def self.newstate(name, parent = nil, &block)
|
493
|
+
parent ||= Puppet::State
|
494
|
+
if @validstates.include?(name)
|
495
|
+
raise Puppet::DevError, "Class %s already has a state named %s" %
|
496
|
+
[self.name, name]
|
497
|
+
end
|
498
|
+
s = Class.new(parent) do
|
499
|
+
@name = name
|
500
|
+
end
|
501
|
+
const_set("State" + name.to_s.capitalize,s)
|
502
|
+
s.class_eval(&block)
|
503
|
+
@states ||= []
|
504
|
+
|
505
|
+
# If it's the 'ensure' state, always put it first.
|
506
|
+
if name == :ensure
|
507
|
+
@states.unshift s
|
508
|
+
else
|
509
|
+
@states << s
|
510
|
+
end
|
511
|
+
@validstates[name] = s
|
512
|
+
|
513
|
+
# define_method(name) do
|
514
|
+
# @states[name].should
|
515
|
+
# end
|
516
|
+
#
|
517
|
+
# define_method(name.to_s + "=") do |value|
|
518
|
+
# newstate(name, :should => value)
|
519
|
+
# end
|
520
|
+
|
521
|
+
return s
|
522
|
+
end
|
523
|
+
|
524
|
+
# Specify a block for generating a list of objects to autorequire. This
|
525
|
+
# makes it so that you don't have to manually specify things that you clearly
|
526
|
+
# require.
|
527
|
+
def self.autorequire(name, &block)
|
528
|
+
@autorequires ||= {}
|
529
|
+
@autorequires[name] = block
|
530
|
+
end
|
531
|
+
|
532
|
+
# Yield each of those autorequires in turn, yo.
|
533
|
+
def self.eachautorequire
|
534
|
+
@autorequires ||= {}
|
535
|
+
@autorequires.each { |type, block|
|
536
|
+
yield(type, block)
|
328
537
|
}
|
329
538
|
end
|
330
539
|
|
540
|
+
# Return the parameter names
|
541
|
+
def self.parameters
|
542
|
+
return [] unless defined? @parameters
|
543
|
+
@parameters.collect { |klass| klass.name }
|
544
|
+
end
|
545
|
+
|
546
|
+
# Find the metaparameter class associated with a given metaparameter name.
|
547
|
+
def self.metaparamclass(name)
|
548
|
+
@@metaparamhash[name]
|
549
|
+
end
|
550
|
+
|
551
|
+
# Find the parameter class associated with a given parameter name.
|
552
|
+
def self.paramclass(name)
|
553
|
+
@paramhash[name]
|
554
|
+
end
|
555
|
+
|
556
|
+
# Find the class associated with any given attribute.
|
557
|
+
def self.attrclass(name)
|
558
|
+
@attrclasses ||= {}
|
559
|
+
|
560
|
+
# We cache the value, since this method gets called such a huge number
|
561
|
+
# of times (as in, hundreds of thousands in a given run).
|
562
|
+
unless @attrclasses.include?(name)
|
563
|
+
@attrclasses[name] = case self.attrtype(name)
|
564
|
+
when :state: @validstates[name]
|
565
|
+
when :meta: @@metaparamhash[name]
|
566
|
+
when :param: @paramhash[name]
|
567
|
+
end
|
568
|
+
end
|
569
|
+
@attrclasses[name]
|
570
|
+
end
|
571
|
+
|
572
|
+
def self.to_s
|
573
|
+
if defined? @name
|
574
|
+
"Puppet::Type::" + @name.to_s.capitalize
|
575
|
+
else
|
576
|
+
super
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
# Create a block to validate that our object is set up entirely. This will
|
581
|
+
# be run before the object is operated on.
|
582
|
+
def self.validate(&block)
|
583
|
+
define_method(:validate, &block)
|
584
|
+
#@validate = block
|
585
|
+
end
|
586
|
+
|
331
587
|
# does the name reflect a valid state?
|
332
588
|
def self.validstate?(name)
|
333
589
|
unless @validstates.length == @states.length
|
@@ -342,6 +598,7 @@ class Type < Puppet::Element
|
|
342
598
|
|
343
599
|
# Return the list of validstates
|
344
600
|
def self.validstates
|
601
|
+
return {} unless defined? @states
|
345
602
|
unless @validstates.length == @states.length
|
346
603
|
self.buildstatehash
|
347
604
|
end
|
@@ -362,14 +619,75 @@ class Type < Puppet::Element
|
|
362
619
|
unless defined? @parameters
|
363
620
|
raise Puppet::DevError, "Class %s has not defined parameters" % self
|
364
621
|
end
|
365
|
-
if @
|
622
|
+
if @paramhash.include?(name) or @@metaparamhash.include?(name)
|
366
623
|
return true
|
367
624
|
else
|
368
625
|
return false
|
369
626
|
end
|
370
627
|
end
|
371
628
|
|
372
|
-
|
629
|
+
# What type of parameter are we dealing with? Cache the results, because
|
630
|
+
# this method gets called so many times.
|
631
|
+
def self.attrtype(name)
|
632
|
+
@attrtypes ||= {}
|
633
|
+
unless @attrtypes.include?(name)
|
634
|
+
@attrtypes[name] = case
|
635
|
+
when @validstates.include?(name): :state
|
636
|
+
when @@metaparamhash.include?(name): :meta
|
637
|
+
when @paramhash.include?(name): :param
|
638
|
+
else
|
639
|
+
raise Puppet::DevError, "Invalid attribute '%s' for class '%s'" %
|
640
|
+
[name, self.name]
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
@attrtypes[name]
|
645
|
+
end
|
646
|
+
|
647
|
+
# All parameters, in the appropriate order. The namevar comes first,
|
648
|
+
# then the states, then the params and metaparams in the order they
|
649
|
+
# were specified in the files.
|
650
|
+
def self.allattrs
|
651
|
+
# now get all of the arguments, in a specific order
|
652
|
+
# Cache this, since it gets called so many times
|
653
|
+
namevar = self.namevar
|
654
|
+
|
655
|
+
order = [namevar]
|
656
|
+
order << [self.states.collect { |state| state.name },
|
657
|
+
self.parameters,
|
658
|
+
self.metaparams].flatten.reject { |param|
|
659
|
+
# we don't want our namevar in there multiple times
|
660
|
+
param == namevar
|
661
|
+
}
|
662
|
+
|
663
|
+
order.flatten!
|
664
|
+
|
665
|
+
return order
|
666
|
+
end
|
667
|
+
|
668
|
+
# A similar function but one that yields the name, type, and class.
|
669
|
+
# This is mainly so that setdefaults doesn't call quite so many functions.
|
670
|
+
def self.eachattr(*ary)
|
671
|
+
# now get all of the arguments, in a specific order
|
672
|
+
# Cache this, since it gets called so many times
|
673
|
+
|
674
|
+
if ary.empty?
|
675
|
+
ary = nil
|
676
|
+
end
|
677
|
+
self.states.each { |state|
|
678
|
+
yield(state, :state) if ary.nil? or ary.include?(state.name)
|
679
|
+
}
|
680
|
+
|
681
|
+
@parameters.each { |param|
|
682
|
+
yield(param, :param) if ary.nil? or ary.include?(param.name)
|
683
|
+
}
|
684
|
+
|
685
|
+
@@metaparams.each { |param|
|
686
|
+
yield(param, :meta) if ary.nil? or ary.include?(param.name)
|
687
|
+
}
|
688
|
+
end
|
689
|
+
|
690
|
+
def self.validattr?(name)
|
373
691
|
if name.is_a?(String)
|
374
692
|
name = name.intern
|
375
693
|
end
|
@@ -393,26 +711,35 @@ class Type < Puppet::Element
|
|
393
711
|
if name == :name
|
394
712
|
name = self.class.namevar
|
395
713
|
end
|
396
|
-
|
714
|
+
case self.class.attrtype(name)
|
715
|
+
when :state
|
397
716
|
if @states.include?(name)
|
398
717
|
return @states[name].is
|
399
718
|
else
|
400
719
|
return nil
|
401
720
|
end
|
402
|
-
|
721
|
+
when :meta
|
403
722
|
if @metaparams.include?(name)
|
404
|
-
return @metaparams[name]
|
723
|
+
return @metaparams[name].value
|
405
724
|
else
|
406
|
-
|
725
|
+
if default = self.class.metaparamclass(name).default
|
726
|
+
return default
|
727
|
+
else
|
728
|
+
return nil
|
729
|
+
end
|
407
730
|
end
|
408
|
-
|
731
|
+
when :param
|
409
732
|
if @parameters.include?(name)
|
410
|
-
return @parameters[name]
|
733
|
+
return @parameters[name].value
|
411
734
|
else
|
412
|
-
|
735
|
+
if default = self.class.paramclass(name).default
|
736
|
+
return default
|
737
|
+
else
|
738
|
+
return nil
|
739
|
+
end
|
413
740
|
end
|
414
741
|
else
|
415
|
-
raise TypeError.new("Invalid parameter %s" % [name])
|
742
|
+
raise TypeError.new("Invalid parameter %s(%s)" % [name, name.inspect])
|
416
743
|
end
|
417
744
|
end
|
418
745
|
|
@@ -430,11 +757,9 @@ class Type < Puppet::Element
|
|
430
757
|
if value.nil?
|
431
758
|
raise Puppet::Error.new("Got nil value for %s" % name)
|
432
759
|
end
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
self.send(("meta" + name.id2name + "="),value)
|
437
|
-
elsif stateklass = self.class.validstate?(name)
|
760
|
+
|
761
|
+
case self.class.attrtype(name)
|
762
|
+
when :state
|
438
763
|
if value.is_a?(Puppet::State)
|
439
764
|
self.debug "'%s' got handed a state for '%s'" % [self,name]
|
440
765
|
@states[name] = value
|
@@ -450,15 +775,11 @@ class Type < Puppet::Element
|
|
450
775
|
end
|
451
776
|
end
|
452
777
|
end
|
453
|
-
|
778
|
+
when :meta
|
779
|
+
self.newmetaparam(self.class.metaparamclass(name), value)
|
780
|
+
when :param
|
454
781
|
# if they've got a method to handle the parameter, then do it that way
|
455
|
-
|
456
|
-
if self.respond_to?(method)
|
457
|
-
self.send(method,value)
|
458
|
-
else
|
459
|
-
# else just set it
|
460
|
-
@parameters[name] = value
|
461
|
-
end
|
782
|
+
self.newparam(self.class.attrclass(name), value)
|
462
783
|
else
|
463
784
|
raise Puppet::Error, "Invalid parameter %s" % [name]
|
464
785
|
end
|
@@ -475,8 +796,12 @@ class Type < Puppet::Element
|
|
475
796
|
else
|
476
797
|
if @states.has_key?(attr)
|
477
798
|
@states.delete(attr)
|
799
|
+
elsif @parameters.has_key?(attr)
|
800
|
+
@parameters.delete(attr)
|
801
|
+
elsif @metaparams.has_key?(attr)
|
802
|
+
@metaparams.delete(attr)
|
478
803
|
else
|
479
|
-
raise Puppet::DevError.new("Undefined
|
804
|
+
raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}")
|
480
805
|
end
|
481
806
|
end
|
482
807
|
end
|
@@ -513,6 +838,32 @@ class Type < Puppet::Element
|
|
513
838
|
}
|
514
839
|
end
|
515
840
|
|
841
|
+
def devfail(msg)
|
842
|
+
self.fail(Puppet::DevError, msg)
|
843
|
+
end
|
844
|
+
|
845
|
+
# Throw an error, defaulting to a Puppet::Error
|
846
|
+
def fail(*args)
|
847
|
+
type = nil
|
848
|
+
if args[0].is_a?(Class)
|
849
|
+
type = args.shift
|
850
|
+
else
|
851
|
+
type = Puppet::Error
|
852
|
+
end
|
853
|
+
|
854
|
+
error = type.new(args.join(" "))
|
855
|
+
|
856
|
+
if defined? @line and @line
|
857
|
+
error.line = @line
|
858
|
+
end
|
859
|
+
|
860
|
+
if defined? @file and @file
|
861
|
+
error.file = @file
|
862
|
+
end
|
863
|
+
|
864
|
+
raise error
|
865
|
+
end
|
866
|
+
|
516
867
|
# retrieve the 'is' value for a specified state
|
517
868
|
def is(state)
|
518
869
|
if @states.include?(state)
|
@@ -534,7 +885,7 @@ class Type < Puppet::Element
|
|
534
885
|
# create a log at specified level
|
535
886
|
def log(msg)
|
536
887
|
Puppet::Log.create(
|
537
|
-
:level => @metaparams[:loglevel],
|
888
|
+
:level => @metaparams[:loglevel].value,
|
538
889
|
:message => msg,
|
539
890
|
:source => self
|
540
891
|
)
|
@@ -558,10 +909,52 @@ class Type < Puppet::Element
|
|
558
909
|
end
|
559
910
|
end
|
560
911
|
|
912
|
+
# Create a new parameter.
|
913
|
+
def newparam(klass, value = nil)
|
914
|
+
newattr(:param, klass, value)
|
915
|
+
end
|
916
|
+
|
917
|
+
# Create a new parameter or metaparameter. We'll leave the calling
|
918
|
+
# method to store it appropriately.
|
919
|
+
def newmetaparam(klass, value = nil)
|
920
|
+
newattr(:meta, klass, value)
|
921
|
+
end
|
922
|
+
|
923
|
+
# The base function that the others wrap.
|
924
|
+
def newattr(type, klass, value = nil)
|
925
|
+
# This should probably be a bit, um, different, but...
|
926
|
+
if type == :state
|
927
|
+
return newstate(klass)
|
928
|
+
end
|
929
|
+
param = klass.new
|
930
|
+
param.parent = self
|
931
|
+
if value
|
932
|
+
param.value = value
|
933
|
+
end
|
934
|
+
|
935
|
+
case type
|
936
|
+
when :meta
|
937
|
+
@metaparams[klass.name] = param
|
938
|
+
when :param
|
939
|
+
@parameters[klass.name] = param
|
940
|
+
else
|
941
|
+
self.devfail("Invalid param type %s" % type)
|
942
|
+
end
|
943
|
+
|
944
|
+
return param
|
945
|
+
end
|
946
|
+
|
561
947
|
# create a new state
|
562
948
|
def newstate(name, hash = {})
|
563
|
-
|
564
|
-
|
949
|
+
stateklass = nil
|
950
|
+
if name.is_a?(Class)
|
951
|
+
stateklass = name
|
952
|
+
name = stateklass.name
|
953
|
+
else
|
954
|
+
stateklass = self.class.validstate?(name)
|
955
|
+
unless stateklass
|
956
|
+
self.fail("Invalid state %s" % name)
|
957
|
+
end
|
565
958
|
end
|
566
959
|
if @states.include?(name)
|
567
960
|
hash.each { |var,value|
|
@@ -575,7 +968,7 @@ class Type < Puppet::Element
|
|
575
968
|
# make sure the state doesn't have any errors
|
576
969
|
newstate = stateklass.new(hash)
|
577
970
|
@states[name] = newstate
|
578
|
-
return
|
971
|
+
return newstate
|
579
972
|
rescue Puppet::Error => detail
|
580
973
|
# the state failed, so just ignore it
|
581
974
|
self.warning "State %s failed: %s" %
|
@@ -600,7 +993,7 @@ class Type < Puppet::Element
|
|
600
993
|
unless name.is_a? Symbol
|
601
994
|
name = name.intern
|
602
995
|
end
|
603
|
-
return @parameters[name]
|
996
|
+
return @parameters[name].value
|
604
997
|
end
|
605
998
|
|
606
999
|
def push(*childs)
|
@@ -615,23 +1008,35 @@ class Type < Puppet::Element
|
|
615
1008
|
|
616
1009
|
# Remove an object. The argument determines whether the object's
|
617
1010
|
# subscriptions get eliminated, too.
|
618
|
-
def remove(rmdeps)
|
1011
|
+
def remove(rmdeps = true)
|
619
1012
|
@children.each { |child|
|
620
|
-
child.remove
|
1013
|
+
child.remove(rmdeps)
|
621
1014
|
}
|
622
|
-
self.class.delete(self)
|
623
1015
|
|
624
1016
|
if rmdeps
|
625
1017
|
Puppet::Event::Subscription.dependencies(self).each { |dep|
|
626
|
-
|
1018
|
+
begin
|
1019
|
+
self.unsubscribe(dep)
|
1020
|
+
rescue
|
1021
|
+
# ignore failed unsubscribes
|
1022
|
+
end
|
627
1023
|
}
|
628
1024
|
end
|
1025
|
+
self.class.delete(self)
|
629
1026
|
|
630
1027
|
if defined? @parent and @parent
|
631
1028
|
@parent.delete(self)
|
632
1029
|
end
|
633
1030
|
end
|
634
1031
|
|
1032
|
+
# Is the named state defined?
|
1033
|
+
def statedefined?(name)
|
1034
|
+
unless name.is_a? Symbol
|
1035
|
+
name = name.intern
|
1036
|
+
end
|
1037
|
+
return @states.include?(name)
|
1038
|
+
end
|
1039
|
+
|
635
1040
|
# return an actual type by name; to return the value, use 'inst[name]'
|
636
1041
|
# FIXME this method should go away
|
637
1042
|
def state(name)
|
@@ -652,8 +1057,9 @@ class Type < Puppet::Element
|
|
652
1057
|
end
|
653
1058
|
}
|
654
1059
|
unless tmpstates.length == @states.length
|
655
|
-
|
1060
|
+
self.devfail(
|
656
1061
|
"Something went very wrong with tmpstates creation"
|
1062
|
+
)
|
657
1063
|
end
|
658
1064
|
return tmpstates
|
659
1065
|
end
|
@@ -697,7 +1103,7 @@ class Type < Puppet::Element
|
|
697
1103
|
else
|
698
1104
|
# We will probably want to support merging of some kind in
|
699
1105
|
# the future, but for now, just throw an error.
|
700
|
-
raise Puppet::Error, "%s %s is already being managed" %
|
1106
|
+
raise Puppet::Error, "%s '%s' is already being managed" %
|
701
1107
|
[self.name, name]
|
702
1108
|
#retobj.merge(hash)
|
703
1109
|
|
@@ -711,9 +1117,7 @@ class Type < Puppet::Element
|
|
711
1117
|
obj = new(hash)
|
712
1118
|
rescue => detail
|
713
1119
|
if Puppet[:debug]
|
714
|
-
|
715
|
-
puts detail.stack
|
716
|
-
end
|
1120
|
+
puts detail.backtrace
|
717
1121
|
end
|
718
1122
|
Puppet.err "Could not create %s: %s" % [name, detail.to_s]
|
719
1123
|
if obj
|
@@ -757,8 +1161,7 @@ class Type < Puppet::Element
|
|
757
1161
|
private :new
|
758
1162
|
end
|
759
1163
|
|
760
|
-
|
761
|
-
def initialize(hash)
|
1164
|
+
def initvars
|
762
1165
|
@children = []
|
763
1166
|
@evalcount = 0
|
764
1167
|
|
@@ -782,72 +1185,245 @@ class Type < Puppet::Element
|
|
782
1185
|
unless defined? @metaparams
|
783
1186
|
@metaparams = Hash.new(false)
|
784
1187
|
end
|
785
|
-
|
786
|
-
#unless defined? @paramdoc
|
787
|
-
# @paramdoc = Hash.new { |hash,key|
|
788
|
-
# if key.is_a?(String)
|
789
|
-
# key = key.intern
|
790
|
-
# end
|
791
|
-
# if hash.include?(key)
|
792
|
-
# hash[key]
|
793
|
-
# else
|
794
|
-
# "Param Documentation for %s not found" % key
|
795
|
-
# end
|
796
|
-
# }
|
797
|
-
#end
|
798
1188
|
|
799
1189
|
# set defalts
|
800
1190
|
@noop = false
|
801
|
-
@metaparams[:loglevel] = :notice
|
802
1191
|
# keeping stats for the total number of changes, and how many were
|
803
1192
|
# completely sync'ed
|
804
|
-
# this isn't really sufficient either, because it adds lots of special
|
805
|
-
# such as failed changes
|
1193
|
+
# this isn't really sufficient either, because it adds lots of special
|
1194
|
+
# cases such as failed changes
|
806
1195
|
# it also doesn't distinguish between changes from the current transaction
|
807
1196
|
# vs. changes over the process lifetime
|
808
1197
|
@totalchanges = 0
|
809
1198
|
@syncedchanges = 0
|
810
1199
|
@failedchanges = 0
|
811
1200
|
|
1201
|
+
@inited = true
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
# initialize the type instance
|
1205
|
+
def initialize(hash)
|
1206
|
+
unless defined? @inited
|
1207
|
+
self.initvars
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
# If we got passed a transportable object, we just pull a bunch of info
|
1211
|
+
# directly from it.
|
1212
|
+
if hash.is_a?(Puppet::TransObject)
|
1213
|
+
#self[:name] = hash[:name]
|
1214
|
+
[:file, :line, :tags].each { |getter|
|
1215
|
+
if hash.respond_to?(getter)
|
1216
|
+
setter = getter.to_s + "="
|
1217
|
+
if val = hash.send(getter)
|
1218
|
+
self.send(setter, val)
|
1219
|
+
end
|
1220
|
+
end
|
1221
|
+
}
|
1222
|
+
hash = hash.to_hash
|
1223
|
+
end
|
1224
|
+
|
812
1225
|
# Before anything else, set our parent if it was included
|
813
1226
|
if hash.include?(:parent)
|
814
1227
|
@parent = hash[:parent]
|
815
1228
|
hash.delete(:parent)
|
816
1229
|
end
|
817
1230
|
|
1231
|
+
# Convert all args to symbols
|
818
1232
|
hash = self.argclean(hash)
|
819
1233
|
|
820
|
-
#
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
1234
|
+
# Let's do the name first, because some things need to happen once
|
1235
|
+
# we have the name but before anything else
|
1236
|
+
|
1237
|
+
attrs = self.class.allattrs
|
1238
|
+
namevar = self.class.namevar
|
1239
|
+
|
1240
|
+
if hash.include?(namevar)
|
1241
|
+
#self.send(namevar.to_s + "=", hash[namevar])
|
1242
|
+
self[namevar] = hash[namevar]
|
1243
|
+
hash.delete(namevar)
|
1244
|
+
if attrs.include?(namevar)
|
1245
|
+
attrs.delete(namevar)
|
1246
|
+
else
|
1247
|
+
self.devfail "My namevar isn't a valid attribute...?"
|
1248
|
+
end
|
1249
|
+
else
|
1250
|
+
self.devfail "I was not passed a namevar"
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
# The information to cache to disk. We have to do this after
|
1254
|
+
# the name is set because it uses the name and/or path, but before
|
1255
|
+
# everything else is set because the states need to be able to
|
1256
|
+
# retrieve their stored info.
|
1257
|
+
#@cache = Puppet::Storage.cache(self)
|
1258
|
+
|
1259
|
+
# This is all of our attributes except the namevar.
|
1260
|
+
attrs.each { |name|
|
830
1261
|
if hash.include?(name)
|
831
1262
|
begin
|
832
1263
|
self[name] = hash[name]
|
833
1264
|
rescue => detail
|
834
|
-
|
835
|
-
"Could not set %s on %s: %s" %
|
1265
|
+
self.devfail(
|
1266
|
+
"Could not set %s on %s: %s" %
|
1267
|
+
[name, self.class.name, detail]
|
836
1268
|
)
|
837
1269
|
end
|
838
1270
|
hash.delete name
|
839
1271
|
end
|
840
1272
|
}
|
841
1273
|
|
1274
|
+
# While this could theoretically be set after all of the objects are
|
1275
|
+
# created, it seems to make more sense to set them immediately.
|
1276
|
+
self.setdefaults
|
1277
|
+
|
842
1278
|
if hash.length > 0
|
843
1279
|
self.debug hash.inspect
|
844
|
-
|
1280
|
+
self.fail("Class %s does not accept argument(s) %s" %
|
845
1281
|
[self.class.name, hash.keys.join(" ")])
|
846
1282
|
end
|
847
1283
|
|
848
1284
|
# add this object to the specific class's list of objects
|
849
1285
|
#puts caller
|
850
1286
|
self.class[self.name] = self
|
1287
|
+
|
1288
|
+
if self.respond_to?(:validate)
|
1289
|
+
self.validate
|
1290
|
+
end
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
# Figure out of there are any objects we can automatically add as
|
1294
|
+
# dependencies.
|
1295
|
+
def autorequire
|
1296
|
+
self.class.eachautorequire { |type, block|
|
1297
|
+
# Ignore any types we can't find, although that would be a bit odd.
|
1298
|
+
next unless typeobj = Puppet.type(type)
|
1299
|
+
|
1300
|
+
# Retrieve the list of names from the block.
|
1301
|
+
next unless list = self.instance_eval(&block)
|
1302
|
+
unless list.is_a?(Array)
|
1303
|
+
list = [list]
|
1304
|
+
end
|
1305
|
+
|
1306
|
+
# Collect the current prereqs
|
1307
|
+
list.each { |dep|
|
1308
|
+
# Skip autorequires that we aren't managing
|
1309
|
+
next unless obj = typeobj[dep]
|
1310
|
+
|
1311
|
+
# Skip autorequires that we already require
|
1312
|
+
next if self.requires?(obj)
|
1313
|
+
self.info "Auto-requiring %s" % obj.name
|
1314
|
+
|
1315
|
+
self[:require] = [type, dep]
|
1316
|
+
}
|
1317
|
+
|
1318
|
+
#self.info reqs.inspect
|
1319
|
+
#self[:require] = reqs
|
1320
|
+
}
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
# Set up all of our autorequires.
|
1324
|
+
def finish
|
1325
|
+
self.autorequire
|
1326
|
+
|
1327
|
+
# Scheduling has to be done when the whole config is instantiated, so
|
1328
|
+
# that file order doesn't matter in finding them.
|
1329
|
+
self.schedule
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
# Return a cached value
|
1333
|
+
def cached(name)
|
1334
|
+
Puppet::Storage.cache(self)[name]
|
1335
|
+
#@cache[name] ||= nil
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
# Cache a value
|
1339
|
+
def cache(name, value)
|
1340
|
+
Puppet::Storage.cache(self)[name] = value
|
1341
|
+
#@cache[name] = value
|
1342
|
+
end
|
1343
|
+
|
1344
|
+
# Look up the schedule and set it appropriately. This is done after
|
1345
|
+
# the instantiation phase, so that the schedule can be anywhere in the
|
1346
|
+
# file.
|
1347
|
+
def schedule
|
1348
|
+
|
1349
|
+
# If we've already set the schedule, then just move on
|
1350
|
+
return if self[:schedule].is_a?(Puppet.type(:schedule))
|
1351
|
+
|
1352
|
+
return unless self[:schedule]
|
1353
|
+
|
1354
|
+
# Schedules don't need to be scheduled
|
1355
|
+
#return if self.is_a?(Puppet.type(:schedule))
|
1356
|
+
|
1357
|
+
# Nor do components
|
1358
|
+
#return if self.is_a?(Puppet.type(:component))
|
1359
|
+
|
1360
|
+
if sched = Puppet.type(:schedule)[self[:schedule]]
|
1361
|
+
self[:schedule] = sched
|
1362
|
+
else
|
1363
|
+
self.fail "Could not find schedule %s" % self[:schedule]
|
1364
|
+
end
|
1365
|
+
# if self[:schedule]
|
1366
|
+
# elsif Puppet[:schedule] and ! Puppet[:ignoreschedules]
|
1367
|
+
# # We handle schedule defaults here mostly because otherwise things
|
1368
|
+
# # will behave very very erratically during testing.
|
1369
|
+
# if sched = Puppet.type(:schedule)[Puppet[:schedule]]
|
1370
|
+
# self[:schedule] = sched
|
1371
|
+
# else
|
1372
|
+
# self.fail "Could not find default schedule %s" % Puppet[:schedule]
|
1373
|
+
# end
|
1374
|
+
# else
|
1375
|
+
# # While it's unlikely we won't have any schedule (since there's a
|
1376
|
+
# # default), it's at least possible during testing
|
1377
|
+
# return true
|
1378
|
+
# end
|
1379
|
+
end
|
1380
|
+
|
1381
|
+
# Check whether we are scheduled to run right now or not.
|
1382
|
+
def scheduled?
|
1383
|
+
return true if Puppet[:ignoreschedules]
|
1384
|
+
return true unless schedule = self[:schedule]
|
1385
|
+
|
1386
|
+
# We use 'checked' here instead of 'synced' because otherwise we'll
|
1387
|
+
# end up checking most elements most times, because they will generally
|
1388
|
+
# have been synced a long time ago (e.g., a file only gets updated
|
1389
|
+
# once a month on the server and its schedule is daily; the last sync time
|
1390
|
+
# will have been a month ago, so we'd end up checking every run).
|
1391
|
+
return schedule.match?(self.cached(:checked).to_i)
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
# Is the specified parameter set?
|
1395
|
+
def attrset?(type, attr)
|
1396
|
+
case type
|
1397
|
+
when :state: return @states.include?(attr)
|
1398
|
+
when :param: return @parameters.include?(attr)
|
1399
|
+
when :meta: return @metaparams.include?(attr)
|
1400
|
+
else
|
1401
|
+
self.devfail "Invalid set type %s" % [type]
|
1402
|
+
end
|
1403
|
+
end
|
1404
|
+
|
1405
|
+
# def set(name, value)
|
1406
|
+
# send(name.to_s + "=", value)
|
1407
|
+
# end
|
1408
|
+
#
|
1409
|
+
# def get(name)
|
1410
|
+
# send(name)
|
1411
|
+
# end
|
1412
|
+
|
1413
|
+
# For any parameters or states that have defaults and have not yet been
|
1414
|
+
# set, set them now.
|
1415
|
+
def setdefaults(*ary)
|
1416
|
+
self.class.eachattr(*ary) { |klass, type|
|
1417
|
+
# not many attributes will have defaults defined, so we short-circuit
|
1418
|
+
# those away
|
1419
|
+
next unless klass.method_defined?(:default)
|
1420
|
+
next if self.attrset?(type, klass.name)
|
1421
|
+
|
1422
|
+
obj = self.newattr(type, klass)
|
1423
|
+
#self.debug "defaulting %s to %s" % [obj.name, obj.default]
|
1424
|
+
obj.value = obj.default
|
1425
|
+
}
|
1426
|
+
|
851
1427
|
end
|
852
1428
|
|
853
1429
|
# Merge new information with an existing object, checking for conflicts
|
@@ -880,10 +1456,10 @@ class Type < Puppet::Element
|
|
880
1456
|
# take the intersection
|
881
1457
|
newvals = oldvals & value
|
882
1458
|
if newvals.empty?
|
883
|
-
|
1459
|
+
self.fail "No common values for %s on %s(%s)" %
|
884
1460
|
[param, self.class.name, self.name]
|
885
1461
|
elsif newvals.length > 1
|
886
|
-
|
1462
|
+
self.fail "Too many values for %s on %s(%s)" %
|
887
1463
|
[param, self.class.name, self.name]
|
888
1464
|
else
|
889
1465
|
self.debug "Reduced old values %s and new values %s to %s" %
|
@@ -903,18 +1479,18 @@ class Type < Puppet::Element
|
|
903
1479
|
unless defined? @name and @name
|
904
1480
|
namevar = self.class.namevar
|
905
1481
|
if self.class.validparameter?(namevar)
|
906
|
-
@name =
|
1482
|
+
@name = self[:name]
|
907
1483
|
elsif self.class.validstate?(namevar)
|
908
1484
|
@name = self.should(namevar)
|
909
1485
|
else
|
910
|
-
|
1486
|
+
self.devfail "Could not find namevar %s for %s" %
|
911
1487
|
[namevar, self.class.name]
|
912
1488
|
end
|
913
1489
|
end
|
914
1490
|
|
915
1491
|
unless @name
|
916
|
-
|
917
|
-
[namevar, self.class.name]
|
1492
|
+
self.devfail "Could not find namevar '%s' for %s" %
|
1493
|
+
[self.class.namevar, self.class.name]
|
918
1494
|
end
|
919
1495
|
|
920
1496
|
return @name
|
@@ -922,9 +1498,11 @@ class Type < Puppet::Element
|
|
922
1498
|
|
923
1499
|
# fix any namevar => param translations
|
924
1500
|
def argclean(hash)
|
925
|
-
#
|
926
|
-
# because it might be used in creating the other states
|
927
|
-
hash
|
1501
|
+
# We have to set the name of our object before anything else,
|
1502
|
+
# because it might be used in creating the other states. We dup and
|
1503
|
+
# then convert to a hash here because TransObjects behave strangely
|
1504
|
+
# here.
|
1505
|
+
hash = hash.dup.to_hash
|
928
1506
|
|
929
1507
|
if hash.include?(:parent)
|
930
1508
|
hash.delete(:parent)
|
@@ -960,28 +1538,11 @@ class Type < Puppet::Element
|
|
960
1538
|
def retrieve
|
961
1539
|
# it's important to use the method here, as it follows the order
|
962
1540
|
# in which they're defined in the object
|
963
|
-
states.each { |state|
|
1541
|
+
states().each { |state|
|
964
1542
|
state.retrieve
|
965
1543
|
}
|
966
1544
|
end
|
967
1545
|
|
968
|
-
# sync the changes to disk, and return the events generated by the changes
|
969
|
-
# FIXME this method is essentially obviated, but it's still used by tests
|
970
|
-
# and i don't feel like fixing it yet
|
971
|
-
def sync
|
972
|
-
#raise Puppet::DevError, "Type#sync called"
|
973
|
-
events = self.collect { |child|
|
974
|
-
child.sync
|
975
|
-
}.reject { |event|
|
976
|
-
! (event.is_a?(Symbol) or event.is_a?(String))
|
977
|
-
}.flatten
|
978
|
-
|
979
|
-
#Puppet.notice "got events %s" % events.inspect
|
980
|
-
|
981
|
-
Puppet::Metric.addevents(self.class,self,events)
|
982
|
-
return events
|
983
|
-
end
|
984
|
-
|
985
1546
|
# convert to a string
|
986
1547
|
def to_s
|
987
1548
|
self.name
|
@@ -1001,12 +1562,42 @@ class Type < Puppet::Element
|
|
1001
1562
|
end
|
1002
1563
|
end
|
1003
1564
|
|
1565
|
+
# Retrieve the changes associated with all of the states.
|
1566
|
+
def statechanges
|
1567
|
+
# If we are changing the existence of the object, then none of
|
1568
|
+
# the other states matter.
|
1569
|
+
if @states.include?(:ensure) and ! @states[:ensure].insync?
|
1570
|
+
#self.info "ensuring %s from %s" %
|
1571
|
+
# [@states[:ensure].should, @states[:ensure].is]
|
1572
|
+
return [Puppet::StateChange.new(@states[:ensure])]
|
1573
|
+
# Else, if the 'ensure' state is correctly absent, then do
|
1574
|
+
# nothing
|
1575
|
+
elsif @states.include?(:ensure) and @states[:ensure].is == :absent
|
1576
|
+
#self.info "Object is correctly absent"
|
1577
|
+
return []
|
1578
|
+
else
|
1579
|
+
#if @states.include?(:ensure)
|
1580
|
+
# self.info "ensure: Is: %s, Should: %s" %
|
1581
|
+
# [@states[:ensure].is, @states[:ensure].should]
|
1582
|
+
#else
|
1583
|
+
# self.info "no ensure state"
|
1584
|
+
#end
|
1585
|
+
return states().find_all { |state|
|
1586
|
+
! state.insync?
|
1587
|
+
}.collect { |state|
|
1588
|
+
Puppet::StateChange.new(state)
|
1589
|
+
}
|
1590
|
+
end
|
1591
|
+
end
|
1592
|
+
|
1004
1593
|
# this method is responsible for collecting state changes
|
1005
1594
|
# we always descend into the children before we evaluate our current
|
1006
1595
|
# states
|
1007
1596
|
# this returns any changes resulting from testing, thus 'collect'
|
1008
1597
|
# rather than 'each'
|
1009
1598
|
def evaluate
|
1599
|
+
now = Time.now
|
1600
|
+
|
1010
1601
|
#Puppet.err "Evaluating %s" % self.path.join(":")
|
1011
1602
|
unless defined? @evalcount
|
1012
1603
|
self.err "No evalcount defined on '%s' of type '%s'" %
|
@@ -1040,11 +1631,7 @@ class Type < Puppet::Element
|
|
1040
1631
|
|
1041
1632
|
# states() is a private method, returning an ordered list
|
1042
1633
|
unless self.class.depthfirst?
|
1043
|
-
changes
|
1044
|
-
! state.insync?
|
1045
|
-
}.collect { |state|
|
1046
|
-
Puppet::StateChange.new(state)
|
1047
|
-
}
|
1634
|
+
changes += statechanges()
|
1048
1635
|
end
|
1049
1636
|
|
1050
1637
|
if changes.length > 0
|
@@ -1054,7 +1641,9 @@ class Type < Puppet::Element
|
|
1054
1641
|
#end
|
1055
1642
|
|
1056
1643
|
changes << @children.collect { |child|
|
1057
|
-
child.evaluate
|
1644
|
+
ch = child.evaluate
|
1645
|
+
child.cache(:checked, now)
|
1646
|
+
ch
|
1058
1647
|
}
|
1059
1648
|
#unless self.class.depthfirst?
|
1060
1649
|
# changes << self.collect { |child|
|
@@ -1068,11 +1657,7 @@ class Type < Puppet::Element
|
|
1068
1657
|
#}
|
1069
1658
|
|
1070
1659
|
if self.class.depthfirst?
|
1071
|
-
changes
|
1072
|
-
! state.insync?
|
1073
|
-
}.collect { |state|
|
1074
|
-
Puppet::StateChange.new(state)
|
1075
|
-
}
|
1660
|
+
changes += statechanges()
|
1076
1661
|
end
|
1077
1662
|
|
1078
1663
|
changes.flatten!
|
@@ -1086,6 +1671,7 @@ class Type < Puppet::Element
|
|
1086
1671
|
# self.debug "change: %s" % change.state.name
|
1087
1672
|
#}
|
1088
1673
|
end
|
1674
|
+
self.cache(:checked, now)
|
1089
1675
|
return changes.flatten
|
1090
1676
|
end
|
1091
1677
|
|
@@ -1095,10 +1681,16 @@ class Type < Puppet::Element
|
|
1095
1681
|
def insync?
|
1096
1682
|
insync = true
|
1097
1683
|
|
1684
|
+
if state = @states[:ensure]
|
1685
|
+
if state.insync? and state.should == :absent
|
1686
|
+
return true
|
1687
|
+
end
|
1688
|
+
end
|
1689
|
+
|
1098
1690
|
states.each { |state|
|
1099
1691
|
unless state.insync?
|
1100
1692
|
self.debug("%s is not in sync: %s vs %s" %
|
1101
|
-
[state, state.is, state.should])
|
1693
|
+
[state, state.is.inspect, state.should.inspect])
|
1102
1694
|
insync = false
|
1103
1695
|
end
|
1104
1696
|
}
|
@@ -1110,95 +1702,57 @@ class Type < Puppet::Element
|
|
1110
1702
|
# Meta-parameter methods: These methods deal with the results
|
1111
1703
|
# of specifying metaparameters
|
1112
1704
|
|
1113
|
-
def self.
|
1114
|
-
@@metaparams.
|
1115
|
-
yield param
|
1116
|
-
}
|
1117
|
-
end
|
1118
|
-
|
1119
|
-
# This just marks states that we definitely want to retrieve values
|
1120
|
-
# on. There is currently no way to uncheck a parameter.
|
1121
|
-
def metacheck=(args)
|
1122
|
-
unless args.is_a?(Array)
|
1123
|
-
args = [args]
|
1124
|
-
end
|
1125
|
-
|
1126
|
-
# these are states that we might not have 'should'
|
1127
|
-
# values for but we want to retrieve 'is' values for anyway
|
1128
|
-
args.each { |state|
|
1129
|
-
unless state.is_a?(Symbol)
|
1130
|
-
state = state.intern
|
1131
|
-
end
|
1132
|
-
next if @states.include?(state)
|
1133
|
-
|
1134
|
-
stateklass = nil
|
1135
|
-
self.newstate(state)
|
1136
|
-
}
|
1705
|
+
def self.metaparams
|
1706
|
+
@@metaparams.collect { |param| param.name }
|
1137
1707
|
end
|
1138
1708
|
|
1139
1709
|
# Is the parameter in question a meta-parameter?
|
1140
1710
|
def self.metaparam?(param)
|
1141
|
-
@@
|
1711
|
+
@@metaparamhash.include?(param)
|
1142
1712
|
end
|
1143
1713
|
|
1144
|
-
#
|
1145
|
-
# generates
|
1146
|
-
# we might reduce the level of subscription eventually, but for now...
|
1147
|
-
def metarequire=(requires)
|
1148
|
-
self.handledepends(requires, :NONE, nil)
|
1149
|
-
end
|
1150
|
-
|
1151
|
-
# for each object we require, subscribe to all events that it
|
1152
|
-
# generates
|
1153
|
-
# we might reduce the level of subscription eventually, but for now...
|
1154
|
-
def metasubscribe=(requires)
|
1155
|
-
self.handledepends(requires, :ALL_EVENTS, :refresh)
|
1156
|
-
end
|
1714
|
+
# Subscription and relationship methods
|
1157
1715
|
|
1158
|
-
def
|
1159
|
-
|
1160
|
-
|
1161
|
-
elsif noop == "false" or noop == false
|
1162
|
-
@noop = false
|
1163
|
-
else
|
1164
|
-
raise Puppet::Error.new("Invalid noop value '%s'" % noop)
|
1165
|
-
end
|
1166
|
-
end
|
1716
|
+
#def addcallback(object, event, method)
|
1717
|
+
# @callbacks[object][event] = method
|
1718
|
+
#end
|
1167
1719
|
|
1168
|
-
#
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1720
|
+
# Build all of the dependencies for all of the different types. This is called
|
1721
|
+
# after all of the objects are instantiated, so that we don't depend on
|
1722
|
+
# file order. If we didn't use this (and instead just checked dependencies
|
1723
|
+
# as we came across them), any required object would have to come before the
|
1724
|
+
# requiring object in the file(s).
|
1725
|
+
def self.mkdepends
|
1726
|
+
@types.each { |name, type|
|
1727
|
+
type.each { |obj|
|
1728
|
+
obj.builddepends
|
1729
|
+
}
|
1730
|
+
}
|
1172
1731
|
end
|
1173
1732
|
|
1174
|
-
#
|
1175
|
-
|
1176
|
-
|
1733
|
+
# The per-type version of dependency building. This actually goes through
|
1734
|
+
# all of the objects themselves and builds deps.
|
1735
|
+
def self.builddepends
|
1736
|
+
return unless defined? @objects
|
1737
|
+
@objects.each { |name, obj|
|
1738
|
+
obj.builddepends
|
1739
|
+
}
|
1177
1740
|
end
|
1178
1741
|
|
1179
|
-
#
|
1180
|
-
def
|
1181
|
-
|
1182
|
-
|
1742
|
+
# Build the dependencies associated with an individual object.
|
1743
|
+
def builddepends
|
1744
|
+
# Handle the requires
|
1745
|
+
if self[:require]
|
1746
|
+
self.handledepends(self[:require], :NONE, nil)
|
1183
1747
|
end
|
1184
|
-
if loglevel == :verbose
|
1185
|
-
loglevel = :info
|
1186
|
-
end
|
1187
1748
|
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
raise Puppet::Error.new("Invalid loglevel '%s'" % loglevel)
|
1749
|
+
# And the subscriptions
|
1750
|
+
if self[:subscribe]
|
1751
|
+
self.handledepends(self[:subscribe], :ALL_EVENTS, :refresh)
|
1192
1752
|
end
|
1193
1753
|
end
|
1194
1754
|
|
1195
|
-
#
|
1196
|
-
|
1197
|
-
#def addcallback(object, event, method)
|
1198
|
-
# @callbacks[object][event] = method
|
1199
|
-
#end
|
1200
|
-
|
1201
|
-
# return all objects subscribed to the current object
|
1755
|
+
# return all objects that we depend on
|
1202
1756
|
def eachdependency
|
1203
1757
|
Puppet::Event::Subscription.dependencies(self).each { |dep|
|
1204
1758
|
yield dep.source
|
@@ -1225,11 +1779,11 @@ class Type < Puppet::Element
|
|
1225
1779
|
object = nil
|
1226
1780
|
tname = rname[0]
|
1227
1781
|
unless type = Puppet::Type.type(tname)
|
1228
|
-
|
1782
|
+
self.fail "Could not find type %s" % tname.inspect
|
1229
1783
|
end
|
1230
1784
|
name = rname[1]
|
1231
1785
|
unless object = type[name]
|
1232
|
-
|
1786
|
+
self.fail "Could not retrieve object '%s' of type '%s'" %
|
1233
1787
|
[name,type]
|
1234
1788
|
end
|
1235
1789
|
self.debug("subscribes to %s" % [object])
|
@@ -1253,10 +1807,6 @@ class Type < Puppet::Element
|
|
1253
1807
|
subargs[:callback] = method
|
1254
1808
|
end
|
1255
1809
|
Puppet::Event::Subscription.new(subargs)
|
1256
|
-
#if self.respond_to?(method)
|
1257
|
-
# self.addcallback(object, event, method)
|
1258
|
-
#end
|
1259
|
-
#object.addnotify(self)
|
1260
1810
|
}
|
1261
1811
|
end
|
1262
1812
|
|
@@ -1270,6 +1820,18 @@ class Type < Puppet::Element
|
|
1270
1820
|
end
|
1271
1821
|
end
|
1272
1822
|
|
1823
|
+
def requires?(object)
|
1824
|
+
req = false
|
1825
|
+
self.eachdependency { |dep|
|
1826
|
+
if dep == object
|
1827
|
+
req = true
|
1828
|
+
break
|
1829
|
+
end
|
1830
|
+
}
|
1831
|
+
|
1832
|
+
return req
|
1833
|
+
end
|
1834
|
+
|
1273
1835
|
def subscribe(hash)
|
1274
1836
|
hash[:source] = self
|
1275
1837
|
Puppet::Event::Subscription.new(hash)
|
@@ -1291,15 +1853,6 @@ class Type < Puppet::Element
|
|
1291
1853
|
}
|
1292
1854
|
end
|
1293
1855
|
|
1294
|
-
# return all of the subscriptions to a given event
|
1295
|
-
#def subscribers?(event)
|
1296
|
-
# Puppet::Event::Subscription.subscriptions(self).find_all { |sub|
|
1297
|
-
# sub.match?(event)
|
1298
|
-
# }.collect { |sub|
|
1299
|
-
# sub.target
|
1300
|
-
# }
|
1301
|
-
#end
|
1302
|
-
|
1303
1856
|
# we've received an event
|
1304
1857
|
# we only support local events right now, so we can pass actual
|
1305
1858
|
# objects around, including the transaction object
|
@@ -1327,10 +1880,239 @@ class Type < Puppet::Element
|
|
1327
1880
|
|
1328
1881
|
# Documentation methods
|
1329
1882
|
def self.paramdoc(param)
|
1330
|
-
@
|
1883
|
+
@paramhash[param].doc
|
1331
1884
|
end
|
1332
1885
|
def self.metaparamdoc(metaparam)
|
1333
|
-
@@
|
1886
|
+
@@metaparamhash[metaparam].doc
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
# Add all of the meta parameters.
|
1890
|
+
#newmetaparam(:onerror) do
|
1891
|
+
# desc "How to handle errors -- roll back innermost
|
1892
|
+
# transaction, roll back entire transaction, ignore, etc. Currently
|
1893
|
+
# non-functional."
|
1894
|
+
#end
|
1895
|
+
|
1896
|
+
newmetaparam(:noop) do
|
1897
|
+
desc "Boolean flag indicating whether work should actually
|
1898
|
+
be done. *true*/**false**"
|
1899
|
+
munge do |noop|
|
1900
|
+
if noop == "true" or noop == true
|
1901
|
+
return true
|
1902
|
+
elsif noop == "false" or noop == false
|
1903
|
+
return false
|
1904
|
+
else
|
1905
|
+
self.fail("Invalid noop value '%s'" % noop)
|
1906
|
+
end
|
1907
|
+
end
|
1908
|
+
end
|
1909
|
+
|
1910
|
+
newmetaparam(:schedule) do
|
1911
|
+
desc "On what schedule the object should be managed. You must create a
|
1912
|
+
schedule_ object, and then reference the name of that object to use
|
1913
|
+
that for your schedule::
|
1914
|
+
|
1915
|
+
schedule { daily:
|
1916
|
+
period => daily,
|
1917
|
+
range => \"2-4\"
|
1918
|
+
}
|
1919
|
+
|
1920
|
+
exec { \"/usr/bin/apt-get update\":
|
1921
|
+
schedule => daily
|
1922
|
+
}
|
1923
|
+
|
1924
|
+
The creation of the schedule object does not need to appear in the
|
1925
|
+
configuration before objects that use it."
|
1926
|
+
|
1927
|
+
munge do |name|
|
1928
|
+
if schedule = Puppet.type(:schedule)[name]
|
1929
|
+
return schedule
|
1930
|
+
else
|
1931
|
+
return name
|
1932
|
+
end
|
1933
|
+
end
|
1934
|
+
end
|
1935
|
+
|
1936
|
+
newmetaparam(:check) do
|
1937
|
+
desc "States which should have their values retrieved
|
1938
|
+
but which should not actually be modified. This is currently used
|
1939
|
+
internally, but will eventually be used for querying, so that you
|
1940
|
+
could specify that you wanted to check the install state of all
|
1941
|
+
packages, and then query the Puppet client daemon to get reports
|
1942
|
+
on all packages."
|
1943
|
+
|
1944
|
+
munge do |args|
|
1945
|
+
unless args.is_a?(Array)
|
1946
|
+
args = [args]
|
1947
|
+
end
|
1948
|
+
|
1949
|
+
unless defined? @parent
|
1950
|
+
self.devfail "No parent for %s, %s?" %
|
1951
|
+
[self.class, self.name]
|
1952
|
+
end
|
1953
|
+
|
1954
|
+
args.each { |state|
|
1955
|
+
unless state.is_a?(Symbol)
|
1956
|
+
state = state.intern
|
1957
|
+
end
|
1958
|
+
next if @parent.statedefined?(state)
|
1959
|
+
|
1960
|
+
@parent.newstate(state)
|
1961
|
+
}
|
1962
|
+
end
|
1963
|
+
end
|
1964
|
+
# For each object we require, subscribe to all events that it generates. We
|
1965
|
+
# might reduce the level of subscription eventually, but for now...
|
1966
|
+
newmetaparam(:require) do
|
1967
|
+
desc "One or more objects that this object depends on.
|
1968
|
+
This is used purely for guaranteeing that changes to required objects
|
1969
|
+
happen before the dependent object. For instance::
|
1970
|
+
|
1971
|
+
# Create the destination directory before you copy things down
|
1972
|
+
file { \"/usr/local/scripts\":
|
1973
|
+
ensure => directory
|
1974
|
+
}
|
1975
|
+
|
1976
|
+
file { \"/usr/local/scripts/myscript\":
|
1977
|
+
source => \"puppet://server/module/myscript\",
|
1978
|
+
mode => 755,
|
1979
|
+
require => file[\"/usr/local/scripts\"]
|
1980
|
+
}
|
1981
|
+
|
1982
|
+
Note that Puppet will autorequire everything that it can, and
|
1983
|
+
there are hooks in place so that it's easy for elements to add new
|
1984
|
+
ways to autorequire objects, so if you think Puppet could be
|
1985
|
+
smarter here, let us know.
|
1986
|
+
|
1987
|
+
In fact, the above code was redundant -- Puppet will autorequire
|
1988
|
+
any parent directories that are being managed; it will
|
1989
|
+
automatically realize that the parent directory should be created
|
1990
|
+
before the script is pulled down.
|
1991
|
+
|
1992
|
+
Currently, exec_ elements will autorequire their CWD (if it is
|
1993
|
+
specified) plus any fully qualified paths that appear in the
|
1994
|
+
command. For instance, if you had an ``exec`` command that ran
|
1995
|
+
the ``myscript`` mentioned above, the above code that pulls the
|
1996
|
+
file down would be automatically listed as a requirement to the
|
1997
|
+
``exec`` code, so that you would always be running againts the
|
1998
|
+
most recent version.
|
1999
|
+
"
|
2000
|
+
|
2001
|
+
# Take whatever dependencies currently exist and add these.
|
2002
|
+
# Note that this probably doesn't behave correctly with unsubscribe.
|
2003
|
+
munge do |requires|
|
2004
|
+
# We need to be two arrays deep...
|
2005
|
+
unless requires.is_a?(Array)
|
2006
|
+
requires = [requires]
|
2007
|
+
end
|
2008
|
+
unless requires[0].is_a?(Array)
|
2009
|
+
requires = [requires]
|
2010
|
+
end
|
2011
|
+
if values = @parent[:require]
|
2012
|
+
requires = values + requires
|
2013
|
+
end
|
2014
|
+
requires
|
2015
|
+
#p @parent[:require]
|
2016
|
+
#@parent.handledepends(requires, :NONE, nil)
|
2017
|
+
end
|
2018
|
+
end
|
2019
|
+
|
2020
|
+
# For each object we require, subscribe to all events that it generates.
|
2021
|
+
# We might reduce the level of subscription eventually, but for now...
|
2022
|
+
newmetaparam(:subscribe) do
|
2023
|
+
desc "One or more objects that this object depends on. Changes in the
|
2024
|
+
subscribed to objects result in the dependent objects being
|
2025
|
+
refreshed (e.g., a service will get restarted). For instance::
|
2026
|
+
|
2027
|
+
class nagios {
|
2028
|
+
file { \"/etc/nagios/nagios.conf\":
|
2029
|
+
source => \"puppet://server/module/nagios.conf\",
|
2030
|
+
alias => nagconf # just to make things easier for me
|
2031
|
+
}
|
2032
|
+
|
2033
|
+
service { nagios:
|
2034
|
+
running => true,
|
2035
|
+
require => file[nagconf]
|
2036
|
+
}
|
2037
|
+
}
|
2038
|
+
"
|
2039
|
+
|
2040
|
+
munge do |requires|
|
2041
|
+
if values = @parent[:subscribe]
|
2042
|
+
requires = values + requires
|
2043
|
+
end
|
2044
|
+
requires
|
2045
|
+
# @parent.handledepends(requires, :ALL_EVENTS, :refresh)
|
2046
|
+
end
|
2047
|
+
end
|
2048
|
+
|
2049
|
+
newmetaparam(:loglevel) do
|
2050
|
+
desc "Sets the level that information will be logged:
|
2051
|
+
debug, info, verbose, notice, warning, err, alert, emerg or crit.
|
2052
|
+
The log levels have the biggest impact when logs are sent to
|
2053
|
+
syslog (which is currently the default)."
|
2054
|
+
defaultto :notice
|
2055
|
+
|
2056
|
+
validate do |loglevel|
|
2057
|
+
if loglevel.is_a?(String)
|
2058
|
+
loglevel = loglevel.intern
|
2059
|
+
end
|
2060
|
+
unless Puppet::Log.validlevel?(loglevel)
|
2061
|
+
self.fail "Invalid log level %s" % loglevel
|
2062
|
+
end
|
2063
|
+
end
|
2064
|
+
|
2065
|
+
munge do |loglevel|
|
2066
|
+
if loglevel.is_a?(String)
|
2067
|
+
loglevel = loglevel.intern
|
2068
|
+
end
|
2069
|
+
if loglevel == :verbose
|
2070
|
+
loglevel = :info
|
2071
|
+
end
|
2072
|
+
loglevel
|
2073
|
+
end
|
2074
|
+
end
|
2075
|
+
|
2076
|
+
newmetaparam(:alias) do
|
2077
|
+
desc "Creates an alias for the object. This simplifies lookup of the
|
2078
|
+
object so is useful in the language. It is especially useful when
|
2079
|
+
you are creating long commands using exec or when many different
|
2080
|
+
systems call a given package_ different names::
|
2081
|
+
|
2082
|
+
|
2083
|
+
file { \"/usr/local/scripts/myscript\":
|
2084
|
+
source => \"puppet://server/module/myscript\",
|
2085
|
+
mode => 755,
|
2086
|
+
alias => myscript
|
2087
|
+
}
|
2088
|
+
|
2089
|
+
exec { \"/usr/local/scripts/myscript\":
|
2090
|
+
require => file[myscript]
|
2091
|
+
}
|
2092
|
+
|
2093
|
+
Again, this is somewhat redundant, since any sane person would
|
2094
|
+
just use a variable (unless the two statements were in different
|
2095
|
+
scopes), and Puppet will autorequire the script anyway, but it
|
2096
|
+
gets the point across."
|
2097
|
+
|
2098
|
+
munge do |aliases|
|
2099
|
+
unless aliases.is_a?(Array)
|
2100
|
+
aliases = [aliases]
|
2101
|
+
end
|
2102
|
+
@parent.info "Adding aliases %s" % aliases.join(", ")
|
2103
|
+
aliases.each do |other|
|
2104
|
+
if obj = @parent.class[other]
|
2105
|
+
unless obj == @parent
|
2106
|
+
self.fail(
|
2107
|
+
"%s an not create alias %s: object already exists" %
|
2108
|
+
[@parent.name, other]
|
2109
|
+
)
|
2110
|
+
end
|
2111
|
+
next
|
2112
|
+
end
|
2113
|
+
@parent.class.alias(other, @parent)
|
2114
|
+
end
|
2115
|
+
end
|
1334
2116
|
end
|
1335
2117
|
end # Puppet::Type
|
1336
2118
|
end
|
@@ -1343,12 +2125,11 @@ require 'puppet/type/group'
|
|
1343
2125
|
require 'puppet/type/package'
|
1344
2126
|
require 'puppet/type/pfile'
|
1345
2127
|
require 'puppet/type/pfilebucket'
|
2128
|
+
require 'puppet/type/schedule'
|
1346
2129
|
require 'puppet/type/service'
|
1347
2130
|
require 'puppet/type/symlink'
|
1348
2131
|
require 'puppet/type/user'
|
1349
2132
|
require 'puppet/type/tidy'
|
1350
|
-
|
1351
|
-
#require 'puppet/type/typegen/filetype'
|
1352
|
-
#require 'puppet/type/typegen/filerecord'
|
2133
|
+
require 'puppet/type/parsedtype'
|
1353
2134
|
|
1354
|
-
# $Id: type.rb
|
2135
|
+
# $Id: type.rb 886 2006-02-08 17:45:26Z luke $
|