chef 0.9.8 → 0.9.10.rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/README.rdoc +1 -1
  2. data/distro/common/man/man8/knife.8 +89 -79
  3. data/distro/common/markdown/knife.mkd +7 -0
  4. data/distro/debian/etc/default/chef-server +3 -0
  5. data/distro/debian/etc/default/chef-server-webui +3 -0
  6. data/distro/debian/etc/default/chef-solr +3 -0
  7. data/distro/debian/etc/default/chef-solr-indexer +3 -0
  8. data/distro/debian/etc/init.d/chef-server +3 -1
  9. data/distro/debian/etc/init.d/chef-server-webui +3 -1
  10. data/distro/redhat/etc/init.d/chef-client +1 -1
  11. data/lib/chef/application.rb +2 -0
  12. data/lib/chef/application/client.rb +5 -3
  13. data/lib/chef/application/knife.rb +16 -5
  14. data/lib/chef/application/solo.rb +0 -1
  15. data/lib/chef/checksum.rb +65 -1
  16. data/lib/chef/checksum_cache.rb +173 -0
  17. data/lib/chef/client.rb +84 -121
  18. data/lib/chef/cookbook/remote_file_vendor.rb +10 -3
  19. data/lib/chef/cookbook/syntax_check.rb +2 -2
  20. data/lib/chef/cookbook_loader.rb +2 -0
  21. data/lib/chef/cookbook_site_streaming_uploader.rb +29 -0
  22. data/lib/chef/cookbook_uploader.rb +8 -7
  23. data/lib/chef/cookbook_version.rb +155 -114
  24. data/lib/chef/exceptions.rb +5 -0
  25. data/lib/chef/handler.rb +43 -0
  26. data/lib/chef/index_queue/consumer.rb +1 -1
  27. data/lib/chef/index_queue/indexable.rb +1 -1
  28. data/lib/chef/knife.rb +18 -5
  29. data/lib/chef/knife/bootstrap.rb +2 -2
  30. data/lib/chef/knife/bootstrap/archlinux-gems.erb +44 -0
  31. data/lib/chef/knife/bootstrap/client-install.vbs +80 -0
  32. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
  33. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -7
  34. data/lib/chef/knife/bootstrap/windows-gems.erb +34 -0
  35. data/lib/chef/knife/configure_client.rb +4 -2
  36. data/lib/chef/knife/cookbook_metadata.rb +1 -1
  37. data/lib/chef/knife/cookbook_site_share.rb +2 -1
  38. data/lib/chef/knife/cookbook_site_vendor.rb +6 -0
  39. data/lib/chef/knife/cookbook_test.rb +1 -1
  40. data/lib/chef/knife/ec2_server_create.rb +51 -26
  41. data/lib/chef/knife/exec.rb +52 -0
  42. data/lib/chef/knife/ssh.rb +27 -15
  43. data/lib/chef/knife/status.rb +27 -10
  44. data/lib/chef/knife/windows_bootstrap.rb +154 -0
  45. data/lib/chef/mixin/checksum.rb +2 -2
  46. data/lib/chef/mixin/xml_escape.rb +75 -49
  47. data/lib/chef/node.rb +54 -58
  48. data/lib/chef/node/attribute.rb +61 -53
  49. data/lib/chef/platform.rb +19 -2
  50. data/lib/chef/provider/breakpoint.rb +1 -1
  51. data/lib/chef/provider/cookbook_file.rb +3 -3
  52. data/lib/chef/provider/cron.rb +3 -3
  53. data/lib/chef/provider/cron/solaris.rb +195 -0
  54. data/lib/chef/provider/deploy.rb +3 -3
  55. data/lib/chef/provider/directory.rb +2 -2
  56. data/lib/chef/provider/env.rb +5 -5
  57. data/lib/chef/provider/execute.rb +1 -1
  58. data/lib/chef/provider/file.rb +10 -9
  59. data/lib/chef/provider/git.rb +12 -4
  60. data/lib/chef/provider/group.rb +5 -5
  61. data/lib/chef/provider/http_request.rb +25 -9
  62. data/lib/chef/provider/ifconfig.rb +2 -2
  63. data/lib/chef/provider/link.rb +11 -6
  64. data/lib/chef/provider/log.rb +1 -0
  65. data/lib/chef/provider/mdadm.rb +3 -3
  66. data/lib/chef/provider/mount.rb +5 -5
  67. data/lib/chef/provider/mount/mount.rb +1 -1
  68. data/lib/chef/provider/ohai.rb +41 -0
  69. data/lib/chef/provider/package.rb +5 -5
  70. data/lib/chef/provider/package/yum-dump.py +5 -2
  71. data/lib/chef/provider/remote_directory.rb +11 -5
  72. data/lib/chef/provider/remote_file.rb +2 -2
  73. data/lib/chef/provider/route.rb +154 -133
  74. data/lib/chef/provider/ruby_block.rb +1 -1
  75. data/lib/chef/provider/service.rb +6 -6
  76. data/lib/chef/provider/subversion.rb +12 -9
  77. data/lib/chef/provider/template.rb +2 -2
  78. data/lib/chef/provider/user.rb +7 -7
  79. data/lib/chef/provider/user/useradd.rb +15 -1
  80. data/lib/chef/providers.rb +2 -0
  81. data/lib/chef/resource.rb +164 -58
  82. data/lib/chef/resource/http_request.rb +9 -0
  83. data/lib/chef/resource/ohai.rb +40 -0
  84. data/lib/chef/resource/remote_directory.rb +10 -1
  85. data/lib/chef/resource/rpm_package.rb +34 -0
  86. data/lib/chef/resource_collection.rb +3 -2
  87. data/lib/chef/resources.rb +2 -0
  88. data/lib/chef/rest.rb +13 -7
  89. data/lib/chef/rest/auth_credentials.rb +1 -1
  90. data/lib/chef/rest/rest_request.rb +3 -1
  91. data/lib/chef/runner.rb +31 -55
  92. data/lib/chef/shef/shef_session.rb +1 -1
  93. data/lib/chef/util/windows/net_use.rb +1 -1
  94. data/lib/chef/version.rb +1 -1
  95. data/lib/chef/webui_user.rb +0 -1
  96. metadata +38 -19
  97. data/lib/chef/cache.rb +0 -61
  98. data/lib/chef/cache/checksum.rb +0 -91
