chef 12.0.1 → 12.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +1 -1
  3. data/lib/chef/digester.rb +1 -0
  4. data/lib/chef/dsl/recipe.rb +2 -1
  5. data/lib/chef/exceptions.rb +5 -0
  6. data/lib/chef/knife.rb +7 -0
  7. data/lib/chef/knife/cookbook_site_install.rb +34 -10
  8. data/lib/chef/provider/link.rb +1 -1
  9. data/lib/chef/provider/package/apt.rb +2 -2
  10. data/lib/chef/provider/package/homebrew.rb +11 -2
  11. data/lib/chef/provider/package/windows/msi.rb +2 -0
  12. data/lib/chef/provider/subversion.rb +3 -3
  13. data/lib/chef/resource.rb +23 -91
  14. data/lib/chef/resource/homebrew_package.rb +2 -1
  15. data/lib/chef/resource/resource_notification.rb +109 -0
  16. data/lib/chef/resource_collection/resource_set.rb +8 -8
  17. data/lib/chef/run_context.rb +4 -4
  18. data/lib/chef/version.rb +1 -1
  19. data/lib/chef/whitelist.rb +3 -1
  20. data/lib/chef/win32/api/file.rb +17 -3
  21. data/spec/functional/notifications_spec.rb +169 -0
  22. data/spec/functional/resource/link_spec.rb +31 -32
  23. data/spec/support/platform_helpers.rb +5 -2
  24. data/spec/unit/knife/cookbook_site_install_spec.rb +157 -116
  25. data/spec/unit/knife_spec.rb +108 -78
  26. data/spec/unit/mixin/shell_out_spec.rb +39 -40
  27. data/spec/unit/node_spec.rb +34 -0
  28. data/spec/unit/provider/link_spec.rb +5 -5
  29. data/spec/unit/provider/package/apt_spec.rb +264 -257
  30. data/spec/unit/provider/package/homebrew_spec.rb +26 -0
  31. data/spec/unit/provider/package/windows/msi_spec.rb +18 -3
  32. data/spec/unit/provider/subversion_spec.rb +5 -5
  33. data/spec/unit/provider_resolver_spec.rb +2 -2
  34. data/spec/unit/recipe_spec.rb +1 -0
  35. data/spec/unit/resource/apt_package_spec.rb +3 -5
  36. data/spec/unit/resource/resource_notification_spec.rb +170 -0
  37. data/spec/unit/resource_spec.rb +0 -151
  38. data/spec/unit/run_context_spec.rb +94 -55
  39. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e11671748225ec17a9c6a23041fa3cff028f640c
4
- data.tar.gz: 54f0f6d8d85c7cebadf90892e102bc36caa6a420
3
+ metadata.gz: e516e23b8f432618bba6ae817b113bef6f1fd7e6
4
+ data.tar.gz: 0130eaec499c6059291f3d395b1fb282a203d9d5
5
5
  SHA512:
6
- metadata.gz: 23faed269443bad8321dd3214a33f610c41a5853d541a2d93fa5cbdda8d51ff6d79f6fa6d6e934a881bf50d8c7303915b7f53a8757a2b3f4f43b933a7b0001a8
7
- data.tar.gz: 15c8402828acf3b4080226341fabaa90d2dcc10dd44c4a47939e8a8e36b9e8eb257276caa7eabf29f9df7d1acfa2ab9f2338ad028d494f944958f31beb69f85c
6
+ metadata.gz: dad78645f06fa14308a32787553f371b741d3195df67b027afddb3f6e3e3a44b291a47bda4fddb7a623358c3677c95b145203e5657e133116cc0ee255c168b90
7
+ data.tar.gz: 4aa354a66a468b4100723a4027b1ff9265cfcf8c8377d3698f279c6852494c9f01bc246868c29dea3d8b49251a0c287920671bb9fbeb913bbbf0682e6a4a6ad9
@@ -64,7 +64,7 @@ class Chef
64
64
  end
65
65
 
66
66
  def minimize(file_contents, entry)
67
- object = Chef::JSONCompat.from_json(file_contents)
67
+ object = Chef::JSONCompat.parse(file_contents)
68
68
  object = data_handler.normalize(object, entry)
69
69
  object = data_handler.minimize(object, entry)
70
70
  Chef::JSONCompat.to_json_pretty(object)
@@ -19,6 +19,7 @@
19
19
  #
20
20
 
21
21
  require 'openssl'
22
+ require 'singleton'
22
23
 
