puppet 0.16.0 → 0.18.4
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 +98 -0
- data/Rakefile +5 -1
- data/bin/puppet +1 -1
- data/bin/puppetca +25 -11
- data/bin/puppetd +189 -66
- data/bin/puppetdoc +79 -62
- data/bin/puppetmasterd +93 -49
- data/bin/puppetrun +385 -0
- data/conf/redhat/client.init +5 -2
- data/conf/redhat/fileserver.conf +1 -1
- data/conf/redhat/lsb-config.patch +51 -0
- data/conf/redhat/puppet.spec +45 -18
- data/conf/redhat/puppetd.conf +32 -4
- data/conf/redhat/server.init +5 -2
- data/conf/solaris/pkginfo +7 -0
- data/conf/solaris/smf/puppetd.xml +77 -0
- data/conf/solaris/smf/puppetmasterd.xml +77 -0
- data/conf/solaris/smf/svc-puppetd +66 -0
- data/conf/solaris/smf/svc-puppetmasterd +62 -0
- data/examples/code/failers/noobjectrvalue +1 -0
- data/examples/code/snippets/deepclassheirarchy.pp +23 -0
- data/examples/code/snippets/defineoverrides.pp +17 -0
- data/examples/code/snippets/emptyexec.pp +3 -0
- data/examples/code/snippets/selectorvalues.pp +6 -1
- data/examples/code/snippets/tagged.pp +35 -0
- data/ext/ldap/puppet.schema +2 -2
- data/install.rb +4 -2
- data/lib/puppet.rb +206 -15
- data/lib/puppet/client.rb +30 -20
- data/lib/puppet/client/ca.rb +2 -2
- data/lib/puppet/client/dipper.rb +5 -9
- data/lib/puppet/client/master.rb +224 -44
- data/lib/puppet/client/pelement.rb +54 -9
- data/lib/puppet/client/proxy.rb +3 -2
- data/lib/puppet/client/reporter.rb +34 -0
- data/lib/puppet/client/runner.rb +17 -0
- data/lib/puppet/config.rb +136 -55
- data/lib/puppet/daemon.rb +59 -37
- data/lib/puppet/element.rb +2 -1
- data/lib/puppet/event.rb +14 -3
- data/lib/puppet/filetype.rb +28 -19
- data/lib/puppet/log.rb +297 -132
- data/lib/puppet/metric.rb +31 -131
- data/lib/puppet/networkclient.rb +73 -46
- data/lib/puppet/parameter.rb +49 -1
- data/lib/puppet/parsedfile.rb +32 -12
- data/lib/puppet/parser/ast.rb +6 -1
- data/lib/puppet/parser/ast/astarray.rb +32 -6
- data/lib/puppet/parser/ast/collection.rb +91 -0
- data/lib/puppet/parser/ast/compdef.rb +2 -2
- data/lib/puppet/parser/ast/component.rb +24 -11
- data/lib/puppet/parser/ast/function.rb +50 -0
- data/lib/puppet/parser/ast/hostclass.rb +70 -22
- data/lib/puppet/parser/ast/node.rb +17 -8
- data/lib/puppet/parser/ast/nodedef.rb +1 -1
- data/lib/puppet/parser/ast/objectdef.rb +28 -10
- data/lib/puppet/parser/ast/selector.rb +4 -1
- data/lib/puppet/parser/functions.rb +145 -0
- data/lib/puppet/parser/interpreter.rb +243 -86
- data/lib/puppet/parser/lexer.rb +5 -4
- data/lib/puppet/parser/parser.rb +586 -505
- data/lib/puppet/parser/scope.rb +337 -187
- data/lib/puppet/rails.rb +115 -0
- data/lib/puppet/rails/database.rb +40 -0
- data/lib/puppet/rails/host.rb +83 -0
- data/lib/puppet/rails/rails_object.rb +42 -0
- data/lib/puppet/rails/rails_parameter.rb +5 -0
- data/lib/puppet/reports/rrdgraph.rb +20 -0
- data/lib/puppet/reports/tagmail.rb +94 -0
- data/lib/puppet/server.rb +20 -4
- data/lib/puppet/server/authconfig.rb +14 -3
- data/lib/puppet/server/authstore.rb +2 -2
- data/lib/puppet/server/ca.rb +23 -11
- data/lib/puppet/server/filebucket.rb +10 -10
- data/lib/puppet/server/fileserver.rb +4 -8
- data/lib/puppet/server/master.rb +19 -22
- data/lib/puppet/server/pelement.rb +28 -16
- data/lib/puppet/server/report.rb +184 -0
- data/lib/puppet/server/runner.rb +62 -0
- data/lib/puppet/server/servlet.rb +23 -9
- data/lib/puppet/sslcertificates/ca.rb +25 -1
- data/lib/puppet/statechange.rb +34 -53
- data/lib/puppet/storage.rb +1 -2
- data/lib/puppet/transaction.rb +305 -133
- data/lib/puppet/transaction/report.rb +42 -0
- data/lib/puppet/transportable.rb +57 -33
- data/lib/puppet/type.rb +260 -127
- data/lib/puppet/type/component.rb +9 -21
- data/lib/puppet/type/cron.rb +367 -116
- data/lib/puppet/type/exec.rb +15 -16
- data/lib/puppet/type/group.rb +9 -1
- data/lib/puppet/type/nameservice.rb +2 -5
- data/lib/puppet/type/nameservice/netinfo.rb +3 -0
- data/lib/puppet/type/nameservice/objectadd.rb +23 -10
- data/lib/puppet/type/nameservice/pw.rb +16 -3
- data/lib/puppet/type/package.rb +25 -75
- data/lib/puppet/type/package/apple.rb +15 -1
- data/lib/puppet/type/package/apt.rb +37 -2
- data/lib/puppet/type/package/blastwave.rb +136 -0
- data/lib/puppet/type/package/dpkg.rb +4 -4
- data/lib/puppet/type/package/gem.rb +119 -0
- data/lib/puppet/type/package/openbsd.rb +7 -6
- data/lib/puppet/type/package/ports.rb +7 -2
- data/lib/puppet/type/package/rpm.rb +1 -1
- data/lib/puppet/type/package/sun.rb +23 -9
- data/lib/puppet/type/package/sunfreeware.rb +7 -0
- data/lib/puppet/type/package/yum.rb +16 -9
- data/lib/puppet/type/parsedtype.rb +7 -5
- data/lib/puppet/type/parsedtype/mount.rb +55 -34
- data/lib/puppet/type/parsedtype/port.rb +7 -1
- data/lib/puppet/type/parsedtype/sshkey.rb +6 -16
- data/lib/puppet/type/pfile.rb +115 -23
- data/lib/puppet/type/pfile/checksum.rb +18 -5
- data/lib/puppet/type/pfile/content.rb +2 -2
- data/lib/puppet/type/pfile/ensure.rb +3 -3
- data/lib/puppet/type/pfile/group.rb +2 -2
- data/lib/puppet/type/pfile/source.rb +28 -17
- data/lib/puppet/type/pfile/target.rb +25 -17
- data/lib/puppet/type/pfilebucket.rb +25 -6
- data/lib/puppet/type/schedule.rb +6 -6
- data/lib/puppet/type/service.rb +24 -14
- data/lib/puppet/type/service/debian.rb +1 -1
- data/lib/puppet/type/service/redhat.rb +13 -10
- data/lib/puppet/type/service/smf.rb +3 -3
- data/lib/puppet/type/state.rb +1 -2
- data/lib/puppet/type/symlink.rb +3 -4
- data/lib/puppet/type/user.rb +22 -10
- data/lib/puppet/type/yumrepo.rb +6 -1
- data/lib/puppet/type/zone.rb +595 -0
- data/lib/puppet/util.rb +58 -12
- data/test/client/client.rb +2 -2
- data/test/client/master.rb +92 -3
- data/test/client/pelement.rb +99 -0
- data/test/executables/puppetbin.rb +3 -4
- data/test/executables/puppetca.rb +3 -3
- data/test/executables/puppetd.rb +3 -3
- data/test/executables/puppetmasterd.rb +1 -5
- data/test/executables/puppetmodule.rb +2 -2
- data/test/language/ast.rb +200 -11
- data/test/language/functions.rb +245 -0
- data/test/language/interpreter.rb +155 -6
- data/test/language/lexer.rb +35 -2
- data/test/language/node.rb +48 -1
- data/test/language/parser.rb +250 -1
- data/test/language/rails.rb +105 -0
- data/test/language/scope.rb +304 -10
- data/test/language/snippets.rb +54 -5
- data/test/language/transportable.rb +60 -28
- data/test/other/config.rb +214 -1
- data/test/other/events.rb +67 -9
- data/test/other/log.rb +31 -5
- data/test/other/metrics.rb +23 -21
- data/test/other/parsedfile.rb +29 -2
- data/test/other/puppet.rb +79 -0
- data/test/other/report.rb +106 -0
- data/test/other/storage.rb +2 -2
- data/test/other/transactions.rb +128 -2
- data/test/puppet/utiltest.rb +10 -5
- data/test/puppettest.rb +193 -21
- data/test/server/authstore.rb +13 -4
- data/test/server/bucket.rb +33 -8
- data/test/server/ca.rb +44 -6
- data/test/server/master.rb +6 -7
- data/test/server/pelement.rb +15 -5
- data/test/server/report.rb +93 -0
- data/test/server/runner.rb +107 -0
- data/test/server/server.rb +28 -1
- data/test/types/cron.rb +339 -31
- data/test/types/file.rb +256 -24
- data/test/types/filebucket.rb +6 -2
- data/test/types/filesources.rb +41 -92
- data/test/types/group.rb +31 -1
- data/test/types/host.rb +2 -1
- data/test/types/mount.rb +18 -1
- data/test/types/package.rb +200 -18
- data/test/types/service.rb +5 -1
- data/test/types/sshkey.rb +2 -1
- data/test/types/symlink.rb +3 -2
- data/test/types/type.rb +180 -1
- data/test/types/user.rb +65 -27
- data/test/types/yumrepo.rb +15 -0
- data/test/types/zone.rb +437 -0
- metadata +43 -4
- data/bin/cf2puppet +0 -186
- data/conf/redhat/puppetmasterd.conf +0 -5
@@ -77,10 +77,18 @@ module Puppet
|
|
77
77
|
# dependencies. This will get run once on the top-level component,
|
78
78
|
# and it will do everything necessary.
|
79
79
|
def finalize
|
80
|
+
started = {}
|
80
81
|
finished = {}
|
81
82
|
|
82
83
|
# First do all of the finish work, which mostly involves
|
83
84
|
self.delve do |object|
|
85
|
+
# Make sure we don't get into loops
|
86
|
+
if started.has_key?(object)
|
87
|
+
debug "Already finished %s" % object.name
|
88
|
+
next
|
89
|
+
else
|
90
|
+
started[object] = true
|
91
|
+
end
|
84
92
|
unless finished.has_key?(object)
|
85
93
|
object.finish
|
86
94
|
object.builddepends
|
@@ -133,20 +141,6 @@ module Puppet
|
|
133
141
|
return @name
|
134
142
|
end
|
135
143
|
|
136
|
-
def push(*ary)
|
137
|
-
ary.each { |child|
|
138
|
-
unless child.is_a?(Puppet::Element)
|
139
|
-
self.debug "Got object of type %s" % child.class
|
140
|
-
self.devfail(
|
141
|
-
"Containers can only contain Puppet::Elements, not %s" %
|
142
|
-
child.class
|
143
|
-
)
|
144
|
-
end
|
145
|
-
@children.push child
|
146
|
-
child.parent = self
|
147
|
-
}
|
148
|
-
end
|
149
|
-
|
150
144
|
def refresh
|
151
145
|
@children.collect { |child|
|
152
146
|
if child.respond_to?(:refresh)
|
@@ -156,16 +150,10 @@ module Puppet
|
|
156
150
|
}
|
157
151
|
end
|
158
152
|
|
159
|
-
#def retrieve
|
160
|
-
# self.collect { |child|
|
161
|
-
# child.retrieve
|
162
|
-
# }
|
163
|
-
#end
|
164
|
-
|
165
153
|
def to_s
|
166
154
|
return "component(%s)" % self.name
|
167
155
|
end
|
168
156
|
end
|
169
157
|
end
|
170
158
|
|
171
|
-
# $Id: component.rb
|
159
|
+
# $Id: component.rb 1246 2006-06-08 20:38:44Z luke $
|
data/lib/puppet/type/cron.rb
CHANGED
@@ -10,7 +10,6 @@ module Puppet
|
|
10
10
|
# completely symbolic 'name' paremeter, which gets written to the file
|
11
11
|
# and is used to manage the job.
|
12
12
|
newtype(:cron) do
|
13
|
-
ensurable
|
14
13
|
|
15
14
|
# A base class for all of the Cron parameters, since they all have
|
16
15
|
# similar argument checking going on. We're stealing the base class
|
@@ -18,20 +17,16 @@ module Puppet
|
|
18
17
|
# but it was just too annoying to do.
|
19
18
|
class CronParam < Puppet::State::ParsedParam
|
20
19
|
class << self
|
21
|
-
attr_accessor :boundaries
|
20
|
+
attr_accessor :boundaries, :default
|
22
21
|
end
|
23
22
|
|
24
23
|
# We have to override the parent method, because we consume the entire
|
25
24
|
# "should" array
|
26
25
|
def insync?
|
27
|
-
if
|
28
|
-
|
26
|
+
if defined? @should and @should
|
27
|
+
self.is_to_s == self.should_to_s
|
29
28
|
else
|
30
|
-
|
31
|
-
return @is == @should
|
32
|
-
else
|
33
|
-
return @is == @should[0]
|
34
|
-
end
|
29
|
+
true
|
35
30
|
end
|
36
31
|
end
|
37
32
|
|
@@ -81,23 +76,35 @@ module Puppet
|
|
81
76
|
return false
|
82
77
|
end
|
83
78
|
|
84
|
-
def
|
85
|
-
if @
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
79
|
+
def should_to_s
|
80
|
+
if @should
|
81
|
+
unless @should.is_a?(Array)
|
82
|
+
fail "wtf?"
|
83
|
+
end
|
84
|
+
|
85
|
+
if self.name == :command or @should[0].is_a? Symbol
|
86
|
+
@should[0]
|
90
87
|
else
|
91
|
-
|
88
|
+
@should.join(",")
|
92
89
|
end
|
90
|
+
else
|
91
|
+
nil
|
93
92
|
end
|
94
93
|
end
|
95
94
|
|
96
|
-
def
|
97
|
-
if
|
98
|
-
|
95
|
+
def is_to_s
|
96
|
+
if @is
|
97
|
+
unless @is.is_a?(Array)
|
98
|
+
return @is
|
99
|
+
end
|
100
|
+
|
101
|
+
if self.name == :command or @is[0].is_a? Symbol
|
102
|
+
@is[0]
|
103
|
+
else
|
104
|
+
@is.join(",")
|
105
|
+
end
|
99
106
|
else
|
100
|
-
|
107
|
+
nil
|
101
108
|
end
|
102
109
|
end
|
103
110
|
|
@@ -112,6 +119,21 @@ module Puppet
|
|
112
119
|
if value == "absent" or value == :absent
|
113
120
|
return :absent
|
114
121
|
end
|
122
|
+
|
123
|
+
# Allow the */2 syntax
|
124
|
+
if value =~ /^\*\/[0-9]+$/
|
125
|
+
return value
|
126
|
+
end
|
127
|
+
|
128
|
+
# Allow ranges
|
129
|
+
if value =~ /^[0-9]+-[0-9]+$/
|
130
|
+
return value
|
131
|
+
end
|
132
|
+
|
133
|
+
if value == "*"
|
134
|
+
return value
|
135
|
+
end
|
136
|
+
|
115
137
|
return value unless self.class.boundaries
|
116
138
|
lower, upper = self.class.boundaries
|
117
139
|
retval = nil
|
@@ -132,6 +154,15 @@ module Puppet
|
|
132
154
|
end
|
133
155
|
end
|
134
156
|
end
|
157
|
+
|
158
|
+
|
159
|
+
# Override 'newstate' so that all states default to having the
|
160
|
+
# correct parent type
|
161
|
+
def self.newstate(name, parent = nil, &block)
|
162
|
+
parent ||= Puppet::State::CronParam
|
163
|
+
super(name, parent, &block)
|
164
|
+
end
|
165
|
+
|
135
166
|
# Somewhat uniquely, this state does not actually change anything -- it
|
136
167
|
# just calls +@parent.sync+, which writes out the whole cron tab for
|
137
168
|
# the user in question. There is no real way to change individual cron
|
@@ -148,6 +179,33 @@ module Puppet
|
|
148
179
|
|
149
180
|
All cron parameters support ``absent`` as a value; this will
|
150
181
|
remove any existing values for that field."
|
182
|
+
|
183
|
+
def should
|
184
|
+
if @should
|
185
|
+
if @should.is_a? Array
|
186
|
+
@should[0]
|
187
|
+
else
|
188
|
+
devfail "command is not an array"
|
189
|
+
end
|
190
|
+
else
|
191
|
+
nil
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
newstate(:special, Puppet::State::ParsedParam) do
|
197
|
+
desc "Special schedules only supported on FreeBSD."
|
198
|
+
|
199
|
+
def specials
|
200
|
+
%w{reboot yearly annually monthly weekly daily midnight hourly}
|
201
|
+
end
|
202
|
+
|
203
|
+
validate do |value|
|
204
|
+
unless specials().include?(value)
|
205
|
+
raise ArgumentError, "Invalid special schedule %s" %
|
206
|
+
value.inspect
|
207
|
+
end
|
208
|
+
end
|
151
209
|
end
|
152
210
|
|
153
211
|
newstate(:minute, CronParam) do
|
@@ -188,17 +246,58 @@ module Puppet
|
|
188
246
|
command. Optional; if specified, must be between 1 and 31."
|
189
247
|
end
|
190
248
|
|
249
|
+
newstate(:environment, Puppet::State::ParsedParam) do
|
250
|
+
desc "Any environment settings associated with this cron job. They
|
251
|
+
will be stored between the header and the job in the crontab. There
|
252
|
+
can be no guarantees that other, earlier settings will not also
|
253
|
+
affect a given cron job.
|
254
|
+
|
255
|
+
Also, Puppet cannot automatically determine whether an existing,
|
256
|
+
unmanaged environment setting is associated with a given cron
|
257
|
+
job. If you already have cron jobs with environment settings,
|
258
|
+
then Puppet will keep those settings in the same place in the file,
|
259
|
+
but will not associate them with a specific job."
|
260
|
+
|
261
|
+
validate do |value|
|
262
|
+
unless value =~ /^\s*(\w+)\s*=\s*(.+)\s*$/
|
263
|
+
raise ArgumentError, "Invalid environment setting %s" %
|
264
|
+
value.inspect
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def insync?
|
269
|
+
if @is.is_a? Array
|
270
|
+
return @is.sort == @should.sort
|
271
|
+
else
|
272
|
+
return @is == @should[0]
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def should
|
277
|
+
@should
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
191
281
|
newparam(:name) do
|
192
282
|
desc "The symbolic name of the cron job. This name
|
193
283
|
is used for human reference only and is generated automatically
|
194
284
|
for cron jobs found on the system. This generally won't
|
195
285
|
matter, as Puppet will do its best to match existing cron jobs
|
196
|
-
against specified jobs (and Puppet adds a
|
286
|
+
against specified jobs (and Puppet adds a comment to cron jobs it
|
197
287
|
adds), but it is at least possible that converting from
|
198
288
|
unmanaged jobs to managed jobs might require manual
|
199
|
-
intervention.
|
289
|
+
intervention.
|
290
|
+
|
291
|
+
The names can only have alphanumeric characters plus the '-'
|
292
|
+
character."
|
200
293
|
|
201
294
|
isnamevar
|
295
|
+
|
296
|
+
validate do |value|
|
297
|
+
unless value =~ /^[-\w]+$/
|
298
|
+
raise ArgumentError, "Invalid name format '%s'" % value
|
299
|
+
end
|
300
|
+
end
|
202
301
|
end
|
203
302
|
|
204
303
|
newparam(:user) do
|
@@ -232,7 +331,7 @@ module Puppet
|
|
232
331
|
association is made and synced to disk, you can then manage the job
|
233
332
|
normally (e.g., change the schedule of the job).
|
234
333
|
|
235
|
-
Example
|
334
|
+
Example:
|
236
335
|
|
237
336
|
cron { logrotate:
|
238
337
|
command => \"/usr/sbin/logrotate\",
|
@@ -247,17 +346,18 @@ module Puppet
|
|
247
346
|
|
248
347
|
class << self
|
249
348
|
attr_accessor :filetype
|
349
|
+
|
350
|
+
def cronobj(name)
|
351
|
+
if defined? @tabs
|
352
|
+
return @tabs[name]
|
353
|
+
else
|
354
|
+
return nil
|
355
|
+
end
|
356
|
+
end
|
250
357
|
end
|
251
358
|
|
252
359
|
attr_accessor :uid
|
253
360
|
|
254
|
-
# Override the Puppet::Type#[]= method so that we can store the instances
|
255
|
-
# in per-user arrays. Then just call +super+.
|
256
|
-
def self.[]=(name, object)
|
257
|
-
self.instance(object)
|
258
|
-
super
|
259
|
-
end
|
260
|
-
|
261
361
|
# In addition to removing the instances in @objects, Cron has to remove
|
262
362
|
# per-user cron tab information.
|
263
363
|
def self.clear
|
@@ -293,6 +393,55 @@ module Puppet
|
|
293
393
|
return [:minute, :hour, :monthday, :month, :weekday, :command]
|
294
394
|
end
|
295
395
|
|
396
|
+
# Convert our hash to an object
|
397
|
+
def self.hash2obj(hash)
|
398
|
+
obj = nil
|
399
|
+
namevar = self.namevar
|
400
|
+
unless hash.include?(namevar) and hash[namevar]
|
401
|
+
Puppet.info "Autogenerating name for %s" % hash[:command]
|
402
|
+
hash[:name] = "autocron-%s" % hash.object_id
|
403
|
+
end
|
404
|
+
|
405
|
+
unless hash.include?(:command)
|
406
|
+
raise Puppet::DevError, "No command for %s" % name
|
407
|
+
end
|
408
|
+
# if the cron already exists with that name...
|
409
|
+
if obj = (self[hash[:name]] || match(hash))
|
410
|
+
# Mark the cron job as present
|
411
|
+
obj.is = [:ensure, :present]
|
412
|
+
|
413
|
+
# Mark all of the values appropriately
|
414
|
+
hash.each { |param, value|
|
415
|
+
if state = obj.state(param)
|
416
|
+
state.is = value
|
417
|
+
elsif val = obj[param]
|
418
|
+
obj[param] = val
|
419
|
+
else
|
420
|
+
# There is a value on disk, but it should go away
|
421
|
+
obj.is = [param, value]
|
422
|
+
obj[param] = :absent
|
423
|
+
end
|
424
|
+
}
|
425
|
+
else
|
426
|
+
# create a new cron job, since no existing one
|
427
|
+
# seems to match
|
428
|
+
obj = self.create(
|
429
|
+
:name => hash[namevar]
|
430
|
+
)
|
431
|
+
|
432
|
+
obj.is = [:ensure, :present]
|
433
|
+
|
434
|
+
obj.notice "created"
|
435
|
+
|
436
|
+
hash.delete(namevar)
|
437
|
+
hash.each { |param, value|
|
438
|
+
obj.is = [param, value]
|
439
|
+
}
|
440
|
+
end
|
441
|
+
|
442
|
+
instance(obj)
|
443
|
+
end
|
444
|
+
|
296
445
|
# Return the header placed at the top of each generated file, warning
|
297
446
|
# users that modifying this file manually is probably a bad idea.
|
298
447
|
def self.header
|
@@ -302,16 +451,13 @@ module Puppet
|
|
302
451
|
# HEADER not be deleted, as doing so could cause duplicate cron jobs.\n}
|
303
452
|
end
|
304
453
|
|
305
|
-
# Store a new instance of a cron job. Called from Cron#initialize.
|
306
454
|
def self.instance(obj)
|
307
455
|
user = obj[:user]
|
308
|
-
|
309
|
-
|
310
|
-
@instances[obj[:user]] << obj
|
311
|
-
end
|
312
|
-
else
|
313
|
-
@instances[obj[:user]] = [obj]
|
456
|
+
unless @instances.include?(user)
|
457
|
+
@instances[user] = []
|
314
458
|
end
|
459
|
+
|
460
|
+
@instances[user] << obj
|
315
461
|
end
|
316
462
|
|
317
463
|
def self.list
|
@@ -323,6 +469,53 @@ module Puppet
|
|
323
469
|
self.collect { |c| c }
|
324
470
|
end
|
325
471
|
|
472
|
+
# See if we can match the hash against an existing cron job.
|
473
|
+
def self.match(hash)
|
474
|
+
self.find_all { |obj|
|
475
|
+
obj[:user] == hash[:user] and obj.value(:command) == hash[:command][0]
|
476
|
+
}.each do |obj|
|
477
|
+
# we now have a cron job whose command exactly matches
|
478
|
+
# let's see if the other fields match
|
479
|
+
|
480
|
+
# First check the @special stuff
|
481
|
+
if hash[:special]
|
482
|
+
next unless obj.value(:special) == hash[:special]
|
483
|
+
end
|
484
|
+
|
485
|
+
# Then the normal fields.
|
486
|
+
matched = true
|
487
|
+
fields().each do |field|
|
488
|
+
next if field == :command
|
489
|
+
if hash[field] and ! obj.value(field)
|
490
|
+
#Puppet.info "Cron is missing %s: %s and %s" %
|
491
|
+
# [field, hash[field].inspect, obj.value(field).inspect]
|
492
|
+
matched = false
|
493
|
+
break
|
494
|
+
end
|
495
|
+
|
496
|
+
if ! hash[field] and obj.value(field)
|
497
|
+
#Puppet.info "Hash is missing %s: %s and %s" %
|
498
|
+
# [field, obj.value(field).inspect, hash[field].inspect]
|
499
|
+
matched = false
|
500
|
+
break
|
501
|
+
end
|
502
|
+
|
503
|
+
# FIXME It'd be great if I could somehow reuse how the
|
504
|
+
# fields are turned into text, but....
|
505
|
+
next if (hash[field] == [:absent] and obj.value(field) == "*")
|
506
|
+
next if (hash[field].join(",") == obj.value(field))
|
507
|
+
#Puppet.info "Did not match %s: %s vs %s" %
|
508
|
+
# [field, obj.value(field).inspect, hash[field].inspect]
|
509
|
+
matched = false
|
510
|
+
break
|
511
|
+
end
|
512
|
+
next unless matched
|
513
|
+
return obj
|
514
|
+
end
|
515
|
+
|
516
|
+
return false
|
517
|
+
end
|
518
|
+
|
326
519
|
# Parse a user's cron job into individual cron objects.
|
327
520
|
#
|
328
521
|
# Autogenerates names for any jobs that don't already have one; these
|
@@ -334,74 +527,67 @@ module Puppet
|
|
334
527
|
def self.parse(user, text)
|
335
528
|
count = 0
|
336
529
|
hash = {}
|
337
|
-
|
338
|
-
|
339
|
-
@instances[user] = []
|
340
|
-
end
|
530
|
+
|
531
|
+
envs = []
|
341
532
|
text.chomp.split("\n").each { |line|
|
342
533
|
case line
|
343
|
-
when /^# Puppet Name: (
|
534
|
+
when /^# Puppet Name: (.+)$/
|
535
|
+
hash[:name] = $1
|
536
|
+
next
|
344
537
|
when /^#/:
|
345
538
|
# add other comments to the list as they are
|
346
539
|
@instances[user] << line
|
540
|
+
next
|
541
|
+
when /^\s*(\w+)\s*=\s*(.+)\s*$/:
|
542
|
+
# Match env settings.
|
543
|
+
if hash[:name]
|
544
|
+
envs << line
|
545
|
+
else
|
546
|
+
@instances[user] << line
|
547
|
+
end
|
548
|
+
next
|
549
|
+
when /^@(\w+)\s+(.+)/ # FreeBSD special cron crap
|
550
|
+
fields().each do |field|
|
551
|
+
next if field == :command
|
552
|
+
hash[field] = :absent
|
553
|
+
end
|
554
|
+
hash[:special] = $1
|
555
|
+
hash[:command] = $2
|
347
556
|
else
|
348
557
|
if match = /^(\S+) (\S+) (\S+) (\S+) (\S+) (.+)$/.match(line)
|
349
558
|
fields().zip(match.captures).each { |param, value|
|
350
|
-
|
351
|
-
|
559
|
+
if value == "*"
|
560
|
+
hash[param] = [:absent]
|
561
|
+
else
|
562
|
+
if param == :command
|
563
|
+
hash[param] = [value]
|
564
|
+
else
|
352
565
|
# We always want the 'is' value to be an
|
353
566
|
# array
|
354
|
-
|
567
|
+
hash[param] = value.split(",")
|
355
568
|
end
|
356
|
-
hash[param] = value
|
357
569
|
end
|
358
570
|
}
|
359
571
|
else
|
360
|
-
|
572
|
+
# Don't fail on unmatched lines, just warn on them
|
573
|
+
# and skip them.
|
574
|
+
Puppet.warning "Could not match '%s'" % line
|
575
|
+
next
|
361
576
|
end
|
577
|
+
end
|
362
578
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
name = "cron-%s" % hash.object_id
|
367
|
-
end
|
579
|
+
unless envs.empty?
|
580
|
+
hash[:environment] = envs
|
581
|
+
end
|
368
582
|
|
369
|
-
|
370
|
-
raise Puppet::DevError, "No command for %s" % name
|
371
|
-
end
|
372
|
-
# if the cron already exists with that name...
|
373
|
-
if cron = Puppet.type(:cron)[name]
|
374
|
-
# Mark the cron job as present
|
375
|
-
cron.is = [:ensure, :present]
|
376
|
-
elsif tmp = @instances[user].reject { |obj|
|
377
|
-
! obj.is_a?(self)
|
378
|
-
}.find { |obj|
|
379
|
-
obj.should(:command) == hash[:command]
|
380
|
-
}
|
381
|
-
# if we can find a cron whose spec exactly matches
|
382
|
-
|
383
|
-
# we now have a cron job whose command exactly matches
|
384
|
-
# let's see if the other fields match
|
385
|
-
txt = tmp.to_record.sub(/#.+\n/,'')
|
386
|
-
|
387
|
-
if txt == line
|
388
|
-
cron = tmp
|
389
|
-
end
|
390
|
-
else
|
391
|
-
# create a new cron job, since no existing one
|
392
|
-
# seems to match
|
393
|
-
cron = self.create(
|
394
|
-
:name => name
|
395
|
-
)
|
396
|
-
end
|
583
|
+
hash[:user] = user
|
397
584
|
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
end
|
585
|
+
# Now convert our hash to an object.
|
586
|
+
hash2obj(hash)
|
587
|
+
|
588
|
+
hash = {}
|
589
|
+
envs.clear
|
590
|
+
count += 1
|
405
591
|
}
|
406
592
|
end
|
407
593
|
|
@@ -427,10 +613,16 @@ module Puppet
|
|
427
613
|
self.find_all { |obj|
|
428
614
|
obj[:user] == user
|
429
615
|
}.each { |obj|
|
430
|
-
obj.
|
431
|
-
state.is = :absent
|
432
|
-
}
|
616
|
+
obj.is = [:ensure, :absent]
|
433
617
|
}
|
618
|
+
|
619
|
+
# Get rid of the old instances, so we don't get duplicates
|
620
|
+
if @instances.include?(user)
|
621
|
+
@instances[user].clear
|
622
|
+
else
|
623
|
+
@instances[user] = []
|
624
|
+
end
|
625
|
+
|
434
626
|
self.parse(user, text)
|
435
627
|
end
|
436
628
|
end
|
@@ -443,14 +635,24 @@ module Puppet
|
|
443
635
|
|
444
636
|
# Store the user's cron tab. Collects the text of the new tab and
|
445
637
|
# sends it to the +@filetype+ module's +write+ function. Also adds
|
446
|
-
# header warning users not to modify the file directly.
|
638
|
+
# header, warning users not to modify the file directly.
|
447
639
|
def self.store(user)
|
448
|
-
@
|
449
|
-
|
450
|
-
|
451
|
-
else
|
640
|
+
unless @instances.include?(user) or @objects.find do |n,o|
|
641
|
+
o[:user] == user
|
642
|
+
end
|
452
643
|
Puppet.notice "No cron instances for %s" % user
|
644
|
+
return
|
645
|
+
end
|
646
|
+
|
647
|
+
@tabs[user] ||= @filetype.new(user)
|
648
|
+
|
649
|
+
self.each do |inst|
|
650
|
+
unless (@instances[user] and @instances[user].include? inst)
|
651
|
+
@instances[user] ||= []
|
652
|
+
@instances[user] << inst
|
653
|
+
end
|
453
654
|
end
|
655
|
+
@tabs[user].write(self.tab(user))
|
454
656
|
end
|
455
657
|
|
456
658
|
# Collect all Cron instances for a given user and convert them
|
@@ -460,8 +662,6 @@ module Puppet
|
|
460
662
|
if @instances.include?(user)
|
461
663
|
return self.header() + @instances[user].reject { |obj|
|
462
664
|
if obj.is_a?(self) and obj.should(:ensure) == :absent
|
463
|
-
#obj.log "now absent"
|
464
|
-
#obj.is = [:ensure, :absent]
|
465
665
|
true
|
466
666
|
else
|
467
667
|
false
|
@@ -502,21 +702,11 @@ module Puppet
|
|
502
702
|
def destroy
|
503
703
|
# nothing, since the 'Cron.tab' method just doesn't write out
|
504
704
|
# crons whose 'ensure' states are set to 'absent'.
|
505
|
-
#@states.each { |n, state|
|
506
|
-
# next if n == :ensure
|
507
|
-
# state.should == :absent
|
508
|
-
#}
|
509
705
|
self.store
|
510
706
|
end
|
511
707
|
|
512
708
|
def exists?
|
513
|
-
|
514
|
-
if @states.include?(:command) and
|
515
|
-
@states[:command].is != :absent and
|
516
|
-
! @states[:command].is.nil?
|
517
|
-
val = true
|
518
|
-
end
|
519
|
-
return val
|
709
|
+
@states.include?(:ensure) and @states[:ensure].is == :present
|
520
710
|
end
|
521
711
|
|
522
712
|
# Override the default Puppet::Type method because we need to call
|
@@ -527,7 +717,15 @@ module Puppet
|
|
527
717
|
end
|
528
718
|
|
529
719
|
self.class.retrieve(self[:user])
|
530
|
-
|
720
|
+
if withtab = self.class["testwithtab"]
|
721
|
+
Puppet.info withtab.is(:ensure).inspect
|
722
|
+
end
|
723
|
+
self.eachstate { |st|
|
724
|
+
st.retrieve
|
725
|
+
}
|
726
|
+
if withtab = self.class["testwithtab"]
|
727
|
+
Puppet.info withtab.is(:ensure).inspect
|
728
|
+
end
|
531
729
|
end
|
532
730
|
|
533
731
|
# Write the entire user's cron tab out.
|
@@ -538,25 +736,78 @@ module Puppet
|
|
538
736
|
# Convert the current object a cron-style string. Adds the cron name
|
539
737
|
# as a comment above the cron job, in the form '# Puppet Name: <name>'.
|
540
738
|
def to_record
|
541
|
-
hash = {
|
739
|
+
hash = {}
|
542
740
|
|
543
741
|
# Collect all of the values that we have
|
544
|
-
self.class.fields().
|
545
|
-
|
546
|
-
|
742
|
+
self.class.fields().each { |param|
|
743
|
+
hash[param] = self.value(param)
|
744
|
+
|
745
|
+
unless hash[param]
|
746
|
+
devfail "Got no value for %s" % param
|
547
747
|
end
|
548
748
|
}
|
549
749
|
|
550
|
-
|
551
|
-
|
750
|
+
str = ""
|
751
|
+
|
752
|
+
str = "# Puppet Name: %s\n" % self.name
|
753
|
+
|
754
|
+
if @states.include?(:environment) and
|
755
|
+
@states[:environment].should != :absent
|
756
|
+
envs = @states[:environment].should
|
757
|
+
unless envs.is_a? Array
|
758
|
+
envs = [envs]
|
759
|
+
end
|
760
|
+
|
761
|
+
envs.each do |line| str += (line + "\n") end
|
762
|
+
end
|
763
|
+
|
764
|
+
line = nil
|
765
|
+
if special = self.value(:special)
|
766
|
+
line = str + "@%s %s" %
|
767
|
+
[special, self.value(:command)]
|
768
|
+
else
|
769
|
+
line = str + self.class.fields.collect { |f|
|
552
770
|
if hash[f] and hash[f] != :absent
|
553
771
|
hash[f]
|
554
772
|
else
|
555
773
|
"*"
|
556
774
|
end
|
557
775
|
}.join(" ")
|
776
|
+
end
|
777
|
+
|
778
|
+
return line
|
779
|
+
end
|
780
|
+
|
781
|
+
def value(name)
|
782
|
+
name = name.intern if name.is_a? String
|
783
|
+
ret = nil
|
784
|
+
if @states.include?(name)
|
785
|
+
ret = @states[name].should_to_s
|
786
|
+
|
787
|
+
if ret == :absent or ret.nil?
|
788
|
+
ret = @states[name].is_to_s
|
789
|
+
end
|
790
|
+
|
791
|
+
if ret == :absent
|
792
|
+
ret = nil
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
796
|
+
unless ret
|
797
|
+
case name
|
798
|
+
when :command
|
799
|
+
devfail "No command, somehow"
|
800
|
+
when :special
|
801
|
+
# nothing
|
802
|
+
else
|
803
|
+
#ret = (self.class.validstate?(name).default || "*").to_s
|
804
|
+
ret = "*"
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
808
|
+
ret
|
558
809
|
end
|
559
810
|
end
|
560
811
|
end
|
561
812
|
|
562
|
-
# $Id: cron.rb
|
813
|
+
# $Id: cron.rb 1402 2006-07-18 15:35:15Z luke $
|