@@ -26,7 +26,7 @@ class Chef
26
26
 
27
27
  def action_create
28
28
  @new_resource.block.call
29
- @new_resource.updated = true
29
+ @new_resource.updated_by_last_action(true)
30
30
  end
31
31
  end
32
32
  end
@@ -36,7 +36,7 @@ class Chef
36
36
  else
37
37
  Chef::Log.debug("#{@new_resource}: attempting to enable")
38
38
  if enable_service
39
- @new_resource.updated = true
39
+ @new_resource.updated_by_last_action(true)
40
40
  Chef::Log.info("#{@new_resource}: enabled successfully")
41
41
  end
42
42
  end
@@ -46,7 +46,7 @@ class Chef
46
46
  if @current_resource.enabled
47
47
  Chef::Log.debug("#{@new_resource}: attempting to disable")
48
48
  if disable_service
49
- @new_resource.updated = true
49
+ @new_resource.updated_by_last_action(true)
50
50
  Chef::Log.info("#{@new_resource}: disabled successfully")
51
51
  end
52
52
  else
@@ -58,7 +58,7 @@ class Chef
58
58
  unless @current_resource.running
59
59
  Chef::Log.debug("#{@new_resource}: attempting to start")
60
60
  if start_service
61
- @new_resource.updated = true
61
+ @new_resource.updated_by_last_action(true)
62
62
  Chef::Log.info("Started service #{@new_resource} successfully")
63
63
  end
64
64
  else
@@ -70,7 +70,7 @@ class Chef
70
70
  if @current_resource.running
71
71
  Chef::Log.debug("#{@new_resource}: attempting to stop")
72
72
  if stop_service
73
- @new_resource.updated = true
73
+ @new_resource.updated_by_last_action(true)
74
74
  Chef::Log.info("#{@new_resource}: stopped successfully")