23
24
  class Chef
24
25
  class Digester
@@ -81,7 +81,7 @@ class Chef
81
81
 
82
82
  resource = build_resource(type, name, created_at, &resource_attrs_block)
83
83
 
84
- run_context.resource_collection.insert(resource, resource_type:type, instance_name:name)
84
+ run_context.resource_collection.insert(resource, resource_type: type, instance_name: name)
85
85
  resource
86
86
  end
87
87
 
@@ -101,6 +101,7 @@ class Chef
101
101
 
102
102
  resource = resource_class.new(name, run_context)
103
103
  resource.source_line = created_at
104
+ resource.declared_type = type
104
105
  # If we have a resource like this one, we want to steal its state
105
106
  # This behavior is very counter-intuitive and should be removed.
106
107
  # See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694
@@ -149,6 +149,11 @@ class Chef
149
149
  class IllegalVersionConstraint < NotImplementedError; end
150
150
 
151
151
  class MetadataNotValid < StandardError; end
152
+ class MetadataNotFound < StandardError
153
+ def initialize
154
+ super "No metadata.rb or metadata.json!"
155
+ end
156
+ end
152
157
 
153
158
  # File operation attempted but no permissions to perform it
154
159
  class InsufficientPermissions < RuntimeError; end
@@ -428,6 +428,13 @@ class Chef
428
428
  raise # make sure exit passes through.
429
429
  when Net::HTTPServerException, Net::HTTPFatalError
430
430
  humanize_http_exception(e)
431
+ when OpenSSL::SSL::SSLError
432
+ ui.error "Could not establish a secure connection to the server."
433
+ ui.info "Use `knife ssl check` to troubleshoot your SSL configuration."
434
+ ui.info "If your Chef Server uses a self-signed certificate, you can use"
435
+ ui.info "`knife ssl fetch` to make knife trust the server's certificates."
436
+ ui.info ""
437
+ ui.info "Original Exception: #{e.class.name}: #{e.message}"
431
438
  when Errno::ECONNREFUSED, Timeout::Error, Errno::ETIMEDOUT, SocketError
432
439
  ui.error "Network Error: #{e.message}"
433
440
  ui.info "Check your knife configuration and network settings"
@@ -17,11 +17,11 @@
17
17
  #
18
18
 
19
19
  require 'chef/knife'
20
+ require 'chef/exceptions'
20
21
  require 'shellwords'
21
22
 
22
23
  class Chef
23
24
  class Knife
24
-
25
25
  class CookbookSiteInstall < Knife
26
26
 
27
27
  deps do
@@ -107,11 +107,8 @@ class Chef
107
107
  end
108
108
  end
109
109
 
110
-
111
110
  unless config[:no_deps]
112
- md = Chef::Cookbook::Metadata.new
113
- md.from_file(File.join(@install_path, @cookbook_name, "metadata.rb"))
114
- md.dependencies.each do |cookbook, version_list|
111
+ preferred_metadata.dependencies.each do |cookbook, version_list|
115
112
  # Doesn't do versions.. yet
116
113
  nv = self.class.new
117
114
  nv.config = config
@@ -144,6 +141,7 @@ class Chef
144
141
 
145
142
  def extract_cookbook(upstream_file, version)
146
143
  ui.info("Uncompressing #{@cookbook_name} version #{version}.")
144
+ # FIXME: Detect if we have the bad tar from git on Windows: https://github.com/opscode/chef/issues/1753
147
145
  shell_out!("tar zxvf #{convert_path upstream_file}", :cwd => @install_path)
148
146
  end
149
147
 
@@ -153,11 +151,37 @@ class Chef
153
151
  end
154
152
 
155
153
  def convert_path(upstream_file)
156
- if ENV['MSYSTEM'] == 'MINGW32'
157
- return upstream_file.sub(/^([[:alpha:]]):/, '/\1')
158
- else
159
- return Shellwords.escape upstream_file
160
- end
154
+ # converts a Windows path (C:\foo) to a mingw path (/c/foo)
155
+ if ENV['MSYSTEM'] == 'MINGW32'
156
+ return upstream_file.sub(/^([[:alpha:]]):/, '/\1')
157
+ else
158
+ return Shellwords.escape upstream_file
159
+ end
160
+ end
161
+
162
+ # Get the preferred metadata path on disk. Chef prefers the metadata.rb
163
+ # over the metadata.json.
164
+ #
165
+ # @raise if there is no metadata in the cookbook
166
+ #
167
+ # @return [Chef::Cookbook::Metadata]
168
+ def preferred_metadata
169
+ md = Chef::Cookbook::Metadata.new
170
+
171
+ rb = File.join(@install_path, @cookbook_name, "metadata.rb")
172
+ if File.exist?(rb)
173
+ md.from_file(rb)
174
+ return md
175
+ end
176
+
177
+ json = File.join(@install_path, @cookbook_name, "metadata.json")
178
+ if File.exist?(json)
179
+ json = IO.read(json)
180
+ md.from_json(json)
181
+ return md
182
+ end
183
+
184
+ raise Chef::Exceptions::MetadataNotFound
161
185
  end
