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
@@ -1,6 +1,3 @@
|
|
1
|
-
#!/usr/local/bin/ruby -w
|
2
|
-
|
3
|
-
# $Id: component.rb 740 2005-11-01 20:22:19Z luke $
|
4
1
|
|
5
2
|
# the object allowing us to build complex structures
|
6
3
|
# this thing contains everything else, including itself
|
@@ -10,15 +7,20 @@ require 'puppet/type'
|
|
10
7
|
require 'puppet/transaction'
|
11
8
|
|
12
9
|
module Puppet
|
13
|
-
|
14
|
-
class Component < Puppet::Type
|
10
|
+
newtype(:component) do
|
15
11
|
include Enumerable
|
16
12
|
|
17
|
-
|
18
|
-
|
13
|
+
newparam(:name) do
|
14
|
+
desc "The name of the component. Generally optional."
|
15
|
+
isnamevar
|
16
|
+
end
|
17
|
+
|
18
|
+
newparam(:type) do
|
19
|
+
desc "The type that this component maps to. Generally some kind of
|
20
|
+
class from the language."
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
+
defaultto "component"
|
23
|
+
end
|
22
24
|
|
23
25
|
# topo sort functions
|
24
26
|
def self.sort(objects)
|
@@ -39,11 +41,15 @@ module Puppet
|
|
39
41
|
return
|
40
42
|
end
|
41
43
|
inlist[obj.object_id] = true
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
begin
|
45
|
+
obj.eachdependency { |req|
|
46
|
+
self.recurse(req, inlist, list)
|
47
|
+
}
|
48
|
+
rescue Puppet::Error => detail
|
49
|
+
raise Puppet::Error, "%s: %s" % [obj.path, detail]
|
50
|
+
end
|
45
51
|
|
46
|
-
if obj.is_a?
|
52
|
+
if obj.is_a? self
|
47
53
|
obj.each { |child|
|
48
54
|
self.recurse(child, inlist, list)
|
49
55
|
}
|
@@ -76,11 +82,6 @@ module Puppet
|
|
76
82
|
# Initialize a new component
|
77
83
|
def initialize(args)
|
78
84
|
@children = []
|
79
|
-
|
80
|
-
# it makes sense to have a more reasonable default here than 'false'
|
81
|
-
unless args.include?(:type) or args.include?("type")
|
82
|
-
args[:type] = "component"
|
83
|
-
end
|
84
85
|
super(args)
|
85
86
|
end
|
86
87
|
|
@@ -88,6 +89,12 @@ module Puppet
|
|
88
89
|
# this is only called on one component over the whole system
|
89
90
|
# this also won't work with scheduling, but eh
|
90
91
|
def evaluate
|
92
|
+
# The normal client process will automatically finalize things, but
|
93
|
+
# this simplifies a lot of test code -- as long as we use a
|
94
|
+
# compontent, we get finalized.
|
95
|
+
unless Puppet::Type.finalized?
|
96
|
+
Puppet::Type.finalize
|
97
|
+
end
|
91
98
|
transaction = Puppet::Transaction.new(self.flatten)
|
92
99
|
transaction.component = self
|
93
100
|
return transaction
|
@@ -96,7 +103,7 @@ module Puppet
|
|
96
103
|
def name
|
97
104
|
#return self[:name]
|
98
105
|
unless defined? @name
|
99
|
-
if self[:type] == self[:name]
|
106
|
+
if self[:type] == self[:name] or self[:name] =~ /--\d+$/
|
100
107
|
@name = self[:type]
|
101
108
|
else
|
102
109
|
@name = "%s[%s]" % [self[:type],self[:name]]
|
@@ -109,7 +116,7 @@ module Puppet
|
|
109
116
|
ary.each { |child|
|
110
117
|
unless child.is_a?(Puppet::Element)
|
111
118
|
self.debug "Got object of type %s" % child.class
|
112
|
-
|
119
|
+
self.devfail(
|
113
120
|
"Containers can only contain Puppet::Elements, not %s" %
|
114
121
|
child.class
|
115
122
|
)
|
@@ -123,6 +130,7 @@ module Puppet
|
|
123
130
|
@children.collect { |child|
|
124
131
|
if child.respond_to?(:refresh)
|
125
132
|
child.refresh
|
133
|
+
child.log "triggering %s" % :refresh
|
126
134
|
end
|
127
135
|
}
|
128
136
|
end
|
@@ -137,5 +145,6 @@ module Puppet
|
|
137
145
|
return "component(%s)" % self.name
|
138
146
|
end
|
139
147
|
end
|
140
|
-
end
|
141
148
|
end
|
149
|
+
|
150
|
+
# $Id: component.rb 841 2006-01-18 17:24:15Z luke $
|
data/lib/puppet/type/cron.rb
CHANGED
@@ -1,543 +1,504 @@
|
|
1
|
-
# A Puppet::Type class to manage cron jobs. Some abstraction is done,
|
2
|
-
# so that different platforms' versions of +crontab+ all work equivalently.
|
3
|
-
|
4
1
|
require 'etc'
|
5
2
|
require 'facter'
|
6
3
|
require 'puppet/type/state'
|
4
|
+
require 'puppet/filetype'
|
5
|
+
require 'puppet/type/parsedtype'
|
7
6
|
|
8
7
|
module Puppet
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
rescue ArgumentError
|
24
|
-
raise Puppet::Error, "User %s not found" % user
|
8
|
+
# Model the actual cron jobs. Supports all of the normal cron job fields
|
9
|
+
# as parameters, with the 'command' as the single state. Also requires a
|
10
|
+
# completely symbolic 'name' paremeter, which gets written to the file
|
11
|
+
# and is used to manage the job.
|
12
|
+
newtype(:cron) do
|
13
|
+
ensurable
|
14
|
+
|
15
|
+
# A base class for all of the Cron parameters, since they all have
|
16
|
+
# similar argument checking going on. We're stealing the base class
|
17
|
+
# from parsedtype, and we should probably subclass Cron from there,
|
18
|
+
# but it was just too annoying to do.
|
19
|
+
class CronParam < Puppet::State::ParsedParam
|
20
|
+
class << self
|
21
|
+
attr_accessor :boundaries
|
25
22
|
end
|
26
|
-
end
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
return "crontab"
|
24
|
+
# A method used to do parameter input handling. Converts integers
|
25
|
+
# in string form to actual integers, and returns the value if it's
|
26
|
+
# an integer or false if it's just a normal string.
|
27
|
+
def numfix(num)
|
28
|
+
if num =~ /^\d+$/
|
29
|
+
return num.to_i
|
30
|
+
elsif num.is_a?(Integer)
|
31
|
+
return num
|
37
32
|
else
|
38
|
-
return
|
33
|
+
return false
|
39
34
|
end
|
40
35
|
end
|
41
36
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
37
|
+
# Verify that a number is within the specified limits. Return the
|
38
|
+
# number if it is, or false if it is not.
|
39
|
+
def limitcheck(num, lower, upper)
|
40
|
+
if num >= lower and num <= upper
|
41
|
+
return num
|
42
|
+
else
|
43
|
+
return false
|
44
|
+
end
|
45
45
|
end
|
46
46
|
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
# Verify that a value falls within the specified array. Does case
|
48
|
+
# insensitive matching, and supports matching either the entire word
|
49
|
+
# or the first three letters of the word.
|
50
|
+
def alphacheck(value, ary)
|
51
|
+
tmp = value.downcase
|
52
|
+
|
53
|
+
# If they specified a shortened version of the name, then see
|
54
|
+
# if we can lengthen it (e.g., mon => monday).
|
55
|
+
if tmp.length == 3
|
56
|
+
ary.each_with_index { |name, index|
|
57
|
+
if name =~ /#{tmp}/i
|
58
|
+
return index
|
59
|
+
end
|
60
|
+
}
|
61
|
+
else
|
62
|
+
if ary.include?(tmp)
|
63
|
+
return ary.index(tmp)
|
64
|
+
end
|
65
|
+
end
|
51
66
|
|
52
|
-
|
53
|
-
# and the text with which to create the cron tab.
|
54
|
-
def self.write(user, text)
|
55
|
-
IO.popen("#{self.cmdbase(user)} -", "w") { |p|
|
56
|
-
p.print text
|
57
|
-
}
|
67
|
+
return false
|
58
68
|
end
|
59
|
-
end
|
60
69
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
%x{crontab -l 2>/dev/null}
|
68
|
-
}
|
70
|
+
def should_to_s
|
71
|
+
if @should.empty?
|
72
|
+
return "*"
|
73
|
+
else
|
74
|
+
return @should.join(",")
|
75
|
+
end
|
69
76
|
end
|
70
77
|
|
71
|
-
#
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
78
|
+
# The method that does all of the actual parameter value
|
79
|
+
# checking; called by all of the +param<name>=+ methods.
|
80
|
+
# Requires the value, type, and bounds, and optionally supports
|
81
|
+
# a boolean of whether to do alpha checking, and if so requires
|
82
|
+
# the ary against which to do the checking.
|
83
|
+
munge do |value|
|
84
|
+
return value unless self.class.boundaries
|
85
|
+
lower, upper = self.class.boundaries
|
86
|
+
retval = nil
|
87
|
+
if num = numfix(value)
|
88
|
+
retval = limitcheck(num, lower, upper)
|
89
|
+
elsif respond_to?(:alpha)
|
90
|
+
# If it has an alpha method defined, then we check
|
91
|
+
# to see if our value is in that list and if so we turn
|
92
|
+
# it into a number
|
93
|
+
retval = alphacheck(value, alpha())
|
94
|
+
end
|
77
95
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
}
|
85
|
-
}
|
96
|
+
if retval
|
97
|
+
return retval.to_s
|
98
|
+
else
|
99
|
+
self.fail "%s is not a valid %s" %
|
100
|
+
[value, self.class.name]
|
101
|
+
end
|
86
102
|
end
|
87
103
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
# actually change anything -- it just calls +@parent.sync+, which writes
|
93
|
-
# out the whole cron tab for the user in question. There is no real way
|
94
|
-
# to change individual cron jobs without rewriting the entire cron file.
|
104
|
+
# Somewhat uniquely, this state does not actually change anything -- it
|
105
|
+
# just calls +@parent.sync+, which writes out the whole cron tab for
|
106
|
+
# the user in question. There is no real way to change individual cron
|
107
|
+
# jobs without rewriting the entire cron file.
|
95
108
|
#
|
96
109
|
# Note that this means that managing many cron jobs for a given user
|
97
110
|
# could currently result in multiple write sessions for that user.
|
98
|
-
|
99
|
-
|
100
|
-
@doc = "The command to execute in the cron job. The environment
|
111
|
+
newstate(:command, CronParam) do
|
112
|
+
desc "The command to execute in the cron job. The environment
|
101
113
|
provided to the command varies by local system rules, and it is
|
102
114
|
best to always provide a fully qualified command. The user's
|
103
115
|
profile is not sourced when the command is run, so if the
|
104
116
|
user's environment is desired it should be sourced manually."
|
105
|
-
|
106
|
-
# Normally this would retrieve the current value, but our state is not
|
107
|
-
# actually capable of doing so. The Cron class does the actual tab
|
108
|
-
# retrieval, so all this method does is default to :notfound for @is.
|
109
|
-
def retrieve
|
110
|
-
unless defined? @is and ! @is.nil?
|
111
|
-
@is = :notfound
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Determine whether the cron job should be destroyed, and figure
|
116
|
-
# out which event to return. Finally, call @parent.sync to write the
|
117
|
-
# cron tab.
|
118
|
-
def sync
|
119
|
-
@parent.store
|
120
|
-
|
121
|
-
event = nil
|
122
|
-
if @is == :notfound
|
123
|
-
#@is = @should
|
124
|
-
event = :cron_created
|
125
|
-
elsif self.should == :notfound
|
126
|
-
@parent.remove(true)
|
127
|
-
event = :cron_deleted
|
128
|
-
elsif self.should == @is
|
129
|
-
self.err "Uh, they're both %s" % self.should
|
130
|
-
return nil
|
131
|
-
else
|
132
|
-
#@is = @should
|
133
|
-
self.err "@is is %s" % @is
|
134
|
-
event = :cron_changed
|
135
|
-
end
|
136
|
-
|
137
|
-
@parent.store
|
138
|
-
|
139
|
-
return event
|
140
|
-
end
|
141
117
|
end
|
142
|
-
end
|
143
118
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
# completely symbolic 'name' paremeter, which gets written to the file
|
148
|
-
# and is used to manage the job.
|
149
|
-
class Cron < Type
|
150
|
-
@states = [
|
151
|
-
Puppet::State::CronCommand
|
152
|
-
]
|
153
|
-
|
154
|
-
@parameters = [
|
155
|
-
:name,
|
156
|
-
:user,
|
157
|
-
:minute,
|
158
|
-
:hour,
|
159
|
-
:weekday,
|
160
|
-
:month,
|
161
|
-
:monthday
|
162
|
-
]
|
163
|
-
|
164
|
-
@paramdoc[:name] = "The symbolic name of the cron job. This name
|
165
|
-
is used for human reference only."
|
166
|
-
@paramdoc[:user] = "The user to run the command as. This user must
|
167
|
-
be allowed to run cron jobs, which is not currently checked by
|
168
|
-
Puppet."
|
169
|
-
@paramdoc[:minute] = "The minute at which to run the cron job.
|
119
|
+
newstate(:minute, CronParam) do
|
120
|
+
self.boundaries = [0, 59]
|
121
|
+
desc "The minute at which to run the cron job.
|
170
122
|
Optional; if specified, must be between 0 and 59, inclusive."
|
171
|
-
|
123
|
+
end
|
124
|
+
|
125
|
+
newstate(:hour, CronParam) do
|
126
|
+
self.boundaries = [0, 23]
|
127
|
+
desc "The hour at which to run the cron job. Optional;
|
172
128
|
if specified, must be between 0 and 23, inclusive."
|
173
|
-
|
129
|
+
end
|
130
|
+
|
131
|
+
newstate(:weekday, CronParam) do
|
132
|
+
def alpha
|
133
|
+
%w{sunday monday tuesday wednesday thursday friday saturday}
|
134
|
+
end
|
135
|
+
self.boundaries = [0, 6]
|
136
|
+
desc "The weekday on which to run the command.
|
174
137
|
Optional; if specified, must be between 0 and 6, inclusive, with
|
175
138
|
0 being Sunday, or must be the name of the day (e.g., Tuesday)."
|
176
|
-
|
139
|
+
end
|
140
|
+
|
141
|
+
newstate(:month, CronParam) do
|
142
|
+
def alpha
|
143
|
+
%w{january february march april may june july
|
144
|
+
august september october november december}
|
145
|
+
end
|
146
|
+
self.boundaries = [1, 12]
|
147
|
+
desc "The month of the year. Optional; if specified
|
177
148
|
must be between 1 and 12 or the month name (e.g., December)."
|
178
|
-
|
179
|
-
command. Optional; if specified, must be between 1 and 31."
|
149
|
+
end
|
180
150
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
a cron job that matches an existing job in every way except name,
|
187
|
-
then the jobs will be considered equivalent and the new name will
|
188
|
-
be permanently associated with that job. Once this association is
|
189
|
-
made and synced to disk, you can then manage the job normally."
|
190
|
-
@name = :cron
|
191
|
-
@namevar = :name
|
151
|
+
newstate(:monthday, CronParam) do
|
152
|
+
self.boundaries = [1, 31]
|
153
|
+
desc "The day of the month on which to run the
|
154
|
+
command. Optional; if specified, must be between 1 and 31."
|
155
|
+
end
|
192
156
|
|
193
|
-
|
157
|
+
newparam(:name) do
|
158
|
+
desc "The symbolic name of the cron job. This name
|
159
|
+
is used for human reference only and is generated
|
160
|
+
automatically for cron jobs found on the system. This generally
|
161
|
+
won't matter, as Puppet will do its best to match existing
|
162
|
+
cron jobs against specified jobs (and Puppet adds a tag to
|
163
|
+
cron jobs it adds), but it is at least possible that converting
|
164
|
+
from unmanaged jobs to managed jobs might require manual intervention."
|
194
165
|
|
195
|
-
|
166
|
+
isnamevar
|
167
|
+
end
|
196
168
|
|
197
|
-
|
169
|
+
newparam(:user) do
|
170
|
+
desc "The user to run the command as. This user must
|
171
|
+
be allowed to run cron jobs, which is not currently checked by
|
172
|
+
Puppet."
|
198
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
|
+
validate do |user|
|
177
|
+
require 'etc'
|
200
178
|
|
201
|
-
|
202
|
-
|
179
|
+
begin
|
180
|
+
obj = Etc.getpwnam(user)
|
181
|
+
parent.uid = obj.uid
|
182
|
+
rescue ArgumentError
|
183
|
+
self.fail "User %s not found" % user
|
184
|
+
end
|
203
185
|
|
204
|
-
|
205
|
-
when "SunOS":
|
206
|
-
@crontype = Puppet::CronType::SunOS
|
207
|
-
else
|
208
|
-
@crontype = Puppet::CronType::Default
|
186
|
+
user
|
209
187
|
end
|
188
|
+
end
|
210
189
|
|
211
|
-
|
212
|
-
|
213
|
-
|
190
|
+
@doc = "Installs and manages cron jobs. All fields except the command
|
191
|
+
and the user are optional, although specifying no periodic
|
192
|
+
fields would result in the command being executed every
|
193
|
+
minute. While the name of the cron job is not part of the actual
|
194
|
+
job, it is used by Puppet to store and retrieve it.
|
195
|
+
|
196
|
+
If you specify a cron job that matches an existing job in every way
|
197
|
+
except name, then the jobs will be considered equivalent and the
|
198
|
+
new name will be permanently associated with that job. Once this
|
199
|
+
association is made and synced to disk, you can then manage the job
|
200
|
+
normally (e.g., change the schedule of the job).
|
201
|
+
|
202
|
+
Example::
|
203
|
+
|
204
|
+
cron { logrotate:
|
205
|
+
command => \"/usr/sbin/logrotate\",
|
206
|
+
user => root,
|
207
|
+
hour => 2,
|
208
|
+
minute => 0
|
209
|
+
}
|
210
|
+
"
|
214
211
|
|
215
|
-
|
212
|
+
@instances = {}
|
213
|
+
@tabs = {}
|
216
214
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
215
|
+
case Facter["operatingsystem"].value
|
216
|
+
when "Solaris":
|
217
|
+
@filetype = Puppet::FileType.filetype(:suntab)
|
218
|
+
else
|
219
|
+
@filetype = Puppet::FileType.filetype(:crontab)
|
220
|
+
end
|
223
221
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
@instances = {}
|
228
|
-
@loaded = {}
|
229
|
-
@synced = {}
|
230
|
-
super
|
231
|
-
end
|
222
|
+
class << self
|
223
|
+
attr_accessor :filetype
|
224
|
+
end
|
232
225
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
226
|
+
attr_accessor :uid
|
227
|
+
|
228
|
+
# Override the Puppet::Type#[]= method so that we can store the instances
|
229
|
+
# in per-user arrays. Then just call +super+.
|
230
|
+
def self.[]=(name, object)
|
231
|
+
self.instance(object)
|
232
|
+
super
|
233
|
+
end
|
234
|
+
|
235
|
+
# In addition to removing the instances in @objects, Cron has to remove
|
236
|
+
# per-user cron tab information.
|
237
|
+
def self.clear
|
238
|
+
@instances = {}
|
239
|
+
@tabs = {}
|
240
|
+
super
|
241
|
+
end
|
242
|
+
|
243
|
+
# Override the default Puppet::Type method, because instances
|
244
|
+
# also need to be deleted from the @instances hash
|
245
|
+
def self.delete(child)
|
246
|
+
if @instances.include?(child[:user])
|
247
|
+
if @instances[child[:user]].include?(child)
|
248
|
+
@instances[child[:user]].delete(child)
|
240
249
|
end
|
241
|
-
super
|
242
250
|
end
|
251
|
+
super
|
252
|
+
end
|
243
253
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
254
|
+
# Return the fields found in the cron tab.
|
255
|
+
def self.fields
|
256
|
+
return [:minute, :hour, :monthday, :month, :weekday, :command]
|
257
|
+
end
|
248
258
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
%{#This file was autogenerated at #{Time.now} by puppet. While it
|
253
|
-
# can still be managed manually, it is definitely not recommended.
|
254
|
-
# Note particularly that the comments starting with 'Puppet Name' should
|
255
|
-
# not be deleted, as doing so could cause duplicate cron jobs.\n}
|
256
|
-
|
259
|
+
# Return the header placed at the top of each generated file, warning
|
260
|
+
# users that modifying this file manually is probably a bad idea.
|
261
|
+
def self.header
|
262
|
+
%{# HEADER This file was autogenerated at #{Time.now} by puppet. While it
|
263
|
+
# HEADER can still be managed manually, it is definitely not recommended.
|
264
|
+
# HEADER Note particularly that the comments starting with 'Puppet Name' should
|
265
|
+
# HEADER not be deleted, as doing so could cause duplicate cron jobs.\n}
|
266
|
+
end
|
257
267
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
end
|
265
|
-
else
|
266
|
-
@instances[obj[:user]] = [obj]
|
268
|
+
# Store a new instance of a cron job. Called from Cron#initialize.
|
269
|
+
def self.instance(obj)
|
270
|
+
user = obj[:user]
|
271
|
+
if @instances.include?(user)
|
272
|
+
unless @instances[obj[:user]].include?(obj)
|
273
|
+
@instances[obj[:user]] << obj
|
267
274
|
end
|
275
|
+
else
|
276
|
+
@instances[obj[:user]] = [obj]
|
268
277
|
end
|
278
|
+
end
|
269
279
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
fields().each { |param|
|
294
|
-
value = ary.shift
|
280
|
+
# Parse a user's cron job into individual cron objects.
|
281
|
+
#
|
282
|
+
# Autogenerates names for any jobs that don't already have one; these
|
283
|
+
# names will get written back to the file.
|
284
|
+
#
|
285
|
+
# This method also stores existing comments, and it stores all cron
|
286
|
+
# jobs in order, mostly so that comments are retained in the order
|
287
|
+
# they were written and in proximity to the same jobs.
|
288
|
+
def self.parse(user, text)
|
289
|
+
count = 0
|
290
|
+
hash = {}
|
291
|
+
name = nil
|
292
|
+
unless @instances.include?(user)
|
293
|
+
@instances[user] = []
|
294
|
+
end
|
295
|
+
text.chomp.split("\n").each { |line|
|
296
|
+
case line
|
297
|
+
when /^# Puppet Name: (\w+)$/: name = $1
|
298
|
+
when /^#/:
|
299
|
+
# add other comments to the list as they are
|
300
|
+
@instances[user] << line
|
301
|
+
else
|
302
|
+
if match = /^(\S+) (\S+) (\S+) (\S+) (\S+) (.+)$/.match(line)
|
303
|
+
fields().zip(match.captures).each { |param, value|
|
295
304
|
unless value == "*"
|
305
|
+
unless param == :command
|
306
|
+
if value =~ /,/
|
307
|
+
value = value.split(",")
|
308
|
+
end
|
309
|
+
end
|
296
310
|
hash[param] = value
|
297
311
|
end
|
298
312
|
}
|
299
|
-
|
300
|
-
|
301
|
-
hash[:command] += " " + ary.join(" ")
|
302
|
-
end
|
303
|
-
cron = nil
|
304
|
-
unless name
|
305
|
-
Puppet.info "Autogenerating name for %s" % hash[:command]
|
306
|
-
name = "cron-%s" % hash.object_id
|
307
|
-
end
|
308
|
-
|
309
|
-
unless hash.include?(:command)
|
310
|
-
raise Puppet::DevError, "No command for %s" % name
|
311
|
-
end
|
312
|
-
# if the cron already exists with that name...
|
313
|
-
if cron = Puppet::Type::Cron[name]
|
314
|
-
# do nothing...
|
315
|
-
elsif tmp = @instances[user].reject { |obj|
|
316
|
-
! obj.is_a?(Cron)
|
317
|
-
}.find { |obj|
|
318
|
-
obj.should(:command) == hash[:command]
|
319
|
-
}
|
320
|
-
# if we can find a cron whose spec exactly matches
|
321
|
-
|
322
|
-
# we now have a cron job whose command exactly matches
|
323
|
-
# let's see if the other fields match
|
324
|
-
txt = tmp.to_cron.sub(/#.+\n/,'')
|
325
|
-
|
326
|
-
if txt == line
|
327
|
-
cron = tmp
|
328
|
-
end
|
329
|
-
else
|
330
|
-
# create a new cron job, since no existing one
|
331
|
-
# seems to match
|
332
|
-
cron = Puppet::Type::Cron.create(
|
333
|
-
:name => name
|
334
|
-
)
|
335
|
-
end
|
336
|
-
|
337
|
-
hash.each { |param, value|
|
338
|
-
cron.is = [param, value]
|
339
|
-
}
|
340
|
-
hash.clear
|
341
|
-
name = nil
|
342
|
-
count += 1
|
313
|
+
else
|
314
|
+
raise Puppet::Error, "Could not match '%s'" % line
|
343
315
|
end
|
344
|
-
}
|
345
|
-
end
|
346
|
-
|
347
|
-
# Retrieve a given user's cron job, using the @crontype's +retrieve+
|
348
|
-
# method. Returns nil if there was no cron job; else, returns the
|
349
|
-
# number of cron instances found.
|
350
|
-
def self.retrieve(user)
|
351
|
-
#%x{crontab -u #{user} -l 2>/dev/null}.split("\n").each { |line|
|
352
|
-
text = @crontype.read(user)
|
353
|
-
if $? != 0
|
354
|
-
# there is no cron file
|
355
|
-
return nil
|
356
|
-
else
|
357
|
-
self.parse(user, text)
|
358
|
-
end
|
359
|
-
|
360
|
-
@loaded[user] = Time.now
|
361
|
-
end
|
362
316
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
@crontype.write(user, self.header + self.tab(user))
|
369
|
-
@synced[user] = Time.now
|
370
|
-
else
|
371
|
-
Puppet.notice "No cron instances for %s" % user
|
372
|
-
end
|
373
|
-
end
|
317
|
+
cron = nil
|
318
|
+
unless name
|
319
|
+
Puppet.info "Autogenerating name for %s" % hash[:command]
|
320
|
+
name = "cron-%s" % hash.object_id
|
321
|
+
end
|
374
322
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
323
|
+
unless hash.include?(:command)
|
324
|
+
raise Puppet::DevError, "No command for %s" % name
|
325
|
+
end
|
326
|
+
# if the cron already exists with that name...
|
327
|
+
if cron = Puppet.type(:cron)[name]
|
328
|
+
# Mark the cron job as present
|
329
|
+
cron.is = [:ensure, :present]
|
330
|
+
elsif tmp = @instances[user].reject { |obj|
|
331
|
+
! obj.is_a?(self)
|
332
|
+
}.find { |obj|
|
333
|
+
obj.should(:command) == hash[:command]
|
334
|
+
}
|
335
|
+
# if we can find a cron whose spec exactly matches
|
336
|
+
|
337
|
+
# we now have a cron job whose command exactly matches
|
338
|
+
# let's see if the other fields match
|
339
|
+
txt = tmp.to_record.sub(/#.+\n/,'')
|
340
|
+
|
341
|
+
if txt == line
|
342
|
+
cron = tmp
|
384
343
|
end
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
# be used for reducing writes, but currently is not.
|
393
|
-
def self.loaded?(user)
|
394
|
-
if @loaded.include?(user)
|
395
|
-
return @loaded[user]
|
396
|
-
else
|
397
|
-
return nil
|
398
|
-
end
|
399
|
-
end
|
344
|
+
else
|
345
|
+
# create a new cron job, since no existing one
|
346
|
+
# seems to match
|
347
|
+
cron = self.create(
|
348
|
+
:name => name
|
349
|
+
)
|
350
|
+
end
|
400
351
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
elsif num.is_a?(Integer)
|
408
|
-
return num
|
409
|
-
else
|
410
|
-
return false
|
352
|
+
hash.each { |param, value|
|
353
|
+
cron.is = [param, value]
|
354
|
+
}
|
355
|
+
hash.clear
|
356
|
+
name = nil
|
357
|
+
count += 1
|
411
358
|
end
|
412
|
-
|
359
|
+
}
|
360
|
+
end
|
413
361
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
362
|
+
# Retrieve a given user's cron job, using the @filetype's +retrieve+
|
363
|
+
# method. Returns nil if there was no cron job; else, returns the
|
364
|
+
# number of cron instances found.
|
365
|
+
def self.retrieve(user)
|
366
|
+
@tabs[user] ||= @filetype.new(user)
|
367
|
+
text = @tabs[user].read
|
368
|
+
if $? != 0
|
369
|
+
# there is no cron file
|
370
|
+
return nil
|
371
|
+
else
|
372
|
+
# Preemptively mark everything absent, so that retrieving it
|
373
|
+
# can mark it present again.
|
374
|
+
self.find_all { |obj|
|
375
|
+
obj[:user] == user
|
376
|
+
}.each { |obj|
|
377
|
+
obj.each { |state|
|
378
|
+
state.is = :absent
|
379
|
+
}
|
380
|
+
}
|
381
|
+
self.parse(user, text)
|
422
382
|
end
|
383
|
+
end
|
423
384
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
if tmp.length == 3
|
430
|
-
ary.each_with_index { |name, index|
|
431
|
-
if name =~ /#{tmp}/i
|
432
|
-
return index
|
433
|
-
end
|
434
|
-
}
|
435
|
-
else
|
436
|
-
if ary.include?(tmp)
|
437
|
-
return ary.index(tmp)
|
438
|
-
end
|
439
|
-
end
|
385
|
+
# Remove a user's cron tab.
|
386
|
+
def self.remove(user)
|
387
|
+
@tabs[user] ||= @filetype.new(user)
|
388
|
+
@tabs[user].remove
|
389
|
+
end
|
440
390
|
|
441
|
-
|
391
|
+
# Store the user's cron tab. Collects the text of the new tab and
|
392
|
+
# sends it to the +@filetype+ module's +write+ function. Also adds
|
393
|
+
# header warning users not to modify the file directly.
|
394
|
+
def self.store(user)
|
395
|
+
@tabs[user] ||= @filetype.new(user)
|
396
|
+
if @instances.include?(user)
|
397
|
+
@tabs[user].write(self.tab(user))
|
398
|
+
else
|
399
|
+
Puppet.notice "No cron instances for %s" % user
|
442
400
|
end
|
401
|
+
end
|
443
402
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
if
|
451
|
-
|
403
|
+
# Collect all Cron instances for a given user and convert them
|
404
|
+
# into literal text.
|
405
|
+
def self.tab(user)
|
406
|
+
Puppet.info "writing cron tab for %s" % user
|
407
|
+
if @instances.include?(user)
|
408
|
+
return self.header() + @instances[user].reject { |obj|
|
409
|
+
if obj.is_a?(self) and obj.should(:ensure) == :absent
|
410
|
+
#obj.log "now absent"
|
411
|
+
#obj.is = [:ensure, :absent]
|
412
|
+
true
|
452
413
|
else
|
453
|
-
|
414
|
+
false
|
454
415
|
end
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
retval = nil
|
459
|
-
if num = numfix(value)
|
460
|
-
retval = limitcheck(num, lower, upper)
|
461
|
-
elsif alpha
|
462
|
-
retval = alphacheck(value, ary)
|
463
|
-
end
|
464
|
-
|
465
|
-
if retval
|
466
|
-
@parameters[type] = retval
|
416
|
+
}.collect { |obj|
|
417
|
+
if obj.is_a? self
|
418
|
+
obj.to_record
|
467
419
|
else
|
468
|
-
|
469
|
-
[value, type]
|
420
|
+
obj.to_s
|
470
421
|
end
|
471
|
-
}
|
472
|
-
end
|
422
|
+
}.join("\n") + "\n"
|
473
423
|
|
474
|
-
|
475
|
-
|
424
|
+
else
|
425
|
+
Puppet.notice "No cron instances for %s" % user
|
476
426
|
end
|
427
|
+
end
|
477
428
|
|
478
|
-
|
479
|
-
|
480
|
-
|
429
|
+
# Return the tab object itself. Pretty much just used for testing.
|
430
|
+
def self.tabobj(user)
|
431
|
+
@tabs[user]
|
432
|
+
end
|
481
433
|
|
482
|
-
|
483
|
-
|
434
|
+
# Return the last time a given user's cron tab was loaded. Could
|
435
|
+
# be used for reducing writes, but currently is not.
|
436
|
+
def self.loaded?(user)
|
437
|
+
if @tabs.include?(user)
|
438
|
+
return @loaded[user].loaded
|
439
|
+
else
|
440
|
+
return nil
|
484
441
|
end
|
442
|
+
end
|
485
443
|
|
486
|
-
|
487
|
-
|
488
|
-
|
444
|
+
def create
|
445
|
+
# nothing
|
446
|
+
self.info "creating"
|
447
|
+
self.store
|
448
|
+
end
|
489
449
|
|
490
|
-
|
491
|
-
|
492
|
-
|
450
|
+
def destroy
|
451
|
+
# nothing, since the 'Cron.tab' method just doesn't write out
|
452
|
+
# crons whose 'ensure' states are set to 'absent'.
|
453
|
+
#@states.each { |n, state|
|
454
|
+
# next if n == :ensure
|
455
|
+
# state.should == :absent
|
456
|
+
#}
|
457
|
+
self.store
|
458
|
+
end
|
493
459
|
|
494
|
-
|
495
|
-
|
460
|
+
def exists?
|
461
|
+
val = false
|
462
|
+
if @states.include?(:command) and @states[:command].is != :absent
|
463
|
+
val = true
|
464
|
+
end
|
465
|
+
return val
|
466
|
+
end
|
496
467
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
end
|
503
|
-
@parameters[:user] = user
|
468
|
+
# Override the default Puppet::Type method because we need to call
|
469
|
+
# the +@filetype+ retrieve method.
|
470
|
+
def retrieve
|
471
|
+
unless @parameters.include?(:user)
|
472
|
+
self.fail "You must specify the cron user"
|
504
473
|
end
|
505
474
|
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
unless @parameters.include?(:user)
|
510
|
-
raise Puppet::Error, "You must specify the cron user"
|
511
|
-
end
|
475
|
+
self.class.retrieve(self[:user])
|
476
|
+
self.eachstate { |st| st.retrieve }
|
477
|
+
end
|
512
478
|
|
513
|
-
|
514
|
-
|
515
|
-
|
479
|
+
# Write the entire user's cron tab out.
|
480
|
+
def store
|
481
|
+
self.class.store(self[:user])
|
482
|
+
end
|
516
483
|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
484
|
+
# Convert the current object a cron-style string. Adds the cron name
|
485
|
+
# as a comment above the cron job, in the form '# Puppet Name: <name>'.
|
486
|
+
def to_record
|
487
|
+
hash = {:command => @states[:command].should || @states[:command].is }
|
521
488
|
|
522
|
-
#
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
}
|
489
|
+
# Collect all of the values that we have
|
490
|
+
self.class.fields().reject { |f| f == :command }.each { |param|
|
491
|
+
if @states.include?(param)
|
492
|
+
hash[param] = @states[param].should_to_s
|
493
|
+
end
|
494
|
+
}
|
529
495
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
else
|
535
|
-
hash[f]
|
536
|
-
end
|
537
|
-
}.join(" ")
|
538
|
-
end
|
496
|
+
return "# Puppet Name: %s\n" % self.name +
|
497
|
+
self.class.fields.collect { |f|
|
498
|
+
hash[f] || "*"
|
499
|
+
}.join(" ")
|
539
500
|
end
|
540
501
|
end
|
541
502
|
end
|
542
503
|
|
543
|
-
# $Id: cron.rb
|
504
|
+
# $Id: cron.rb 841 2006-01-18 17:24:15Z luke $
|