75
75
  end
76
76
  else
@@ -81,7 +81,7 @@ class Chef
81
81
  def action_restart
82
82
  Chef::Log.debug("#{@new_resource}: attempting to restart")
83
83
  if restart_service
84
- @new_resource.updated = true
84
+ @new_resource.updated_by_last_action(true)
85
85
  Chef::Log.info("#{@new_resource}: restarted successfully")
86
86
  end
87
87
  end
@@ -93,7 +93,7 @@ class Chef
93
93
  if @current_resource.running
94
94
  Chef::Log.debug("#{@new_resource}: attempting to reload")
95
95
  if reload_service
96
- @new_resource.updated = true
96
+ @new_resource.updated_by_last_action(true)
97
97
  Chef::Log.info("#{@new_resource}: reloaded successfully")
98
98
  end
99
99
  end
@@ -30,24 +30,27 @@ class Chef
30
30
 
31
31
  def load_current_resource
32
32
  @current_resource = Chef::Resource::Subversion.new(@new_resource.name)
33
- if current_revision = find_current_revision
34
- @current_resource.revision current_revision
33
+
34
+ unless [:export, :force_export].include?(@new_resource.action.first)
35
+ if current_revision = find_current_revision
36
+ @current_resource.revision current_revision
37
+ end
35
38
  end
36
39
  end
37
40
 
38
41
  def action_checkout
39
42
  run_command(run_options(:command => checkout_command))
40
- @new_resource.updated = true
43
+ @new_resource.updated_by_last_action(true)
41
44
  end
42
45
 
43
46
  def action_export
44
47
  run_command(run_options(:command => export_command))
45
- @new_resource.updated = true
48
+ @new_resource.updated_by_last_action(true)
46
49
  end
47
50
 
48
51
  def action_force_export
49
- run_command(run_options(:command => export_command(:force => true)))
50
- @new_resource.updated = true
52
+ run_command(run_options(:command => export_command))
53
+ @new_resource.updated_by_last_action(true)
51
54
  end
52
55
 
53
56
  def action_sync
@@ -56,7 +59,7 @@ class Chef
56
59
  else
57
60
  run_command(run_options(:command => sync_command))
58
61
  end
59
- @new_resource.updated = true
62
+ @new_resource.updated_by_last_action(true)
60
63
  end
61
64
 
62
65
  def sync_command
@@ -70,9 +73,9 @@ class Chef
70
73
  "-r#{revision_int}", @new_resource.repository, @new_resource.destination
71
74
  end
72
75
 
73
- def export_command(opts={})
76
+ def export_command
74
77
  Chef::Log.info "exporting #{@new_resource.repository} at revision #{@new_resource.revision} to #{@new_resource.destination}"
75
- args = opts[:force] ? ["--force"] : []
78
+ args = ["--force"]
76
79
  args << @new_resource.svn_arguments << verbose << authentication <<
77
80
  "-r#{revision_int}" << @new_resource.repository << @new_resource.destination
78
81
  scm :export, *args
@@ -46,7 +46,7 @@ class Chef
46
46
  backup
47
47
  set_all_access_controls(rendered_template.path)
48
48
  FileUtils.mv(rendered_template.path, @new_resource.path)
49
- @new_resource.updated = true
49
+ @new_resource.updated_by_last_action(true)
50
50
  end
51
51
  end
52
52
  end
@@ -88,7 +88,7 @@ class Chef
88
88
  def set_all_access_controls(file)
89
89
  access_controls = Chef::FileAccessControl.new(@new_resource, file)
90
90
  access_controls.set_all
91
- @new_resource.updated = access_controls.modified?
91
+ @new_resource.updated_by_last_action(access_controls.modified?)
92
92
  end
93
93
 
94
94
  private
@@ -98,18 +98,18 @@ class Chef
98
98
  if !@user_exists
99
99
  create_user
100
100
  Chef::Log.info("Created #{@new_resource}")
101
- @new_resource.updated = true
101
+ @new_resource.updated_by_last_action(true)
102
102
  elsif compare_user