162
186
  end
163
187
  end
@@ -86,7 +86,7 @@ class Chef
86
86
  end
87
87
 
88
88
  def canonicalize(path)
89
- Chef::Util::PathHelper.canonical_path(path)
89
+ Chef::Platform.windows? ? path.gsub('/', '\\') : path
90
90
  end
91
91
 
92
92
  def action_create
@@ -46,8 +46,8 @@ class Chef
46
46
  end
47
47
 
48
48
  def default_release_options
49
- # Use apt::Default-Release option only if provider was explicitly defined
50
- "-o APT::Default-Release=#{@new_resource.default_release}" if @new_resource.provider && @new_resource.default_release
49
+ # Use apt::Default-Release option only if provider supports it
50
+ "-o APT::Default-Release=#{@new_resource.default_release}" if @new_resource.respond_to?(:default_release) && @new_resource.default_release
51
51
  end
52
52
 
53
53
  def check_package_state(package)
@@ -26,7 +26,8 @@ class Chef
26
26
  class Package
27
27
  class Homebrew < Chef::Provider::Package
28
28
 
29
- provides :homebrew_package, os: "mac_os_x"
29
+ provides :homebrew_package
30
+ provides :package, os: ["mac_os_x", "darwin"]
30
31
 
31
32
  include Chef::Mixin::HomebrewUser
32
33
 
@@ -94,7 +95,15 @@ class Chef
94
95
  # that brew thinks is linked as the current version.
95
96
  #
96
97
  def current_installed_version
97
- brew_info['keg_only'] ? brew_info['installed'].last['version'] : brew_info['linked_keg']
98
+ if brew_info['keg_only']
99
+ if brew_info['installed'].empty?
100
+ nil
101
+ else
102
+ brew_info['installed'].last['version']
103
+ end
104
+ else
105
+ brew_info['linked_keg']
106
+ end
98
107
  end
99
108
 
100
109
  # Packages (formula) available to install should have a
@@ -19,6 +19,7 @@
19
19
  # TODO: Allow @new_resource.source to be a Product Code as a GUID for uninstall / network install
20
20
 
21
21
  require 'chef/win32/api/installer' if RUBY_PLATFORM =~ /mswin|mingw32|windows/
22
+ require 'chef/mixin/shell_out'
22
23
 
23
24
  class Chef
24
25
  class Provider
@@ -26,6 +27,7 @@ class Chef
26
27
  class Windows
27
28
  class MSI
28
29
  include Chef::ReservedNames::Win32::API::Installer if RUBY_PLATFORM =~ /mswin|mingw32|windows/
30
+ include Chef::Mixin::ShellOut
29
31
 
30
32
  def initialize(resource)
31
33
  @new_resource = resource
@@ -62,7 +62,7 @@ class Chef
62
62
  def action_checkout
63
63
  if target_dir_non_existent_or_empty?
64
64
  converge_by("perform checkout of #{@new_resource.repository} into #{@new_resource.destination}") do
65
- shell_out!(run_options(command: checkout_command))
65
+ shell_out!(checkout_command, run_options)
66
66
  end
67
67
  else
68
68
  Chef::Log.debug "#{@new_resource} checkout destination #{@new_resource.destination} already exists or is a non-empty directory - nothing to do"
@@ -79,7 +79,7 @@ class Chef
79
79
 
80
80
  def action_force_export
81
81
  converge_by("export #{@new_resource.repository} into #{@new_resource.destination}") do
82
- shell_out!(run_options(command: export_command))
82
+ shell_out!(export_command, run_options)
83
83
  end
84
84
  end
85
85
 
@@ -90,7 +90,7 @@ class Chef
90
90
  Chef::Log.debug "#{@new_resource} current revision: #{current_rev} target revision: #{revision_int}"
91
91
  unless current_revision_matches_target_revision?
