chef 0.9.8 → 0.9.10.rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +1 -1
- data/distro/common/man/man8/knife.8 +89 -79
- data/distro/common/markdown/knife.mkd +7 -0
- data/distro/debian/etc/default/chef-server +3 -0
- data/distro/debian/etc/default/chef-server-webui +3 -0
- data/distro/debian/etc/default/chef-solr +3 -0
- data/distro/debian/etc/default/chef-solr-indexer +3 -0
- data/distro/debian/etc/init.d/chef-server +3 -1
- data/distro/debian/etc/init.d/chef-server-webui +3 -1
- data/distro/redhat/etc/init.d/chef-client +1 -1
- data/lib/chef/application.rb +2 -0
- data/lib/chef/application/client.rb +5 -3
- data/lib/chef/application/knife.rb +16 -5
- data/lib/chef/application/solo.rb +0 -1
- data/lib/chef/checksum.rb +65 -1
- data/lib/chef/checksum_cache.rb +173 -0
- data/lib/chef/client.rb +84 -121
- data/lib/chef/cookbook/remote_file_vendor.rb +10 -3
- data/lib/chef/cookbook/syntax_check.rb +2 -2
- data/lib/chef/cookbook_loader.rb +2 -0
- data/lib/chef/cookbook_site_streaming_uploader.rb +29 -0
- data/lib/chef/cookbook_uploader.rb +8 -7
- data/lib/chef/cookbook_version.rb +155 -114
- data/lib/chef/exceptions.rb +5 -0
- data/lib/chef/handler.rb +43 -0
- data/lib/chef/index_queue/consumer.rb +1 -1
- data/lib/chef/index_queue/indexable.rb +1 -1
- data/lib/chef/knife.rb +18 -5
- data/lib/chef/knife/bootstrap.rb +2 -2
- data/lib/chef/knife/bootstrap/archlinux-gems.erb +44 -0
- data/lib/chef/knife/bootstrap/client-install.vbs +80 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
- data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -7
- data/lib/chef/knife/bootstrap/windows-gems.erb +34 -0
- data/lib/chef/knife/configure_client.rb +4 -2
- data/lib/chef/knife/cookbook_metadata.rb +1 -1
- data/lib/chef/knife/cookbook_site_share.rb +2 -1
- data/lib/chef/knife/cookbook_site_vendor.rb +6 -0
- data/lib/chef/knife/cookbook_test.rb +1 -1
- data/lib/chef/knife/ec2_server_create.rb +51 -26
- data/lib/chef/knife/exec.rb +52 -0
- data/lib/chef/knife/ssh.rb +27 -15
- data/lib/chef/knife/status.rb +27 -10
- data/lib/chef/knife/windows_bootstrap.rb +154 -0
- data/lib/chef/mixin/checksum.rb +2 -2
- data/lib/chef/mixin/xml_escape.rb +75 -49
- data/lib/chef/node.rb +54 -58
- data/lib/chef/node/attribute.rb +61 -53
- data/lib/chef/platform.rb +19 -2
- data/lib/chef/provider/breakpoint.rb +1 -1
- data/lib/chef/provider/cookbook_file.rb +3 -3
- data/lib/chef/provider/cron.rb +3 -3
- data/lib/chef/provider/cron/solaris.rb +195 -0
- data/lib/chef/provider/deploy.rb +3 -3
- data/lib/chef/provider/directory.rb +2 -2
- data/lib/chef/provider/env.rb +5 -5
- data/lib/chef/provider/execute.rb +1 -1
- data/lib/chef/provider/file.rb +10 -9
- data/lib/chef/provider/git.rb +12 -4
- data/lib/chef/provider/group.rb +5 -5
- data/lib/chef/provider/http_request.rb +25 -9
- data/lib/chef/provider/ifconfig.rb +2 -2
- data/lib/chef/provider/link.rb +11 -6
- data/lib/chef/provider/log.rb +1 -0
- data/lib/chef/provider/mdadm.rb +3 -3
- data/lib/chef/provider/mount.rb +5 -5
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/ohai.rb +41 -0
- data/lib/chef/provider/package.rb +5 -5
- data/lib/chef/provider/package/yum-dump.py +5 -2
- data/lib/chef/provider/remote_directory.rb +11 -5
- data/lib/chef/provider/remote_file.rb +2 -2
- data/lib/chef/provider/route.rb +154 -133
- data/lib/chef/provider/ruby_block.rb +1 -1
- data/lib/chef/provider/service.rb +6 -6
- data/lib/chef/provider/subversion.rb +12 -9
- data/lib/chef/provider/template.rb +2 -2
- data/lib/chef/provider/user.rb +7 -7
- data/lib/chef/provider/user/useradd.rb +15 -1
- data/lib/chef/providers.rb +2 -0
- data/lib/chef/resource.rb +164 -58
- data/lib/chef/resource/http_request.rb +9 -0
- data/lib/chef/resource/ohai.rb +40 -0
- data/lib/chef/resource/remote_directory.rb +10 -1
- data/lib/chef/resource/rpm_package.rb +34 -0
- data/lib/chef/resource_collection.rb +3 -2
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/rest.rb +13 -7
- data/lib/chef/rest/auth_credentials.rb +1 -1
- data/lib/chef/rest/rest_request.rb +3 -1
- data/lib/chef/runner.rb +31 -55
- data/lib/chef/shef/shef_session.rb +1 -1
- data/lib/chef/util/windows/net_use.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/webui_user.rb +0 -1
- metadata +38 -19
- data/lib/chef/cache.rb +0 -61
- data/lib/chef/cache/checksum.rb +0 -91
data/lib/chef/node/attribute.rb
CHANGED
@@ -29,14 +29,12 @@ class Chef
|
|
29
29
|
:default,
|
30
30
|
:override,
|
31
31
|
:automatic,
|
32
|
-
:state,
|
33
32
|
:current_normal,
|
34
33
|
:current_default,
|
35
34
|
:current_override,
|
36
35
|
:current_automatic,
|
37
36
|
:auto_vivifiy_on_read,
|
38
37
|
:set_unless_value_present,
|
39
|
-
:has_been_read,
|
40
38
|
:set_type
|
41
39
|
|
42
40
|
include Enumerable
|
@@ -50,7 +48,7 @@ class Chef
|
|
50
48
|
@current_override = override
|
51
49
|
@automatic = automatic
|
52
50
|
@current_automatic = automatic
|
53
|
-
@
|
51
|
+
@current_nesting_level = state
|
54
52
|
@auto_vivifiy_on_read = false
|
55
53
|
@set_unless_value_present = false
|
56
54
|
@set_type = nil
|
@@ -78,18 +76,18 @@ class Chef
|
|
78
76
|
end
|
79
77
|
end
|
80
78
|
|
81
|
-
# Reset our internal
|
79
|
+
# Reset our internal current_nesting_level to the top of every tree
|
82
80
|
def reset
|
83
81
|
@current_normal = @normal
|
84
82
|
@current_default = @default
|
85
83
|
@current_override = @override
|
86
84
|
@current_automatic = @automatic
|
87
85
|
@has_been_read = false
|
88
|
-
@
|
86
|
+
@current_nesting_level = []
|
89
87
|
end
|
90
88
|
|
91
89
|
def [](key)
|
92
|
-
@
|
90
|
+
@current_nesting_level << key
|
93
91
|
|
94
92
|
# We set this to so that we can cope with ||= as a setting.
|
95
93
|
# See the comments in []= for more details.
|
@@ -114,21 +112,18 @@ class Chef
|
|
114
112
|
end
|
115
113
|
end
|
116
114
|
|
117
|
-
def attribute?(key)
|
118
|
-
return true if get_value(automatic, key)
|
119
|
-
return true if get_value(override, key)
|
120
|
-
return true if get_value(normal, key)
|
121
|
-
return true if get_value(default, key)
|
122
|
-
false
|
123
|
-
end
|
124
|
-
|
125
115
|
def has_key?(key)
|
126
|
-
|
116
|
+
return true if component_has_key?(@default,key)
|
117
|
+
return true if component_has_key?(@automatic,key)
|
118
|
+
return true if component_has_key?(@normal,key)
|
119
|
+
return true if component_has_key?(@override,key)
|
120
|
+
false
|
127
121
|
end
|
128
122
|
|
129
|
-
alias :
|
130
|
-
alias :
|
131
|
-
alias :
|
123
|
+
alias :attribute? :has_key?
|
124
|
+
alias :include? :has_key?
|
125
|
+
alias :key? :has_key?
|
126
|
+
alias :member? :has_key?
|
132
127
|
|
133
128
|
def each(&block)
|
134
129
|
get_keys.each do |key|
|
@@ -263,7 +258,7 @@ class Chef
|
|
263
258
|
def get_value(data_hash, key)
|
264
259
|
last = nil
|
265
260
|
|
266
|
-
if
|
261
|
+
if @current_nesting_level.length == 0
|
267
262
|
if data_hash.has_key?(key) && ! data_hash[key].nil?
|
268
263
|
return data_hash[key]
|
269
264
|
else
|
@@ -271,18 +266,18 @@ class Chef
|
|
271
266
|
end
|
272
267
|
end
|
273
268
|
|
274
|
-
0.upto(
|
269
|
+
0.upto(@current_nesting_level.length) do |i|
|
275
270
|
if i == 0
|
276
|
-
last = auto_vivifiy(data_hash,
|
277
|
-
elsif i ==
|
278
|
-
fk = last[
|
271
|
+
last = auto_vivifiy(data_hash, @current_nesting_level[i])
|
272
|
+
elsif i == @current_nesting_level.length
|
273
|
+
fk = last[@current_nesting_level[i - 1]]
|
279
274
|
if fk.has_key?(key) && ! fk[key].nil?
|
280
275
|
return fk[key]
|
281
276
|
else
|
282
277
|
return nil
|
283
278
|
end
|
284
279
|
else
|
285
|
-
last = auto_vivifiy(last[
|
280
|
+
last = auto_vivifiy(last[@current_nesting_level[i - 1]], @current_nesting_level[i])
|
286
281
|
end
|
287
282
|
end
|
288
283
|
end
|
@@ -327,7 +322,7 @@ class Chef
|
|
327
322
|
|
328
323
|
if set_unless_value_present
|
329
324
|
if get_value(set_type_hash, key) != nil
|
330
|
-
Chef::Log.debug("Not setting #{
|
325
|
+
Chef::Log.debug("Not setting #{@current_nesting_level.join("/")}/#{key} to #{value.inspect} because it has a #{@set_type} value already")
|
331
326
|
return false
|
332
327
|
end
|
333
328
|
end
|
@@ -338,7 +333,7 @@ class Chef
|
|
338
333
|
#
|
339
334
|
# In practice, these objects are single use - this is just
|
340
335
|
# supporting one more single-use style.
|
341
|
-
@
|
336
|
+
@current_nesting_level.pop if @has_been_read && @current_nesting_level.last == key
|
342
337
|
|
343
338
|
set_value(set_type_hash, key, value)
|
344
339
|
value
|
@@ -347,23 +342,23 @@ class Chef
|
|
347
342
|
def set_value(data_hash, key, value)
|
348
343
|
last = nil
|
349
344
|
|
350
|
-
# If there is no
|
351
|
-
if
|
345
|
+
# If there is no current_nesting_level, just set the value
|
346
|
+
if @current_nesting_level.length == 0
|
352
347
|
data_hash[key] = value
|
353
348
|
return data_hash
|
354
349
|
end
|
355
350
|
|
356
351
|
# Walk all the previous places we have been
|
357
|
-
0.upto(
|
352
|
+
0.upto(@current_nesting_level.length) do |i|
|
358
353
|
# If we are the first, we are top level, and should vivifiy the data_hash
|
359
354
|
if i == 0
|
360
|
-
last = auto_vivifiy(data_hash,
|
361
|
-
# If we are one past the last
|
362
|
-
elsif i ==
|
363
|
-
last[
|
355
|
+
last = auto_vivifiy(data_hash, @current_nesting_level[i])
|
356
|
+
# If we are one past the last current_nesting_level, we are adding a key to that hash with a value
|
357
|
+
elsif i == @current_nesting_level.length
|
358
|
+
last[@current_nesting_level[i - 1]][key] = value
|
364
359
|
# Otherwise, we're auto-vivifiy-ing an interim mash
|
365
360
|
else
|
366
|
-
last = auto_vivifiy(last[
|
361
|
+
last = auto_vivifiy(last[@current_nesting_level[i - 1]], @current_nesting_level[i])
|
367
362
|
end
|
368
363
|
end
|
369
364
|
data_hash
|
@@ -372,7 +367,7 @@ class Chef
|
|
372
367
|
def auto_vivifiy(data_hash, key)
|
373
368
|
if data_hash.has_key?(key)
|
374
369
|
unless data_hash[key].respond_to?(:has_key?)
|
375
|
-
raise ArgumentError, "You tried to set a nested key, where the parent is not a hash-like object: #{@
|
370
|
+
raise ArgumentError, "You tried to set a nested key, where the parent is not a hash-like object: #{@current_nesting_level.join("/")}/#{key} " unless auto_vivifiy_on_read
|
376
371
|
end
|
377
372
|
else
|
378
373
|
data_hash[key] = Mash.new
|
@@ -390,7 +385,7 @@ class Chef
|
|
390
385
|
end
|
391
386
|
|
392
387
|
if data_hash[key].respond_to?(:has_key?)
|
393
|
-
cna = Chef::Node::Attribute.new(@normal, @default, @override, @automatic, @
|
388
|
+
cna = Chef::Node::Attribute.new(@normal, @default, @override, @automatic, @current_nesting_level)
|
394
389
|
cna.current_normal = current_normal.nil? ? Mash.new : current_normal[key]
|
395
390
|
cna.current_default = current_default.nil? ? Mash.new : current_default[key]
|
396
391
|
cna.current_override = current_override.nil? ? Mash.new : current_override[key]
|
@@ -404,27 +399,30 @@ class Chef
|
|
404
399
|
end
|
405
400
|
end
|
406
401
|
|
402
|
+
# Fetches or sets the value, depending on if any arguments are given.
|
403
|
+
# ==== Fetching
|
404
|
+
# If no arguments are given, fetches the value:
|
405
|
+
# node.network
|
406
|
+
# => {network data}
|
407
|
+
# Getters will find either a string or symbol key.
|
408
|
+
# ==== Setting
|
409
|
+
# If arguments are given, a value will be set. Both normal setter and DSL
|
410
|
+
# style setters are allowed:
|
411
|
+
# node.foo = "bar"
|
412
|
+
# node.foo("bar")
|
413
|
+
# Both set node[:foo] = "bar"
|
407
414
|
def method_missing(symbol, *args)
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
else
|
414
|
-
if args.length != 0
|
415
|
-
by = symbol
|
415
|
+
if args.empty?
|
416
|
+
if key?(symbol)
|
417
|
+
self[symbol]
|
418
|
+
elsif key?(symbol.to_s)
|
419
|
+
self[symbol.to_s]
|
416
420
|
else
|
417
|
-
raise ArgumentError, "Attribute #{symbol
|
421
|
+
raise ArgumentError, "Attribute #{symbol} is not defined!" unless auto_vivifiy_on_read
|
418
422
|
end
|
419
|
-
end
|
420
|
-
|
421
|
-
if args.length != 0
|
422
|
-
if by.to_s =~ /^(.+)=$/
|
423
|
-
by = $1
|
424
|
-
end
|
425
|
-
self[by] = args.length == 1 ? args[0] : args
|
426
423
|
else
|
427
|
-
|
424
|
+
key_to_set = symbol.to_s[/^(.+)=$/, 1] || symbol
|
425
|
+
self[key_to_set] = (args.length == 1 ? args[0] : args)
|
428
426
|
end
|
429
427
|
end
|
430
428
|
|
@@ -445,6 +443,16 @@ class Chef
|
|
445
443
|
end
|
446
444
|
end
|
447
445
|
|
446
|
+
def component_has_key?(component_attrs,key)
|
447
|
+
# get the Hash-like object at the current nesting level:
|
448
|
+
nested_attrs = @current_nesting_level.inject(component_attrs) do |subtree, intermediate_key|
|
449
|
+
# if the intermediate value isn't a hash or doesn't have the intermediate key,
|
450
|
+
# it can't have the bottom-level key we're looking for.
|
451
|
+
(subtree.respond_to?(:key?) && subtree[intermediate_key]) or (return false)
|
452
|
+
end
|
453
|
+
nested_attrs.respond_to?(:key?) && nested_attrs.key?(key)
|
454
|
+
end
|
455
|
+
|
448
456
|
end
|
449
457
|
end
|
450
458
|
end
|
data/lib/chef/platform.rb
CHANGED
@@ -80,6 +80,22 @@ class Chef
|
|
80
80
|
:mdadm => Chef::Provider::Mdadm
|
81
81
|
}
|
82
82
|
},
|
83
|
+
:amazon => {
|
84
|
+
:default => {
|
85
|
+
:service => Chef::Provider::Service::Redhat,
|
86
|
+
:cron => Chef::Provider::Cron,
|
87
|
+
:package => Chef::Provider::Package::Yum,
|
88
|
+
:mdadm => Chef::Provider::Mdadm
|
89
|
+
}
|
90
|
+
},
|
91
|
+
:scientific => {
|
92
|
+
:default => {
|
93
|
+
:service => Chef::Provider::Service::Redhat,
|
94
|
+
:cron => Chef::Provider::Cron,
|
95
|
+
:package => Chef::Provider::Package::Yum,
|
96
|
+
:mdadm => Chef::Provider::Mdadm
|
97
|
+
}
|
98
|
+
},
|
83
99
|
:fedora => {
|
84
100
|
:default => {
|
85
101
|
:service => Chef::Provider::Service::Redhat,
|
@@ -150,8 +166,9 @@ class Chef
|
|
150
166
|
:solaris2 => {
|
151
167
|
:default => {
|
152
168
|
:service => Chef::Provider::Service::Solaris,
|
153
|
-
|
154
|
-
|
169
|
+
:package => Chef::Provider::Package::Solaris,
|
170
|
+
:cron => Chef::Provider::Cron::Solaris,
|
171
|
+
:group => Chef::Provider::Group::Usermod
|
155
172
|
}
|
156
173
|
},
|
157
174
|
:default => {
|
@@ -42,11 +42,11 @@ class Chef
|
|
42
42
|
stage_file_to_tmpdir(staging_file.path)
|
43
43
|
FileUtils.mv(staging_file.path, @new_resource.path)
|
44
44
|
end
|
45
|
-
@new_resource.
|
45
|
+
@new_resource.updated_by_last_action(true)
|
46
46
|
else
|
47
47
|
set_all_access_controls(@new_resource.path)
|
48
48
|
end
|
49
|
-
@new_resource.
|
49
|
+
@new_resource.updated_by_last_action(true)
|
50
50
|
end
|
51
51
|
|
52
52
|
def action_create_if_missing
|
@@ -81,7 +81,7 @@ class Chef
|
|
81
81
|
def set_all_access_controls(file)
|
82
82
|
access_controls = Chef::FileAccessControl.new(@new_resource, file)
|
83
83
|
access_controls.set_all
|
84
|
-
@new_resource.
|
84
|
+
@new_resource.updated_by_last_action(access_controls.modified?)
|
85
85
|
end
|
86
86
|
|
87
87
|
def backup_new_resource
|
data/lib/chef/provider/cron.rb
CHANGED
@@ -133,7 +133,7 @@ class Chef
|
|
133
133
|
crontab.each_line { |line| stdin.puts "#{line}" }
|
134
134
|
end
|
135
135
|
Chef::Log.info("Updated cron '#{@new_resource.name}'")
|
136
|
-
@new_resource.
|
136
|
+
@new_resource.updated_by_last_action(true)
|
137
137
|
else
|
138
138
|
unless @cron_empty
|
139
139
|
status = popen4("crontab -l -u #{@new_resource.user}") do |pid, stdin, stdout, stderr|
|
@@ -147,7 +147,7 @@ class Chef
|
|
147
147
|
crontab.each_line { |line| stdin.puts "#{line}" }
|
148
148
|
end
|
149
149
|
Chef::Log.info("Added cron '#{@new_resource.name}'")
|
150
|
-
@new_resource.
|
150
|
+
@new_resource.updated_by_last_action(true)
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
@@ -177,7 +177,7 @@ class Chef
|
|
177
177
|
crontab.each_line { |line| stdin.puts "#{line}" }
|
178
178
|
end
|
179
179
|
Chef::Log.debug("Deleted cron '#{@new_resource.name}'")
|
180
|
-
@new_resource.
|
180
|
+
@new_resource.updated_by_last_action(true)
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
@@ -0,0 +1,195 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Bryan McLellan (btm@loftninjas.org)
|
3
|
+
# Author:: Toomas Pelberg (toomasp@gmx.net)
|
4
|
+
# Copyright:: Copyright (c) 2009 Bryan McLellan
|
5
|
+
# Copyright:: Copyright (c) 2010 Toomas Pelberg
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'chef/log'
|
22
|
+
require 'chef/mixin/command'
|
23
|
+
require 'chef/provider'
|
24
|
+
|
25
|
+
class Chef
|
26
|
+
class Provider
|
27
|
+
class Cron
|
28
|
+
class Solaris < Chef::Provider::Cron
|
29
|
+
include Chef::Mixin::Command
|
30
|
+
|
31
|
+
CRON_PATTERN = /([-0-9*,\/]+)\s([-0-9*,\/]+)\s([-0-9*,\/]+)\s([-0-9*,\/]+)\s([-0-9*,\/]+)\s(.*)/
|
32
|
+
|
33
|
+
def initialize(new_resource, run_context)
|
34
|
+
super(new_resource, run_context)
|
35
|
+
@cron_exists = false
|
36
|
+
@cron_empty = false
|
37
|
+
end
|
38
|
+
attr_accessor :cron_exists, :cron_empty
|
39
|
+
|
40
|
+
def load_current_resource
|
41
|
+
crontab_lines = []
|
42
|
+
@current_resource = Chef::Resource::Cron.new(@new_resource.name)
|
43
|
+
@current_resource.user(@new_resource.user)
|
44
|
+
status = popen4("crontab -l #{@new_resource.user}") do |pid, stdin, stdout, stderr|
|
45
|
+
stdout.each_line { |line| crontab_lines << line }
|
46
|
+
end
|
47
|
+
if status.exitstatus > 1
|
48
|
+
raise Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: #{status.exitstatus}"
|
49
|
+
elsif status.exitstatus == 0
|
50
|
+
cron_found = false
|
51
|
+
crontab_lines.each do |line|
|
52
|
+
case line.chomp
|
53
|
+
when "# Chef Name: #{@new_resource.name}"
|
54
|
+
Chef::Log.debug("Found cron '#{@new_resource.name}'")
|
55
|
+
cron_found = true
|
56
|
+
@cron_exists = true
|
57
|
+
next
|
58
|
+
when /^MAILTO=(\S*)/
|
59
|
+
@current_resource.mailto($1) if cron_found
|
60
|
+
next
|
61
|
+
when /^PATH=(\S*)/
|
62
|
+
@current_resource.path($1) if cron_found
|
63
|
+
next
|
64
|
+
when /^SHELL=(\S*)/
|
65
|
+
@current_resource.shell($1) if cron_found
|
66
|
+
next
|
67
|
+
when /^HOME=(\S*)/
|
68
|
+
@current_resource.home($1) if cron_found
|
69
|
+
next
|
70
|
+
when CRON_PATTERN
|
71
|
+
if cron_found
|
72
|
+
@current_resource.minute($1)
|
73
|
+
@current_resource.hour($2)
|
74
|
+
@current_resource.day($3)
|
75
|
+
@current_resource.month($4)
|
76
|
+
@current_resource.weekday($5)
|
77
|
+
@current_resource.command($6)
|
78
|
+
cron_found=false
|
79
|
+
end
|
80
|
+
next
|
81
|
+
else
|
82
|
+
next
|
83
|
+
end
|
84
|
+
end
|
85
|
+
Chef::Log.debug("Cron '#{@new_resource.name}' not found") unless @cron_exists
|
86
|
+
elsif status.exitstatus == 1
|
87
|
+
Chef::Log.debug("Cron empty for '#{@new_resource.user}'")
|
88
|
+
@cron_empty = true
|
89
|
+
end
|
90
|
+
|
91
|
+
@current_resource
|
92
|
+
end
|
93
|
+
|
94
|
+
def compare_cron
|
95
|
+
[ :minute, :hour, :day, :month, :weekday, :command, :mailto, :path, :shell, :home ].any? do |cron_var|
|
96
|
+
!@new_resource.send(cron_var).nil? && @new_resource.send(cron_var) != @current_resource.send(cron_var)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def write_crontab(crontab)
|
101
|
+
tempcron = Tempfile.new("chef-cron")
|
102
|
+
tempcron << crontab
|
103
|
+
tempcron.flush
|
104
|
+
tempcron.chmod(0644)
|
105
|
+
status = run_command(:command => "/usr/bin/crontab #{tempcron.path}",:user => @new_resource.user)
|
106
|
+
if(status == 0)
|
107
|
+
@new_resource.updated_by_last_action(true)
|
108
|
+
else
|
109
|
+
@new_resource.updated_by_last_action(false)
|
110
|
+
end
|
111
|
+
tempcron.close!
|
112
|
+
return status
|
113
|
+
end
|
114
|
+
|
115
|
+
def action_create
|
116
|
+
crontab = String.new
|
117
|
+
newcron = String.new
|
118
|
+
cron_found = false
|
119
|
+
|
120
|
+
newcron << "# Chef Name: #{new_resource.name}\n"
|
121
|
+
[ :mailto, :path, :shell, :home ].each do |v|
|
122
|
+
newcron << "#{v.to_s.upcase}=#{@new_resource.send(v)}\n" if @new_resource.send(v)
|
123
|
+
end
|
124
|
+
newcron << "#{@new_resource.minute} #{@new_resource.hour} #{@new_resource.day} #{@new_resource.month} #{@new_resource.weekday} #{@new_resource.command}\n"
|
125
|
+
|
126
|
+
if @cron_exists
|
127
|
+
unless compare_cron
|
128
|
+
Chef::Log.debug("Skipping existing cron entry '#{@new_resource.name}'")
|
129
|
+
return
|
130
|
+
end
|
131
|
+
status = popen4("crontab -l #{@new_resource.user}") do |pid, stdin, stdout, stderr|
|
132
|
+
stdout.each_line do |line|
|
133
|
+
case line.chomp
|
134
|
+
when "# Chef Name: #{@new_resource.name}"
|
135
|
+
cron_found = true
|
136
|
+
next
|
137
|
+
when CRON_PATTERN
|
138
|
+
if cron_found
|
139
|
+
cron_found = false
|
140
|
+
crontab << newcron
|
141
|
+
next
|
142
|
+
end
|
143
|
+
else
|
144
|
+
next if cron_found
|
145
|
+
end
|
146
|
+
crontab << line
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
status = write_crontab(crontab)
|
151
|
+
Chef::Log.info("Updated cron '#{@new_resource.name}'")
|
152
|
+
else
|
153
|
+
unless @cron_empty
|
154
|
+
status = popen4("crontab -l #{@new_resource.user}") do |pid, stdin, stdout, stderr|
|
155
|
+
stdout.each { |line| crontab << line }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
crontab << newcron
|
160
|
+
status = write_crontab(crontab)
|
161
|
+
Chef::Log.info("Added cron '#{@new_resource.name}'")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def action_delete
|
166
|
+
if @cron_exists
|
167
|
+
crontab = String.new
|
168
|
+
cron_found = false
|
169
|
+
status = popen4("crontab -l #{@new_resource.user}") do |pid, stdin, stdout, stderr|
|
170
|
+
stdout.each_line do |line|
|
171
|
+
case line.chomp
|
172
|
+
when "# Chef Name: #{@new_resource.name}"
|
173
|
+
cron_found = true
|
174
|
+
next
|
175
|
+
when CRON_PATTERN
|
176
|
+
if cron_found
|
177
|
+
cron_found = false
|
178
|
+
next
|
179
|
+
end
|
180
|
+
else
|
181
|
+
next if cron_found
|
182
|
+
end
|
183
|
+
crontab << line
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
status = write_crontab(crontab)
|
188
|
+
Chef::Log.info("Deleted cron '#{@new_resource.name}'")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|