103
103
  manage_user
104
104
  Chef::Log.info("Altered #{@new_resource}")
105
- @new_resource.updated = true
105
+ @new_resource.updated_by_last_action(true)
106
106
  end
107
107
  end
108
108
 
109
109
  def action_remove
110
110
  if @user_exists
111
111
  remove_user
112
- @new_resource.updated = true
112
+ @new_resource.updated_by_last_action(true)
113
113
  Chef::Log.info("Removed #{@new_resource}")
114
114
  end
115
115
  end
@@ -121,7 +121,7 @@ class Chef
121
121
  def action_manage
122
122
  if @user_exists && compare_user
123
123
  manage_user
124
- @new_resource.updated = true
124
+ @new_resource.updated_by_last_action(true)
125
125
  Chef::Log.info("Managed #{@new_resource}")
126
126
  end
127
127
  end
@@ -134,7 +134,7 @@ class Chef
134
134
  if @user_exists
135
135
  if compare_user
136
136
  manage_user
137
- @new_resource.updated = true
137
+ @new_resource.updated_by_last_action(true)
138
138
  Chef::Log.info("Modified #{@new_resource}")
139
139
  end
140
140
  else
@@ -146,7 +146,7 @@ class Chef
146
146
  if @user_exists
147
147
  if check_lock() == false
148
148
  lock_user
149
- @new_resource.updated = true
149
+ @new_resource.updated_by_last_action(true)
150
150
  Chef::Log.info("Locked #{@new_resource}")
151
151
  else
152
152
  Chef::Log.debug("No need to lock #{@new_resource}")
@@ -168,7 +168,7 @@ class Chef
168
168
  if @user_exists
169
169
  if check_lock() == true
170
170
  unlock_user
171
- @new_resource.updated = true
171
+ @new_resource.updated_by_last_action(true)
172
172
  Chef::Log.info("Unlocked #{@new_resource}")
173
173
  else
174
174
  Chef::Log.debug("No need to unlock #{@new_resource}")
@@ -55,7 +55,21 @@ class Chef
55
55
  end
56
56
 
57
57
  unless status.exitstatus == 0
58
- raise Chef::Exceptions::User, "Cannot determine if #{@new_resource} is locked!"
58
+ raise_lock_error = false
59
+ # we can get an exit code of 1 even when it's successful on rhel/centos (redhat bug 578534)
60
+ if status.exitstatus == 1 && ['redhat', 'centos'].include?(node[:platform])
61
+ passwd_version_status = popen4('rpm -q passwd') do |pid, stdin, stdout, stderr|
62
+ passwd_version = stdout.gets.chomp
63
+
64
+ unless passwd_version == 'passwd-0.73-1'
65
+ raise_lock_error = true
66
+ end
67
+ end
68
+ else
69
+ raise_lock_error = true
70
+ end
71
+
72
+ raise Chef::Exceptions::User, "Cannot determine if #{@new_resource} is locked!" if raise_lock_error
59
73
  end
60
74
 
61
75
  @locked
@@ -19,6 +19,7 @@
19
19
  require 'chef/provider/breakpoint'
20
20
  require 'chef/provider/cookbook_file'
21
21
  require 'chef/provider/cron'
22
+ require 'chef/provider/cron/solaris'
22
23
  require 'chef/provider/deploy'
23
24
  require 'chef/provider/directory'
24
25
  require 'chef/provider/env'
@@ -31,6 +32,7 @@ require 'chef/provider/http_request'
31
32
  require 'chef/provider/ifconfig'
32
33
  require 'chef/provider/link'
33
34
  require 'chef/provider/log'
35
+ require 'chef/provider/ohai'
34
36
  require 'chef/provider/mdadm'
35
37
  require 'chef/provider/mount'
36
38
  require 'chef/provider/package'
@@ -21,6 +21,7 @@ require 'chef/mixin/params_validate'
21
21
  require 'chef/mixin/check_helper'
22
22
  require 'chef/mixin/language'
23
23
  require 'chef/mixin/convert_to_class_name'
