puppet 0.13.0 → 0.13.1
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 +5 -0
- data/Rakefile +2 -0
- data/bin/puppetd +2 -3
- data/bin/puppetmasterd +1 -3
- data/conf/redhat/client.init +3 -3
- data/conf/redhat/client.sysconfig +1 -1
- data/conf/redhat/logrotate +8 -0
- data/conf/redhat/puppet.spec +26 -2
- data/conf/redhat/puppetd.conf +5 -0
- data/conf/redhat/puppetmasterd.conf +5 -0
- data/conf/redhat/server.init +3 -3
- data/examples/code/snippets/aliastest.pp +16 -0
- data/ext/module_puppet +10 -11
- data/lib/puppet.rb +5 -4
- data/lib/puppet/client.rb +4 -4
- data/lib/puppet/daemon.rb +3 -2
- data/lib/puppet/filetype.rb +18 -6
- data/lib/puppet/lock.rb +64 -0
- data/lib/puppet/parser/ast/objectdef.rb +2 -2
- data/lib/puppet/parser/scope.rb +5 -1
- data/lib/puppet/sslcertificates/ca.rb +1 -3
- data/lib/puppet/statechange.rb +6 -5
- data/lib/puppet/storage.rb +9 -11
- data/lib/puppet/transportable.rb +46 -19
- data/lib/puppet/type.rb +108 -41
- data/lib/puppet/type/cron.rb +45 -17
- data/lib/puppet/type/parsedtype.rb +3 -2
- data/lib/puppet/type/pfile.rb +7 -1
- data/lib/puppet/type/pfile/checksum.rb +1 -2
- data/lib/puppet/util.rb +106 -57
- data/test/language/ast.rb +6 -6
- data/test/language/snippets.rb +6 -0
- data/test/puppet/utiltest.rb +34 -1
- data/test/puppettest.rb +9 -1
- data/test/types/cron.rb +40 -1
- data/test/types/schedule.rb +2 -2
- data/test/types/type.rb +26 -1
- metadata +7 -2
data/lib/puppet/type/cron.rb
CHANGED
@@ -21,6 +21,16 @@ module Puppet
|
|
21
21
|
attr_accessor :boundaries
|
22
22
|
end
|
23
23
|
|
24
|
+
# We have to override the parent method, because we consume the entire
|
25
|
+
# "should" array
|
26
|
+
def insync?
|
27
|
+
if self.class.name == :command
|
28
|
+
return super
|
29
|
+
else
|
30
|
+
return @is == @should
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
24
34
|
# A method used to do parameter input handling. Converts integers
|
25
35
|
# in string form to actual integers, and returns the value if it's
|
26
36
|
# an integer or false if it's just a normal string.
|
@@ -67,6 +77,18 @@ module Puppet
|
|
67
77
|
return false
|
68
78
|
end
|
69
79
|
|
80
|
+
def is_to_s
|
81
|
+
if @is.empty?
|
82
|
+
return "*"
|
83
|
+
else
|
84
|
+
if @is.is_a? Array
|
85
|
+
return @is.join(",")
|
86
|
+
else
|
87
|
+
return @is.to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
70
92
|
def should_to_s
|
71
93
|
if @should.empty?
|
72
94
|
return "*"
|
@@ -169,16 +191,18 @@ module Puppet
|
|
169
191
|
newparam(:user) do
|
170
192
|
desc "The user to run the command as. This user must
|
171
193
|
be allowed to run cron jobs, which is not currently checked by
|
172
|
-
Puppet.
|
194
|
+
Puppet.
|
195
|
+
|
196
|
+
The user defaults to whomever Puppet is running as."
|
197
|
+
|
198
|
+
defaultto Process.uid
|
173
199
|
|
174
|
-
# This validation isn't really a good idea, since the user might
|
175
|
-
# be created by Puppet, in which case the validation will fail.
|
176
200
|
validate do |user|
|
177
201
|
require 'etc'
|
178
202
|
|
179
203
|
begin
|
180
|
-
|
181
|
-
|
204
|
+
parent.uid = Puppet::Util.uid(user)
|
205
|
+
#obj = Etc.getpwnam(user)
|
182
206
|
rescue ArgumentError
|
183
207
|
self.fail "User %s not found" % user
|
184
208
|
end
|
@@ -212,13 +236,6 @@ module Puppet
|
|
212
236
|
@instances = {}
|
213
237
|
@tabs = {}
|
214
238
|
|
215
|
-
case Facter["operatingsystem"].value
|
216
|
-
when "Solaris":
|
217
|
-
@filetype = Puppet::FileType.filetype(:suntab)
|
218
|
-
else
|
219
|
-
@filetype = Puppet::FileType.filetype(:crontab)
|
220
|
-
end
|
221
|
-
|
222
239
|
class << self
|
223
240
|
attr_accessor :filetype
|
224
241
|
end
|
@@ -240,6 +257,17 @@ module Puppet
|
|
240
257
|
super
|
241
258
|
end
|
242
259
|
|
260
|
+
def self.defaulttype
|
261
|
+
case Facter["operatingsystem"].value
|
262
|
+
when "Solaris":
|
263
|
+
return Puppet::FileType.filetype(:suntab)
|
264
|
+
else
|
265
|
+
return Puppet::FileType.filetype(:crontab)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
self.filetype = self.defaulttype()
|
270
|
+
|
243
271
|
# Override the default Puppet::Type method, because instances
|
244
272
|
# also need to be deleted from the @instances hash
|
245
273
|
def self.delete(child)
|
@@ -303,9 +331,9 @@ module Puppet
|
|
303
331
|
fields().zip(match.captures).each { |param, value|
|
304
332
|
unless value == "*"
|
305
333
|
unless param == :command
|
306
|
-
|
307
|
-
|
308
|
-
|
334
|
+
# We always want the 'is' value to be an
|
335
|
+
# array
|
336
|
+
value = value.split(",")
|
309
337
|
end
|
310
338
|
hash[param] = value
|
311
339
|
end
|
@@ -403,7 +431,7 @@ module Puppet
|
|
403
431
|
# Collect all Cron instances for a given user and convert them
|
404
432
|
# into literal text.
|
405
433
|
def self.tab(user)
|
406
|
-
Puppet.info "
|
434
|
+
Puppet.info "Writing cron tab for %s" % user
|
407
435
|
if @instances.include?(user)
|
408
436
|
return self.header() + @instances[user].reject { |obj|
|
409
437
|
if obj.is_a?(self) and obj.should(:ensure) == :absent
|
@@ -501,4 +529,4 @@ module Puppet
|
|
501
529
|
end
|
502
530
|
end
|
503
531
|
|
504
|
-
# $Id: cron.rb
|
532
|
+
# $Id: cron.rb 898 2006-02-13 17:13:09Z luke $
|
@@ -55,7 +55,8 @@ module Puppet
|
|
55
55
|
tail = "deleted"
|
56
56
|
#elsif @is == @should
|
57
57
|
elsif self.insync?
|
58
|
-
self.info "
|
58
|
+
self.info "Already in sync: %s vs %s" %
|
59
|
+
[@is.inspect, @should.inspect]
|
59
60
|
return nil
|
60
61
|
else
|
61
62
|
#@is = self.should
|
@@ -292,4 +293,4 @@ end
|
|
292
293
|
require 'puppet/type/parsedtype/host'
|
293
294
|
require 'puppet/type/parsedtype/port'
|
294
295
|
|
295
|
-
# $Id: parsedtype.rb
|
296
|
+
# $Id: parsedtype.rb 898 2006-02-13 17:13:09Z luke $
|
data/lib/puppet/type/pfile.rb
CHANGED
@@ -22,6 +22,12 @@ module Puppet
|
|
22
22
|
newparam(:path) do
|
23
23
|
desc "The path to the file to manage. Must be fully qualified."
|
24
24
|
isnamevar
|
25
|
+
|
26
|
+
validate do |value|
|
27
|
+
unless value =~ /^#{File::SEPARATOR}/
|
28
|
+
raise Puppet::Error, "File paths must be fully qualified"
|
29
|
+
end
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
33
|
newparam(:backup) do
|
@@ -590,4 +596,4 @@ module Puppet
|
|
590
596
|
require 'puppet/type/pfile/mode'
|
591
597
|
require 'puppet/type/pfile/type'
|
592
598
|
end
|
593
|
-
# $Id: pfile.rb
|
599
|
+
# $Id: pfile.rb 896 2006-02-10 22:00:30Z luke $
|
@@ -181,7 +181,6 @@ module Puppet
|
|
181
181
|
# out of sync. We don't want to generate an event the first
|
182
182
|
# time we get a sum.
|
183
183
|
if @should == [:nosum]
|
184
|
-
self.warning "updatingness from %s" % @should.inspect
|
185
184
|
@should = [@is]
|
186
185
|
# FIXME we should support an updatechecksums-like mechanism
|
187
186
|
self.updatesum
|
@@ -272,4 +271,4 @@ module Puppet
|
|
272
271
|
end
|
273
272
|
end
|
274
273
|
|
275
|
-
# $Id: checksum.rb
|
274
|
+
# $Id: checksum.rb 896 2006-02-10 22:00:30Z luke $
|
data/lib/puppet/util.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# A module to collect utility functions.
|
2
2
|
|
3
|
+
require 'sync'
|
4
|
+
require 'puppet/lock'
|
5
|
+
|
3
6
|
module Puppet
|
4
7
|
module Util
|
8
|
+
# Create a sync point for any threads
|
9
|
+
@@sync = Sync.new
|
5
10
|
# Execute a block as a given user or group
|
6
11
|
def self.asuser(user = nil, group = nil)
|
7
12
|
require 'etc'
|
@@ -16,21 +21,7 @@ module Util
|
|
16
21
|
# The gid has to be changed first, because, well, otherwise we won't
|
17
22
|
# be able to
|
18
23
|
if group
|
19
|
-
|
20
|
-
gid = group
|
21
|
-
else
|
22
|
-
unless obj = Puppet.type(:group)[group]
|
23
|
-
obj = Puppet.type(:group).create(
|
24
|
-
:name => group,
|
25
|
-
:check => [:gid]
|
26
|
-
)
|
27
|
-
end
|
28
|
-
obj.retrieve
|
29
|
-
gid = obj.is(:gid)
|
30
|
-
unless gid.is_a?(Integer)
|
31
|
-
raise Puppet::Error, "Could not find group %s" % group
|
32
|
-
end
|
33
|
-
end
|
24
|
+
gid = self.gid(group)
|
34
25
|
|
35
26
|
if Process.gid != gid
|
36
27
|
oldgid = Process.gid
|
@@ -43,23 +34,7 @@ module Util
|
|
43
34
|
end
|
44
35
|
|
45
36
|
if user
|
46
|
-
|
47
|
-
if user.is_a?(Integer)
|
48
|
-
uid = user
|
49
|
-
else
|
50
|
-
unless obj = Puppet.type(:user)[user]
|
51
|
-
obj = Puppet.type(:user).create(
|
52
|
-
:name => user,
|
53
|
-
:check => [:uid, :gid]
|
54
|
-
)
|
55
|
-
end
|
56
|
-
obj.retrieve
|
57
|
-
uid = obj.is(:uid)
|
58
|
-
unless uid.is_a?(Integer)
|
59
|
-
raise Puppet::Error, "Could not find user %s" % user
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
37
|
+
uid = self.uid(user)
|
63
38
|
# Now change the uid
|
64
39
|
if Process.uid != uid
|
65
40
|
olduid = Process.uid
|
@@ -88,16 +63,7 @@ module Util
|
|
88
63
|
# Change the process to a different user
|
89
64
|
def self.chuser
|
90
65
|
if group = Puppet[:group]
|
91
|
-
|
92
|
-
group = Integer(group)
|
93
|
-
else
|
94
|
-
begin
|
95
|
-
g = Etc.getgrnam(group)
|
96
|
-
rescue ArgumentError
|
97
|
-
$stderr.puts "Could not find group %s" % group
|
98
|
-
end
|
99
|
-
group = g.gid
|
100
|
-
end
|
66
|
+
group = self.gid(group)
|
101
67
|
unless Process.gid == group
|
102
68
|
begin
|
103
69
|
Process.egid = group
|
@@ -110,16 +76,7 @@ module Util
|
|
110
76
|
end
|
111
77
|
|
112
78
|
if user = Puppet[:user]
|
113
|
-
|
114
|
-
user = Integer(user)
|
115
|
-
else
|
116
|
-
begin
|
117
|
-
u = Etc.getpwnam(user)
|
118
|
-
rescue ArgumentError
|
119
|
-
$stderr.puts "Could not find user %s" % user
|
120
|
-
end
|
121
|
-
user = u.uid
|
122
|
-
end
|
79
|
+
user = self.uid(user)
|
123
80
|
unless Process.uid == user
|
124
81
|
begin
|
125
82
|
Process.euid = user
|
@@ -132,8 +89,90 @@ module Util
|
|
132
89
|
end
|
133
90
|
end
|
134
91
|
|
92
|
+
# Create a shared lock for reading
|
93
|
+
def self.readlock(file)
|
94
|
+
@@sync.synchronize(Sync::SH) do
|
95
|
+
File.open(file) { |f|
|
96
|
+
f.lock_shared { |lf| yield lf }
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Create an exclusive lock fro writing, and do the writing in a
|
102
|
+
# tmp file.
|
103
|
+
def self.writelock(file, mode = 0600)
|
104
|
+
tmpfile = file + ".tmp"
|
105
|
+
@@sync.synchronize(Sync::EX) do
|
106
|
+
File.open(file, "w", mode) do |rf|
|
107
|
+
rf.lock_exclusive do |lrf|
|
108
|
+
yield lrf
|
109
|
+
File.open(tmpfile, "w", mode) do |tf|
|
110
|
+
yield tf
|
111
|
+
tf.flush
|
112
|
+
end
|
113
|
+
begin
|
114
|
+
File.rename(tmpfile, file)
|
115
|
+
rescue => detail
|
116
|
+
Puppet.err "Could not rename %s to %s: %s" %
|
117
|
+
[file, tmpfile, detail]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Get the GID of a given group, provided either a GID or a name
|
125
|
+
def self.gid(group)
|
126
|
+
if group =~ /^\d+$/
|
127
|
+
group = Integer(group)
|
128
|
+
end
|
129
|
+
gid = nil
|
130
|
+
if group.is_a?(Integer)
|
131
|
+
gid = group
|
132
|
+
else
|
133
|
+
unless obj = Puppet.type(:group)[group]
|
134
|
+
obj = Puppet.type(:group).create(
|
135
|
+
:name => group,
|
136
|
+
:check => [:gid]
|
137
|
+
)
|
138
|
+
end
|
139
|
+
obj.retrieve
|
140
|
+
gid = obj.is(:gid)
|
141
|
+
unless gid.is_a?(Integer)
|
142
|
+
raise Puppet::Error, "Could not find group %s" % group
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
return gid
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get the UID of a given user, whether a UID or name is provided
|
150
|
+
def self.uid(user)
|
151
|
+
uid = nil
|
152
|
+
if user =~ /^\d+$/
|
153
|
+
user = Integer(user)
|
154
|
+
end
|
155
|
+
if user.is_a?(Integer)
|
156
|
+
uid = user
|
157
|
+
else
|
158
|
+
unless obj = Puppet.type(:user)[user]
|
159
|
+
obj = Puppet.type(:user).create(
|
160
|
+
:name => user,
|
161
|
+
:check => [:uid, :gid]
|
162
|
+
)
|
163
|
+
end
|
164
|
+
obj.retrieve
|
165
|
+
uid = obj.is(:uid)
|
166
|
+
unless uid.is_a?(Integer)
|
167
|
+
raise Puppet::Error, "Could not find user %s" % user
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
return uid
|
172
|
+
end
|
173
|
+
|
135
174
|
# Create a lock file while something is happening
|
136
|
-
def self.
|
175
|
+
def self.disabledlock(*opts)
|
137
176
|
lock = opts[0] + ".lock"
|
138
177
|
while File.exists?(lock)
|
139
178
|
stamp = File.stat(lock).mtime.to_i
|
@@ -141,9 +180,11 @@ module Util
|
|
141
180
|
Puppet.notice "Lock file %s is %s seconds old; removing" %
|
142
181
|
[lock, Time.now.to_i - stamp]
|
143
182
|
File.delete(lock)
|
183
|
+
break
|
184
|
+
else
|
185
|
+
sleep 0.1
|
144
186
|
end
|
145
187
|
#Puppet.debug "%s is locked" % opts[0]
|
146
|
-
sleep 0.1
|
147
188
|
end
|
148
189
|
File.open(lock, "w") { |f| f.print " "; f.flush }
|
149
190
|
writing = false
|
@@ -155,8 +196,16 @@ module Util
|
|
155
196
|
end
|
156
197
|
begin
|
157
198
|
File.open(*opts) { |file| yield file }
|
158
|
-
|
159
|
-
|
199
|
+
begin
|
200
|
+
if writing
|
201
|
+
Puppet.warning "opts were %s" % opts.inspect
|
202
|
+
system("ls -l %s 2>/dev/null" % tmp)
|
203
|
+
system("ls -l %s 2>/dev/null" % orig)
|
204
|
+
File.rename(tmp, orig)
|
205
|
+
end
|
206
|
+
rescue => detail
|
207
|
+
Puppet.err "Could not replace %s: %s" % [orig, detail]
|
208
|
+
File.unlink(tmp)
|
160
209
|
end
|
161
210
|
rescue => detail
|
162
211
|
Puppet.err "Storage error: %s" % detail
|
@@ -229,4 +278,4 @@ module Util
|
|
229
278
|
end
|
230
279
|
end
|
231
280
|
|
232
|
-
# $Id: util.rb
|
281
|
+
# $Id: util.rb 898 2006-02-13 17:13:09Z luke $
|
data/test/language/ast.rb
CHANGED
@@ -293,11 +293,11 @@ class TestAST < Test::Unit::TestCase
|
|
293
293
|
|
294
294
|
# And now verify that we got both the top and node objects
|
295
295
|
assert_nothing_raised("Could not find top-declared object") {
|
296
|
-
assert_equal("/testing", objects[0]
|
296
|
+
assert_equal("/testing", objects[0].name)
|
297
297
|
}
|
298
298
|
|
299
299
|
assert_nothing_raised("Could not find node-declared object") {
|
300
|
-
assert_equal("/%s" % name, objects[1][0]
|
300
|
+
assert_equal("/%s" % name, objects[1][0].name)
|
301
301
|
}
|
302
302
|
end
|
303
303
|
|
@@ -338,7 +338,7 @@ class TestAST < Test::Unit::TestCase
|
|
338
338
|
assert(objects, "Could not retrieve objects")
|
339
339
|
|
340
340
|
assert_nothing_raised("Could not find top-declared object") {
|
341
|
-
assert_equal("/%s" % klassname, objects[0][0]
|
341
|
+
assert_equal("/%s" % klassname, objects[0][0].name)
|
342
342
|
}
|
343
343
|
end
|
344
344
|
|
@@ -395,19 +395,19 @@ class TestAST < Test::Unit::TestCase
|
|
395
395
|
# And now verify that we got the subnode file
|
396
396
|
assert_nothing_raised("Could not find basenode file") {
|
397
397
|
base = inner[0]
|
398
|
-
assert_equal("/basenode", base
|
398
|
+
assert_equal("/basenode", base.name)
|
399
399
|
}
|
400
400
|
|
401
401
|
# and the parent node file
|
402
402
|
assert_nothing_raised("Could not find subnode file") {
|
403
403
|
sub = inner[1]
|
404
|
-
assert_equal("/subnode", sub
|
404
|
+
assert_equal("/subnode", sub.name)
|
405
405
|
}
|
406
406
|
|
407
407
|
inner.each { |obj|
|
408
408
|
%w{basenode subnode}.each { |tag|
|
409
409
|
assert(obj.tags.include?(tag),
|
410
|
-
"%s did not include %s tag" % [obj
|
410
|
+
"%s did not include %s tag" % [obj.name, tag]
|
411
411
|
)
|
412
412
|
}
|
413
413
|
}
|
data/test/language/snippets.rb
CHANGED
@@ -394,6 +394,12 @@ class TestSnippets < Test::Unit::TestCase
|
|
394
394
|
}
|
395
395
|
end
|
396
396
|
|
397
|
+
def snippet_aliastest(trans)
|
398
|
+
%w{/tmp/aliastest /tmp/aliastest2 /tmp/aliastest3}.each { |file|
|
399
|
+
assert(FileTest.file?(file), "File %s does not exist" % file)
|
400
|
+
}
|
401
|
+
end
|
402
|
+
|
397
403
|
def snippet_emptyclass(trans)
|
398
404
|
# There's nothing to check other than that it works
|
399
405
|
end
|