92
92
  converge_by("sync #{@new_resource.destination} from #{@new_resource.repository}") do
93
- shell_out!(run_options(command: sync_command))
93
+ shell_out!(sync_command, run_options)
94
94
  Chef::Log.info "#{@new_resource} updated to revision: #{revision_int}"
95
95
  end
96
96
  end
@@ -29,99 +29,14 @@ require 'chef/resource/conditional_action_not_nothing'
29
29
  require 'chef/resource_collection'
30
30
  require 'chef/node_map'
31
31
  require 'chef/node'
32
- require 'chef/provider_resolver'
33
32
  require 'chef/platform'
33
+ require 'chef/resource/resource_notification'
34
34
 
35
35
  require 'chef/mixin/deprecation'
36
36
  require 'chef/mixin/descendants_tracker'
37
37
 
38
38
  class Chef
39
39
  class Resource
40
- class Notification < Struct.new(:resource, :action, :notifying_resource)
41
-
42
- def duplicates?(other_notification)
43
- unless other_notification.respond_to?(:resource) && other_notification.respond_to?(:action)
44
- msg = "only duck-types of Chef::Resource::Notification can be checked for duplication "\
45
- "you gave #{other_notification.inspect}"
46
- raise ArgumentError, msg
47
- end
48
- other_notification.resource == resource && other_notification.action == action
49
- end
50
-
51
- # If resource and/or notifying_resource is not a resource object, this will look them up in the resource collection
52
- # and fix the references from strings to actual Resource objects.
53
- def resolve_resource_reference(resource_collection)
54
- return resource if resource.kind_of?(Chef::Resource) && notifying_resource.kind_of?(Chef::Resource)
55
-
56
- if not(resource.kind_of?(Chef::Resource))
57
- fix_resource_reference(resource_collection)
58
- end
59
-
60
- if not(notifying_resource.kind_of?(Chef::Resource))
61
- fix_notifier_reference(resource_collection)
62
- end
63
- end
64
-
65
- # This will look up the resource if it is not a Resource Object. It will complain if it finds multiple
66
- # resources, can't find a resource, or gets invalid syntax.
67
- def fix_resource_reference(resource_collection)
68
- matching_resource = resource_collection.find(resource)
69
- if Array(matching_resource).size > 1
70
- msg = "Notification #{self} from #{notifying_resource} was created with a reference to multiple resources, "\
71
- "but can only notify one resource. Notifying resource was defined on #{notifying_resource.source_line}"
72
- raise Chef::Exceptions::InvalidResourceReference, msg
73
- end
74
- self.resource = matching_resource
75
-
76
- rescue Chef::Exceptions::ResourceNotFound => e
77
- err = Chef::Exceptions::ResourceNotFound.new(<<-FAIL)
78
- resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
79
- but #{resource} cannot be found in the resource collection. #{notifying_resource} is defined in \
80
- #{notifying_resource.source_line}
81
- FAIL
82
- err.set_backtrace(e.backtrace)
83
- raise err
84
- rescue Chef::Exceptions::InvalidResourceSpecification => e
85
- err = Chef::Exceptions::InvalidResourceSpecification.new(<<-F)
86
- Resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
87
- but #{resource.inspect} is not valid syntax to look up a resource in the resource collection. Notification \
88
- is defined near #{notifying_resource.source_line}
89
- F
90
- err.set_backtrace(e.backtrace)
91
- raise err
92
- end
93
-
94
- # This will look up the notifying_resource if it is not a Resource Object. It will complain if it finds multiple
95
- # resources, can't find a resource, or gets invalid syntax.
96
- def fix_notifier_reference(resource_collection)
97
- matching_notifier = resource_collection.find(notifying_resource)
98
- if Array(matching_notifier).size > 1
99
- msg = "Notification #{self} from #{notifying_resource} was created with a reference to multiple notifying "\
100
- "resources, but can only originate from one resource. Destination resource was defined "\
101
- "on #{resource.source_line}"
102
- raise Chef::Exceptions::InvalidResourceReference, msg
103
- end
104
- self.notifying_resource = matching_notifier
105
-
106
- rescue Chef::Exceptions::ResourceNotFound => e
107
- err = Chef::Exceptions::ResourceNotFound.new(<<-FAIL)
108
- Resource #{resource} is configured to receive notifications from #{notifying_resource} with action #{action}, \
109
- but #{notifying_resource} cannot be found in the resource collection. #{resource} is defined in \
110
- #{resource.source_line}
111
- FAIL
112
- err.set_backtrace(e.backtrace)
113
- raise err
114
- rescue Chef::Exceptions::InvalidResourceSpecification => e
115
- err = Chef::Exceptions::InvalidResourceSpecification.new(<<-F)
116
- Resource #{resource} is configured to receive notifications from #{notifying_resource} with action #{action}, \
117
- but #{notifying_resource.inspect} is not valid syntax to look up a resource in the resource collection. Notification \
118
- is defined near #{resource.source_line}
119
- F
120
- err.set_backtrace(e.backtrace)
121
- raise err
122
- end
123
-
124
- end
125
40
 