24
+ require 'chef/mixin/command'
24
25
  require 'chef/resource_collection'
25
26
  require 'chef/node'
26
27
 
@@ -28,7 +29,45 @@ require 'chef/mixin/deprecation'
28
29
 
29
30
  class Chef
30
31
  class Resource
31
- class Notification < Struct.new(:resource, :action)
32
+ class Notification < Struct.new(:resource, :action, :notifying_resource)
33
+
34
+ def duplicates?(other_notification)
35
+ unless other_notification.respond_to?(:resource) && other_notification.respond_to?(:action)
36
+ msg = "only duck-types of Chef::Resource::Notification can be checked for duplication "\
37
+ "you gave #{other_notification.inspect}"
38
+ raise ArgumentError, msg
39
+ end
40
+ other_notification.resource == resource && other_notification.action == action
41
+ end
42
+
43
+ def resolve_resource_reference(resource_collection)
44
+ return resource if resource.kind_of?(Chef::Resource)
45
+
46
+ matching_resource = resource_collection.find(resource)
47
+ if Array(matching_resource).size > 1
48
+ msg = "Notification #{self} from #{notifying_resource} was created with a reference to multiple resources, "\
49
+ "but can only notify one resource. Notifying resource was defined on #{notifying_resource.source_line}"
50
+ raise Chef::Exceptions::InvalidResourceReference, msg
51
+ end
52
+ self.resource = matching_resource
53
+ rescue Chef::Exceptions::ResourceNotFound => e
54
+ err = Chef::Exceptions::ResourceNotFound.new(<<-FAIL)
55
+ Resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
56
+ but #{resource} cannot be found in the resource collection. #{notifying_resource} is defined in \
57
+ #{notifying_resource.source_line}
58
+ FAIL
59
+ err.set_backtrace(e.backtrace)
60
+ raise err
61
+ rescue Chef::Exceptions::InvalidResourceSpecification => e
62
+ err = Chef::Exceptions::InvalidResourceSpecification.new(<<-F)
63
+ Resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
64
+ but #{resource.inspect} is not valid syntax to look up a resource in the resource collection. Notification \
65
+ is defined near #{notifying_resource.source_line}
66
+ F
67
+ err.set_backtrace(e.backtrace)
68
+ raise err
69
+ end
70
+
32
71
  end
33
72
 
34
73
  HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@node]
@@ -39,13 +78,25 @@ class Chef
39
78
  include Chef::Mixin::ConvertToClassName
40
79
  include Chef::Mixin::Deprecation
41
80
 
42
- attr_accessor :params, :provider, :updated, :allowed_actions, :run_context, :cookbook_name, :recipe_name, :enclosing_provider
81
+ attr_accessor :params
82
+ attr_accessor :provider
83
+ attr_accessor :allowed_actions
84
+ attr_accessor :run_context
85
+ attr_accessor :cookbook_name
86
+ attr_accessor :recipe_name
87
+ attr_accessor :enclosing_provider
43
88
  attr_accessor :source_line
44
- attr_reader :resource_name, :not_if_args, :only_if_args
89
+
90
+ attr_reader :updated
91
+
92
+ attr_reader :resource_name
93
+ attr_reader :not_if_args
94
+ attr_reader :only_if_args
45
95
 
46
96
  # Each notify entry is a resource/action pair, modeled as an
47
- # OpenStruct with a .resource and .action member
48
- attr_reader :notifies_immediate, :notifies_delayed
97
+ # Struct with a #resource and #action member
98
+ attr_reader :immediate_notifications
99
+ attr_reader :delayed_notifications
49
100
 
50
101
  def initialize(name, run_context=nil)
51
102
  @name = name
@@ -57,19 +108,28 @@ class Chef
57
108
  @allowed_actions = [ :nothing ]
58
109
  @action = :nothing
59
110
  @updated = false
111
+ @updated_by_last_action = false
60
112
  @supports = {}
61
113
  @ignore_failure = false
62
114
  @not_if = nil
63
115
  @not_if_args = {}
64
116
  @only_if = nil
65
117
  @only_if_args = {}
