chef 12.0.1-x86-mingw32 → 12.0.3-x86-mingw32
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.
- checksums.yaml +4 -4
- data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +1 -1
- data/lib/chef/digester.rb +1 -0
- data/lib/chef/dsl/recipe.rb +2 -1
- data/lib/chef/exceptions.rb +5 -0
- data/lib/chef/knife.rb +7 -0
- data/lib/chef/knife/cookbook_site_install.rb +34 -10
- data/lib/chef/provider/link.rb +1 -1
- data/lib/chef/provider/package/apt.rb +2 -2
- data/lib/chef/provider/package/homebrew.rb +11 -2
- data/lib/chef/provider/package/windows/msi.rb +2 -0
- data/lib/chef/provider/subversion.rb +3 -3
- data/lib/chef/resource.rb +23 -91
- data/lib/chef/resource/homebrew_package.rb +2 -1
- data/lib/chef/resource/resource_notification.rb +109 -0
- data/lib/chef/resource_collection/resource_set.rb +8 -8
- data/lib/chef/run_context.rb +4 -4
- data/lib/chef/version.rb +1 -1
- data/lib/chef/whitelist.rb +3 -1
- data/lib/chef/win32/api/file.rb +17 -3
- data/spec/functional/notifications_spec.rb +169 -0
- data/spec/functional/resource/link_spec.rb +31 -32
- data/spec/support/platform_helpers.rb +5 -2
- data/spec/unit/knife/cookbook_site_install_spec.rb +157 -116
- data/spec/unit/knife_spec.rb +108 -78
- data/spec/unit/mixin/shell_out_spec.rb +39 -40
- data/spec/unit/node_spec.rb +34 -0
- data/spec/unit/provider/link_spec.rb +5 -5
- data/spec/unit/provider/package/apt_spec.rb +264 -257
- data/spec/unit/provider/package/homebrew_spec.rb +26 -0
- data/spec/unit/provider/package/windows/msi_spec.rb +18 -3
- data/spec/unit/provider/subversion_spec.rb +5 -5
- data/spec/unit/provider_resolver_spec.rb +2 -2
- data/spec/unit/recipe_spec.rb +1 -0
- data/spec/unit/resource/apt_package_spec.rb +3 -5
- data/spec/unit/resource/resource_notification_spec.rb +170 -0
- data/spec/unit/resource_spec.rb +0 -151
- data/spec/unit/run_context_spec.rb +94 -55
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 531cc13db59ae0ad0ae00ae0380fe056ba696815
|
4
|
+
data.tar.gz: 2c27984660c53fc055171ef76ca06c6f8c051ccf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6262a6d2edda375eebf686c68243088cda7e7eaf17ead5ccdb859fd2028288bb6c01332e564fb0260eab1add424d0508e52956261eb852afbc46275a3b85fa2
|
7
|
+
data.tar.gz: eb2fc6c488b804a6a03af730c4f5255bc0425a1d98608e503c631a5a7efbc2e3b26a5c8fdc6f74aa4c0a2bf81ff3109c9f23ee2cd8470910ad2a9ca747533cef
|
@@ -64,7 +64,7 @@ class Chef
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def minimize(file_contents, entry)
|
67
|
-
object = Chef::JSONCompat.
|
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)
|
data/lib/chef/digester.rb
CHANGED
data/lib/chef/dsl/recipe.rb
CHANGED
@@ -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
|
data/lib/chef/exceptions.rb
CHANGED
@@ -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
|
data/lib/chef/knife.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
data/lib/chef/provider/link.rb
CHANGED
@@ -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
|
50
|
-
"-o APT::Default-Release=#{@new_resource.default_release}" if @new_resource.
|
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
|
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']
|
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
|
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
|
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
|
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
|
data/lib/chef/resource.rb
CHANGED
@@ -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 =
|
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|
|
453
|
-
|
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
|
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
|