126
41
  FORBIDDEN_IVARS = [:@run_context, :@not_if, :@only_if, :@enclosing_provider]
127
42
  HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider]
@@ -212,6 +127,7 @@ F
212
127
  attr_accessor :source_line
213
128
  attr_accessor :retries
214
129
  attr_accessor :retry_delay
130
+ attr_accessor :declared_type
215
131
 
216
132
  attr_reader :updated
217
133
 
@@ -299,7 +215,7 @@ F
299
215
 
300
216
  def load_prior_resource(resource_type, instance_name)
301
217
  begin
302
- key = ::Chef::ResourceCollection::ResourceSet.create_key(resource_type, instance_name)
218
+ key = "#{resource_type}[#{instance_name}]"
303
219
  prior_resource = run_context.resource_collection.lookup(key)
304
220
  # if we get here, there is a prior resource (otherwise we'd have jumped
305
221
  # to the rescue clause).
@@ -426,11 +342,11 @@ F
426
342
  def notifies(action, resource_spec, timing=:delayed)
427
343
  # when using old-style resources(:template => "/foo.txt") style, you
428
344
  # could end up with multiple resources.
345
+ validate_resource_spec!(resource_spec)
346
+
429
347
  resources = [ resource_spec ].flatten
430
348
  resources.each do |resource|
431
349
 
432
- validate_resource_spec!(resource_spec)
433
-
434
350
  case timing.to_s
435
351
  when 'delayed'
436
352
  notifies_delayed(action, resource)
@@ -449,8 +365,12 @@ F
449
365
  # resolve_resource_reference on each in turn, causing them to
450
366
  # resolve lazy/forward references.
451
367
  def resolve_notification_references
452
- run_context.immediate_notifications(self).each { |n| n.resolve_resource_reference(run_context.resource_collection) }
453
- run_context.delayed_notifications(self).each {|n| n.resolve_resource_reference(run_context.resource_collection) }
368
+ run_context.immediate_notifications(self).each { |n|
369
+ n.resolve_resource_reference(run_context.resource_collection)
370
+ }
371
+ run_context.delayed_notifications(self).each {|n|
372
+ n.resolve_resource_reference(run_context.resource_collection)
373
+ }
454
374
  end
455
375
 
456
376
  def notifies_immediately(action, resource_spec)
@@ -499,6 +419,14 @@ F
499
419
  end
500
420
  end
501
421
 
422
+ # We usually want to store and reference resources by their declared type and not the actual type that
423
+ # was looked up by the Resolver (IE, "package" becomes YumPackage class). If we have not been provided
424
+ # the declared key we want to fall back on the old to_s key.
425
+ def declared_key
426
+ return to_s if declared_type.nil?
427
+ "#{declared_type}[#{@name}]"
428
+ end
429
+
502
430
  def to_s
503
431
  "#{@resource_name}[#{@name}]"
504
432
  end
@@ -833,3 +761,7 @@ F
833
761
  end
834
762
  end
835
763
  end
764
+
765
+ # We require this at the BOTTOM of this file to avoid circular requires (it is used
766
+ # at runtime but not load time)
767
+ require 'chef/provider_resolver'
@@ -25,7 +25,8 @@ class Chef
25
25
  class Resource
26
26
  class HomebrewPackage < Chef::Resource::Package
27
27
 
28
- provides :homebrew_package, os: "mac_os_x"
28
+ provides :homebrew_package
29
+ provides :package, os: ["mac_os_x", "darwin"]
29
30
 
30
31
  def initialize(name, run_context=nil)
31
32
  super