66
- @notifies_immediate = Array.new
67
- @notifies_delayed = Array.new
118
+ @immediate_notifications = Array.new
119
+ @delayed_notifications = Array.new
68
120
  @source_line = nil
69
121
 
70
122
  @node = run_context ? deprecated_ivar(run_context.node, :node, :warn) : nil
71
123
  end
72
-
124
+
125
+ def updated=(true_or_false)
126
+ Chef::Log.warn("Chef::Resource#updated=(true|false) is deprecated. Please call #updated_by_last_action(true|false) instead.")
127
+ Chef::Log.warn("Called from:")
128
+ caller[0..3].each {|line| Chef::Log.warn(line)}
129
+ updated_by_last_action(true_or_false)
130
+ @updated = true_or_false
131
+ end
132
+
73
133
  def node
74
134
  run_context && run_context.node
75
135
  end
@@ -95,7 +155,7 @@ class Chef
95
155
  end
96
156
  end
97
157
  true
98
- rescue ArgumentError => e
158
+ rescue Chef::Exceptions::ResourceNotFound => e
99
159
  true
100
160
  end
101
161
  end
@@ -166,31 +226,65 @@ class Chef
166
226
  def epic_fail(arg=nil)
167
227
  ignore_failure(arg)
168
228
  end
169
-
229
+
170
230
  def notifies(*args)
171
- raise ArgumentError, "Wrong number of arguments (should be 1, 2, or 3)" unless ( args.size > 0 && args.size < 4)
172
- if args.size > 1
173
- notifies_helper(*args)
231
+ unless ( args.size > 0 && args.size < 4)
232
+ raise ArgumentError, "Wrong number of arguments for notifies: should be 1-3 arguments, you gave #{args.inspect}"
233
+ end
234
+
235
+ if args.size > 1 # notifies(:action, resource) OR notifies(:action, resource, :immediately)
236
+ add_notification(*args)
174
237
  else
175
238
  # This syntax is so weird. surely people will just give us one hash?
176
239
  notifications = args.flatten
177
240
  notifications.each do |resources_notifications|
178
- begin
179
- resources_notifications.each do |resource, notification|
180
- Chef::Log.error "resource KV: `#{resource.inspect}' => `#{notification.inspect}'"
181
- notifies_helper(notification[0], resource, notification[1])
182
- end
183
- rescue NoMethodError
184
- Chef::Log.fatal("encountered NME processing resource #{resources_notifications.inspect}")
185
- Chef::Log.fatal("incoming args: #{args.inspect}")
186
- raise
241
+ resources_notifications.each do |resource, notification|
242
+ action, timing = notification[0], notification[1]
243
+ Chef::Log.debug "adding notification from resource #{self} to `#{resource.inspect}' => `#{notification.inspect}'"
244
+ add_notification(action, resource, timing)
187
245
  end
188
246
  end
189
247
  end
248
+ rescue NoMethodError
249
+ Chef::Log.fatal("Error processing notifies(#{args.inspect}) on #{self}")
250
+ raise
190
251
  end
191
-
252
+
253
+ def add_notification(action, resources, timing=:delayed)
254
+ resources = [resources].flatten
255
+ resources.each do |resource|
256
+ case timing.to_s
257
+ when 'delayed'
258
+ notifies_delayed(action, resource)
259
+ when 'immediate', 'immediately'
260
+ notifies_immediately(action, resource)
261
+ else
262
+ raise ArgumentError, "invalid timing: #{timing} for notifies(#{action}, #{resources.inspect}, #{timing}) resource #{self} "\
263
+ "Valid timings are: :delayed, :immediate, :immediately"
264
+ end
265
+ end
266
+
267
+ true
268
+ end
269
+
270
+ # Iterates over all immediate and delayed notifications, calling
271
+ # resolve_resource_reference on each in turn, causing them to
272
+ # resolve lazy/forward references.
273
+ def resolve_notification_references
274
+ @immediate_notifications.each { |n| n.resolve_resource_reference(run_context.resource_collection) }
275
+ @delayed_notifications.each {|n| n.resolve_resource_reference(run_context.resource_collection) }
276
+ end
277
+
278
+ def notifies_immediately(action, resource_spec)
279
+ @immediate_notifications << Notification.new(resource_spec, action, self)
280
+ end
281
+
282
+ def notifies_delayed(action, resource_spec)
283
+ @delayed_notifications << Notification.new(resource_spec, action, self)
284
+ end
285
+
192
286
  def resources(*args)
193
- run_context.resource_collection.resources(*args)
287
+ run_context.resource_collection.find(*args)
194
288
  end
195
289
 
196
290
  def subscribes(action, resources, timing=:delayed)
@@ -200,7 +294,7 @@ class Chef
200
294
  end
201
295
  true
202
296
  end
203
-
297
+
204
298
  def is(*args)
205
299
  if args.size == 1
206
300
  args.first
@@ -272,10 +366,43 @@ class Chef
272
366
  end
273
367
 
274
368
  def run_action(action)
369
+ # ensure that we don't leave @updated_by_last_action set to true
370
+ # on accident
371
+ updated_by_last_action(false)
372
+
373
+ # Check if this resource has an only_if block -- if it does,
374
+ # evaluate the only_if block and skip the resource if
375
+ # appropriate.
376
+ if only_if
377
+ unless Chef::Mixin::Command.only_if(only_if, only_if_args)
378
+ Chef::Log.debug("Skipping #{self} due to only_if")
379
+ return
380
+ end
381
+ end
382
+
383
+ # Check if this resource has a not_if block -- if it does,
384
+ # evaluate the not_if block and skip the resource if
385
+ # appropriate.
386
+ if not_if
387
+ unless Chef::Mixin::Command.not_if(not_if, not_if_args)
388
+ Chef::Log.debug("Skipping #{self} due to not_if")
389
+ return
390
+ end
391
+ end
392
+
275
393
  provider = Chef::Platform.provider_for_resource(self)
276
394
  provider.load_current_resource
277
395
  provider.send("action_#{action}")
278
396
  end
397
+
398
+ def updated_by_last_action(true_or_false)
399
+ @updated ||= true_or_false
400
+ @updated_by_last_action = true_or_false
401
+ end
402
+
403
+ def updated_by_last_action?
404
+ @updated_by_last_action
405
+ end
279
406
 
280
407
  def updated?
281
408
  updated
@@ -377,41 +504,20 @@ class Chef
377
504
  end
378
505
 
379
506
  end
380
-
507
+
381
508
  private
382
-
383
- def lookup_provider_constant(name)
384
- begin
385
- self.class.provider_base.const_get(convert_to_class_name(name.to_s))
386
- rescue NameError => e
387
- if e.to_s =~ /#{Regexp.escape(self.class.provider_base.to_s)}/
388
- raise ArgumentError, "No provider found to match '#{name}'"
389
- else
390
- raise e
391
- end
392
- end
393
- end
394
-
395
- def validate_timing(timing)
396
- timing = timing.to_sym
397
- raise ArgumentError, "invalid timing: #{timing}; must be one of: :delayed, :immediate, :immediately" unless (timing == :delayed || timing == :immediate || timing == :immediately)
398
- timing == :immediately ? :immediate : timing
399
- end
400
-
401
- def notifies_helper(action, resources, timing=:delayed)
402
- timing = validate_timing(timing)
403
-
404
- resource_array = [resources].flatten
405
- resource_array.each do |resource|
406
- new_notify = Notification.new(resource, action)
407
- if timing == :delayed
408
- notifies_delayed << new_notify
409
- else
410
- notifies_immediate << new_notify
411
- end
509
+
510
+ def lookup_provider_constant(name)
511
+ begin
512
+ self.class.provider_base.const_get(convert_to_class_name(name.to_s))
513
+ rescue NameError => e
514
+ if e.to_s =~ /#{Regexp.escape(self.class.provider_base.to_s)}/
515
+ raise ArgumentError, "No provider found to match '#{name}'"
516
+ else
517
+ raise e
412
518
  end
413
-
414
- true
415
519
  end
416
520
  end
521
+
522
+ end
417
523
  end