@@ -0,0 +1,109 @@
1
+ #
2
+ # Author:: Tyler Ball (<tball@chef.io>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/resource'
20
+
21
+ class Chef
22
+ class Resource
23
+ class Notification < Struct.new(:resource, :action, :notifying_resource)
24
+
25
+ def duplicates?(other_notification)
26
+ unless other_notification.respond_to?(:resource) && other_notification.respond_to?(:action)
27
+ msg = "only duck-types of Chef::Resource::Notification can be checked for duplication "\
28
+ "you gave #{other_notification.inspect}"
29
+ raise ArgumentError, msg
30
+ end
31
+ other_notification.resource == resource && other_notification.action == action
32
+ end
33
+
34
+ # If resource and/or notifying_resource is not a resource object, this will look them up in the resource collection
35
+ # and fix the references from strings to actual Resource objects.
36
+ def resolve_resource_reference(resource_collection)
37
+ return resource if resource.kind_of?(Chef::Resource) && notifying_resource.kind_of?(Chef::Resource)
38
+
39
+ if not(resource.kind_of?(Chef::Resource))
40
+ fix_resource_reference(resource_collection)
41
+ end
42
+
43
+ if not(notifying_resource.kind_of?(Chef::Resource))
44
+ fix_notifier_reference(resource_collection)
45
+ end
46
+ end
47
+
48
+ # This will look up the resource if it is not a Resource Object. It will complain if it finds multiple
49
+ # resources, can't find a resource, or gets invalid syntax.
50
+ def fix_resource_reference(resource_collection)
51
+ matching_resource = resource_collection.find(resource)
52
+ if Array(matching_resource).size > 1
53
+ msg = "Notification #{self} from #{notifying_resource} was created with a reference to multiple resources, "\
54
+ "but can only notify one resource. Notifying resource was defined on #{notifying_resource.source_line}"
55
+ raise Chef::Exceptions::InvalidResourceReference, msg
56
+ end
57
+ self.resource = matching_resource
58
+
59
+ rescue Chef::Exceptions::ResourceNotFound => e
60
+ err = Chef::Exceptions::ResourceNotFound.new(<<-FAIL)
61
+ resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
62
+ but #{resource} cannot be found in the resource collection. #{notifying_resource} is defined in \
63
+ #{notifying_resource.source_line}
64
+ FAIL
65
+ err.set_backtrace(e.backtrace)
66
+ raise err
67
+ rescue Chef::Exceptions::InvalidResourceSpecification => e
68
+ err = Chef::Exceptions::InvalidResourceSpecification.new(<<-F)
69
+ Resource #{notifying_resource} is configured to notify resource #{resource} with action #{action}, \
70
+ but #{resource.inspect} is not valid syntax to look up a resource in the resource collection. Notification \
71
+ is defined near #{notifying_resource.source_line}
72
+ F
73
+ err.set_backtrace(e.backtrace)
74
+ raise err
75
+ end
76
+
77
+ # This will look up the notifying_resource if it is not a Resource Object. It will complain if it finds multiple
78
+ # resources, can't find a resource, or gets invalid syntax.
79
+ def fix_notifier_reference(resource_collection)
80
+ matching_notifier = resource_collection.find(notifying_resource)
81
+ if Array(matching_notifier).size > 1
82
+ msg = "Notification #{self} from #{notifying_resource} was created with a reference to multiple notifying "\
83
+ "resources, but can only originate from one resource. Destination resource was defined "\
84
+ "on #{resource.source_line}"
85
+ raise Chef::Exceptions::InvalidResourceReference, msg
86
+ end
87
+ self.notifying_resource = matching_notifier
88
+
89
+ rescue Chef::Exceptions::ResourceNotFound => e
90
+ err = Chef::Exceptions::ResourceNotFound.new(<<-FAIL)
91
+ Resource #{resource} is configured to receive notifications from #{notifying_resource} with action #{action}, \
92
+ but #{notifying_resource} cannot be found in the resource collection. #{resource} is defined in \
93
+ #{resource.source_line}
94
+ FAIL
95
+ err.set_backtrace(e.backtrace)
96
+ raise err
97
+ rescue Chef::Exceptions::InvalidResourceSpecification => e
98
+ err = Chef::Exceptions::InvalidResourceSpecification.new(<<-F)
99
+ Resource #{resource} is configured to receive notifications from #{notifying_resource} with action #{action}, \
100
+ but #{notifying_resource.inspect} is not valid syntax to look up a resource in the resource collection. Notification \
101
+ is defined near #{resource.source_line}
102
+ F
103
+ err.set_backtrace(e.backtrace)
104
+ raise err
105
+ end
106
+
107
+ end
108
+ end
109
+ end