chef 12.0.0.rc.0 → 12.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +1 -1
- data/lib/chef/api_client/registration.rb +3 -1
- data/lib/chef/chef_fs/data_handler/group_data_handler.rb +4 -0
- data/lib/chef/config.rb +46 -38
- data/lib/chef/event_loggers/windows_eventlog.rb +5 -6
- data/lib/chef/exceptions.rb +13 -1
- data/lib/chef/file_content_management/tempfile.rb +33 -5
- data/lib/chef/knife.rb +11 -3
- data/lib/chef/knife/bootstrap.rb +8 -7
- data/lib/chef/mixin/deep_merge.rb +15 -54
- data/lib/chef/mixin/which.rb +37 -0
- data/lib/chef/node.rb +14 -25
- data/lib/chef/node/attribute.rb +227 -41
- data/lib/chef/node/attribute_collections.rb +117 -3
- data/lib/chef/node/immutable_collections.rb +6 -6
- data/lib/chef/platform/provider_priority_map.rb +3 -2
- data/lib/chef/platform/service_helpers.rb +37 -8
- data/lib/chef/provider/service/aixinit.rb +1 -1
- data/lib/chef/provider/service/arch.rb +1 -1
- data/lib/chef/provider/service/debian.rb +5 -1
- data/lib/chef/provider/service/init.rb +4 -0
- data/lib/chef/provider/service/insserv.rb +5 -1
- data/lib/chef/provider/service/invokercd.rb +5 -1
- data/lib/chef/provider/service/redhat.rb +5 -1
- data/lib/chef/provider/service/systemd.rb +50 -32
- data/lib/chef/provider/service/upstart.rb +5 -2
- data/lib/chef/provider_resolver.rb +30 -16
- data/lib/chef/resource.rb +2 -1
- data/lib/chef/resources.rb +7 -0
- data/lib/chef/run_context.rb +0 -5
- data/lib/chef/run_list/run_list_expansion.rb +2 -2
- data/lib/chef/shell.rb +2 -2
- data/lib/chef/util/selinux.rb +2 -10
- data/lib/chef/version.rb +1 -1
- data/lib/chef/workstation_config_loader.rb +1 -1
- data/spec/support/shared/unit/resource/static_provider_resolution.rb +1 -6
- data/spec/unit/api_client/registration_spec.rb +22 -0
- data/spec/unit/application/knife_spec.rb +6 -2
- data/spec/unit/chef_fs/data_handler/group_handler_spec.rb +63 -0
- data/spec/unit/config_spec.rb +5 -5
- data/spec/unit/knife/bootstrap_spec.rb +27 -1
- data/spec/unit/knife_spec.rb +5 -0
- data/spec/unit/mixin/deep_merge_spec.rb +0 -40
- data/spec/unit/node/attribute_spec.rb +37 -50
- data/spec/unit/node_spec.rb +321 -13
- data/spec/unit/provider/file/content_spec.rb +23 -2
- data/spec/unit/provider/service/systemd_service_spec.rb +173 -158
- data/spec/unit/provider_resolver_spec.rb +175 -10
- data/spec/unit/resource/timestamped_deploy_spec.rb +8 -29
- data/spec/unit/runner_spec.rb +3 -1
- metadata +141 -191
- data/spec/.DS_Store +0 -0
- data/spec/data/.DS_Store +0 -0
- data/spec/data/lwrp/.DS_Store +0 -0
- data/spec/data/lwrp/providers/.DS_Store +0 -0
- data/spec/data/lwrp/resources/.DS_Store +0 -0
- data/spec/data/lwrp_override/.DS_Store +0 -0
- data/spec/data/lwrp_override/providers/.DS_Store +0 -0
- data/spec/data/lwrp_override/resources/.DS_Store +0 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Lamont Granquist <lamont@getchef.io>
|
3
|
+
# Copyright:: Copyright (c) 2010 Opscode, 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
|
+
class Chef
|
19
|
+
module Mixin
|
20
|
+
module Which
|
21
|
+
def which(cmd, opts = {})
|
22
|
+
extra_path =
|
23
|
+
if opts[:extra_path].nil?
|
24
|
+
[ '/bin', '/usr/bin', '/sbin', '/usr/sbin' ]
|
25
|
+
else
|
26
|
+
[ opts[:extra_path] ].flatten
|
27
|
+
end
|
28
|
+
paths = ENV['PATH'].split(File::PATH_SEPARATOR) + extra_path
|
29
|
+
paths.each do |path|
|
30
|
+
filename = File.join(path, cmd)
|
31
|
+
return filename if File.executable?(filename)
|
32
|
+
end
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/chef/node.rb
CHANGED
@@ -42,6 +42,8 @@ class Chef
|
|
42
42
|
extend Forwardable
|
43
43
|
|
44
44
|
def_delegators :attributes, :keys, :each_key, :each_value, :key?, :has_key?
|
45
|
+
def_delegators :attributes, :rm, :rm_default, :rm_normal, :rm_override
|
46
|
+
def_delegators :attributes, :default!, :normal!, :override!, :force_default!, :force_override!
|
45
47
|
|
46
48
|
attr_accessor :recipe_list, :run_state, :override_runlist
|
47
49
|
|
@@ -125,6 +127,7 @@ class Chef
|
|
125
127
|
# Set a normal attribute of this node, but auto-vivify any Mashes that
|
126
128
|
# might be missing
|
127
129
|
def normal
|
130
|
+
attributes.top_level_breadcrumb = nil
|
128
131
|
attributes.set_unless_value_present = false
|
129
132
|
attributes.normal
|
130
133
|
end
|
@@ -134,28 +137,25 @@ class Chef
|
|
134
137
|
# Set a normal attribute of this node, auto-vivifying any mashes that are
|
135
138
|
# missing, but if the final value already exists, don't set it
|
136
139
|
def normal_unless
|
140
|
+
attributes.top_level_breadcrumb = nil
|
137
141
|
attributes.set_unless_value_present = true
|
138
142
|
attributes.normal
|
139
143
|
end
|
144
|
+
|
140
145
|
alias_method :set_unless, :normal_unless
|
141
146
|
|
142
147
|
# Set a default of this node, but auto-vivify any Mashes that might
|
143
148
|
# be missing
|
144
149
|
def default
|
150
|
+
attributes.top_level_breadcrumb = nil
|
145
151
|
attributes.set_unless_value_present = false
|
146
152
|
attributes.default
|
147
153
|
end
|
148
154
|
|
149
|
-
# Set a force default attribute. Intermediate mashes will be created by
|
150
|
-
# auto-vivify if necessary.
|
151
|
-
def default!
|
152
|
-
attributes.set_unless_value_present = false
|
153
|
-
attributes.default!
|
154
|
-
end
|
155
|
-
|
156
155
|
# Set a default attribute of this node, auto-vivifying any mashes that are
|
157
156
|
# missing, but if the final value already exists, don't set it
|
158
157
|
def default_unless
|
158
|
+
attributes.top_level_breadcrumb = nil
|
159
159
|
attributes.set_unless_value_present = true
|
160
160
|
attributes.default
|
161
161
|
end
|
@@ -163,49 +163,38 @@ class Chef
|
|
163
163
|
# Set an override attribute of this node, but auto-vivify any Mashes that
|
164
164
|
# might be missing
|
165
165
|
def override
|
166
|
+
attributes.top_level_breadcrumb = nil
|
166
167
|
attributes.set_unless_value_present = false
|
167
168
|
attributes.override
|
168
169
|
end
|
169
170
|
|
170
|
-
# Set a force override attribute. Intermediate mashes will be created by
|
171
|
-
# auto-vivify if needed.
|
172
|
-
def override!
|
173
|
-
attributes.set_unless_value_present = false
|
174
|
-
attributes.override!
|
175
|
-
end
|
176
|
-
|
177
171
|
# Set an override attribute of this node, auto-vivifying any mashes that
|
178
172
|
# are missing, but if the final value already exists, don't set it
|
179
173
|
def override_unless
|
174
|
+
attributes.top_level_breadcrumb = nil
|
180
175
|
attributes.set_unless_value_present = true
|
181
176
|
attributes.override
|
182
177
|
end
|
183
178
|
|
184
|
-
|
185
|
-
|
186
|
-
|
179
|
+
alias :override_attrs :override
|
180
|
+
alias :default_attrs :default
|
181
|
+
alias :normal_attrs :normal
|
187
182
|
|
188
183
|
def override_attrs=(new_values)
|
189
184
|
attributes.override = new_values
|
190
185
|
end
|
191
186
|
|
192
|
-
def default_attrs
|
193
|
-
attributes.default
|
194
|
-
end
|
195
|
-
|
196
187
|
def default_attrs=(new_values)
|
197
188
|
attributes.default = new_values
|
198
189
|
end
|
199
190
|
|
200
|
-
def normal_attrs
|
201
|
-
attributes.normal
|
202
|
-
end
|
203
|
-
|
204
191
|
def normal_attrs=(new_values)
|
205
192
|
attributes.normal = new_values
|
206
193
|
end
|
207
194
|
|
208
195
|
def automatic_attrs
|
196
|
+
attributes.top_level_breadcrumb = nil
|
197
|
+
attributes.set_unless_value_present = false
|
209
198
|
attributes.automatic
|
210
199
|
end
|
211
200
|
|
data/lib/chef/node/attribute.rb
CHANGED
@@ -58,7 +58,6 @@ class Chef
|
|
58
58
|
:@force_default
|
59
59
|
]
|
60
60
|
|
61
|
-
|
62
61
|
OVERRIDE_COMPONENTS = [
|
63
62
|
:@override,
|
64
63
|
:@role_override,
|
@@ -146,7 +145,6 @@ class Chef
|
|
146
145
|
METHOD_DEFN
|
147
146
|
end
|
148
147
|
|
149
|
-
|
150
148
|
# return the cookbook level default attribute component
|
151
149
|
attr_reader :default
|
152
150
|
|
@@ -159,11 +157,6 @@ class Chef
|
|
159
157
|
# return the force_default level attribute component
|
160
158
|
attr_reader :force_default
|
161
159
|
|
162
|
-
# default! is the "advertised" method for force_default, but is
|
163
|
-
# implemented as an alias because instance variables can't (easily) have
|
164
|
-
# +!+ characters.
|
165
|
-
alias :default! :force_default
|
166
|
-
|
167
160
|
# return the "normal" level attribute component
|
168
161
|
attr_reader :normal
|
169
162
|
|
@@ -179,14 +172,22 @@ class Chef
|
|
179
172
|
# return the force override level attribute component
|
180
173
|
attr_reader :force_override
|
181
174
|
|
182
|
-
# +override!+ is the "advertised" method for +force_override+ but is
|
183
|
-
# implemented as an alias because instance variables can't easily have
|
184
|
-
# +!+ characters.
|
185
|
-
alias :override! :force_override
|
186
|
-
|
187
175
|
# return the automatic level attribute component
|
188
176
|
attr_reader :automatic
|
189
177
|
|
178
|
+
# This is used to track the top level key as we descend through method chaining into
|
179
|
+
# a precedence level (e.g. node.default['foo']['bar']['baz']= results in 'foo' here). We
|
180
|
+
# need this so that when we hit the end of a method chain which results in a mutator method
|
181
|
+
# that we can invalidate the whole top-level deep merge cache for the top-level key. It is
|
182
|
+
# the responsibility of the accessor on the Chef::Node object to reset this to nil, and then
|
183
|
+
# the first VividMash#[] call can ||= and set this to the first key we encounter.
|
184
|
+
attr_accessor :top_level_breadcrumb
|
185
|
+
|
186
|
+
# Cache of deep merged values by top-level key. This is a simple hash which has keys that are the
|
187
|
+
# top-level keys of the node object, and we save the computed deep-merge for that key here. There is
|
188
|
+
# no cache of subtrees.
|
189
|
+
attr_accessor :deep_merge_cache
|
190
|
+
|
190
191
|
def initialize(normal, default, override, automatic)
|
191
192
|
@set_unless_present = false
|
192
193
|
|
@@ -207,6 +208,8 @@ class Chef
|
|
207
208
|
@merged_attributes = nil
|
208
209
|
@combined_override = nil
|
209
210
|
@combined_default = nil
|
211
|
+
@top_level_breadcrumb = nil
|
212
|
+
@deep_merge_cache = {}
|
210
213
|
end
|
211
214
|
|
212
215
|
# Debug what's going on with an attribute. +args+ is a path spec to the
|
@@ -242,13 +245,16 @@ class Chef
|
|
242
245
|
@set_unless_present = setting
|
243
246
|
end
|
244
247
|
|
245
|
-
#
|
246
|
-
#
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
248
|
+
# Invalidate a key in the deep_merge_cache. If called with nil, or no arg, this will invalidate
|
249
|
+
# the entire deep_merge cache. In the case of the user doing node.default['foo']['bar']['baz']=
|
250
|
+
# that eventually results in a call to reset_cache('foo') here. A node.default=hash_thing call
|
251
|
+
# must invalidate the entire cache and re-deep-merge the entire node object.
|
252
|
+
def reset_cache(path = nil)
|
253
|
+
if path.nil?
|
254
|
+
@deep_merge_cache = {}
|
255
|
+
else
|
256
|
+
deep_merge_cache.delete(path)
|
257
|
+
end
|
252
258
|
end
|
253
259
|
|
254
260
|
alias :reset :reset_cache
|
@@ -311,30 +317,136 @@ class Chef
|
|
311
317
|
@automatic = VividMash.new(self, new_data)
|
312
318
|
end
|
313
319
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
320
|
+
#
|
321
|
+
# Deleting attributes
|
322
|
+
#
|
323
|
+
|
324
|
+
# clears attributes from all precedence levels
|
325
|
+
def rm(*args)
|
326
|
+
reset(args[0])
|
327
|
+
# just easier to compute our retval, rather than collect+merge sub-retvals
|
328
|
+
ret = args.inject(merged_attributes) do |attr, arg|
|
329
|
+
if attr.nil? || !attr.respond_to?(:[])
|
330
|
+
nil
|
331
|
+
else
|
332
|
+
begin
|
333
|
+
attr[arg]
|
334
|
+
rescue TypeError
|
335
|
+
raise TypeError, "Wrong type in index of attribute (did you use a Hash index on an Array?)"
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
rm_default(*args)
|
340
|
+
rm_normal(*args)
|
341
|
+
rm_override(*args)
|
342
|
+
ret
|
343
|
+
end
|
344
|
+
|
345
|
+
# does <level>['foo']['bar'].delete('baz')
|
346
|
+
def remove_from_precedence_level(level, *args, key)
|
347
|
+
multimash = level.element(*args)
|
348
|
+
multimash.nil? ? nil : multimash.delete(key)
|
349
|
+
end
|
350
|
+
|
351
|
+
private :remove_from_precedence_level
|
352
|
+
|
353
|
+
# clears attributes from all default precedence levels
|
354
|
+
#
|
355
|
+
# equivalent to: force_default!['foo']['bar'].delete('baz')
|
356
|
+
def rm_default(*args)
|
357
|
+
reset(args[0])
|
358
|
+
remove_from_precedence_level(force_default!(autovivify: false), *args)
|
359
|
+
end
|
360
|
+
|
361
|
+
# clears attributes from normal precedence
|
362
|
+
#
|
363
|
+
# equivalent to: normal!['foo']['bar'].delete('baz')
|
364
|
+
def rm_normal(*args)
|
365
|
+
reset(args[0])
|
366
|
+
remove_from_precedence_level(normal!(autovivify: false), *args)
|
367
|
+
end
|
368
|
+
|
369
|
+
# clears attributes from all override precedence levels
|
370
|
+
#
|
371
|
+
# equivalent to: force_override!['foo']['bar'].delete('baz')
|
372
|
+
def rm_override(*args)
|
373
|
+
reset(args[0])
|
374
|
+
remove_from_precedence_level(force_override!(autovivify: false), *args)
|
375
|
+
end
|
376
|
+
|
377
|
+
#
|
378
|
+
# Replacing attributes without merging
|
379
|
+
#
|
380
|
+
|
381
|
+
# sets default attributes without merging
|
382
|
+
def default!(opts={})
|
383
|
+
# FIXME: do not flush whole cache
|
384
|
+
reset
|
385
|
+
MultiMash.new(self, @default, [], opts)
|
386
|
+
end
|
387
|
+
|
388
|
+
# sets normal attributes without merging
|
389
|
+
def normal!(opts={})
|
390
|
+
# FIXME: do not flush whole cache
|
391
|
+
reset
|
392
|
+
MultiMash.new(self, @normal, [], opts)
|
393
|
+
end
|
394
|
+
|
395
|
+
# sets override attributes without merging
|
396
|
+
def override!(opts={})
|
397
|
+
# FIXME: do not flush whole cache
|
398
|
+
reset
|
399
|
+
MultiMash.new(self, @override, [], opts)
|
322
400
|
end
|
323
401
|
|
324
|
-
|
325
|
-
|
402
|
+
# clears from all default precedence levels and then sets force_default
|
403
|
+
def force_default!(opts={})
|
404
|
+
# FIXME: do not flush whole cache
|
405
|
+
reset
|
406
|
+
MultiMash.new(self, @force_default, [@default, @env_default, @role_default], opts)
|
326
407
|
end
|
327
408
|
|
328
|
-
|
329
|
-
|
409
|
+
# clears from all override precedence levels and then sets force_override
|
410
|
+
def force_override!(opts={})
|
411
|
+
# FIXME: do not flush whole cache
|
412
|
+
reset
|
413
|
+
MultiMash.new(self, @force_override, [@override, @env_override, @role_override], opts)
|
414
|
+
end
|
415
|
+
|
416
|
+
#
|
417
|
+
# Accessing merged attributes.
|
418
|
+
#
|
419
|
+
# Note that merged_attributes('foo', 'bar', 'baz') can be called to compute only the
|
420
|
+
# deep merge of node['foo']['bar']['baz'], but in practice we currently always compute
|
421
|
+
# all of node['foo'] even if the user only requires node['foo']['bar']['baz'].
|
422
|
+
#
|
423
|
+
|
424
|
+
def merged_attributes(*path)
|
425
|
+
# immutablize(
|
426
|
+
merge_all(path)
|
427
|
+
# )
|
428
|
+
end
|
429
|
+
|
430
|
+
def combined_override(*path)
|
431
|
+
immutablize(merge_overrides(path))
|
432
|
+
end
|
433
|
+
|
434
|
+
def combined_default(*path)
|
435
|
+
immutablize(merge_defaults(path))
|
330
436
|
end
|
331
437
|
|
332
438
|
def [](key)
|
333
|
-
|
439
|
+
if deep_merge_cache.has_key?(key)
|
440
|
+
# return the cache of the deep merged values by top-level key
|
441
|
+
deep_merge_cache[key]
|
442
|
+
else
|
443
|
+
# save all the work of computing node[key]
|
444
|
+
deep_merge_cache[key] = merged_attributes(key)
|
445
|
+
end
|
334
446
|
end
|
335
447
|
|
336
448
|
def []=(key, value)
|
337
|
-
|
449
|
+
raise Exceptions::ImmutableAttributeModification
|
338
450
|
end
|
339
451
|
|
340
452
|
def has_key?(key)
|
@@ -377,20 +489,94 @@ class Chef
|
|
377
489
|
|
378
490
|
private
|
379
491
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
492
|
+
# Helper method for merge_all/merge_defaults/merge_overrides.
|
493
|
+
#
|
494
|
+
# apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"]
|
495
|
+
#
|
496
|
+
# The path value can be nil in which case the whole component is returned.
|
497
|
+
#
|
498
|
+
# It returns nil (does not raise an exception) if it walks off the end of an Mash/Hash/Array, it does not
|
499
|
+
# raise any TypeError if it attempts to apply a hash key to an Integer/String/TrueClass, and just returns
|
500
|
+
# nil in that case.
|
501
|
+
#
|
502
|
+
def apply_path(component, path)
|
503
|
+
path ||= []
|
504
|
+
path.inject(component) do |val, path_arg|
|
505
|
+
if val.respond_to?(:[])
|
506
|
+
# Have an Array-like or Hash-like thing
|
507
|
+
if !val.respond_to?(:has_key?)
|
508
|
+
# Have an Array-like thing
|
509
|
+
val[path_arg]
|
510
|
+
elsif val.has_key?(path_arg)
|
511
|
+
# Hash-like thing (must check has_key? first to protect against Autovivification)
|
512
|
+
val[path_arg]
|
513
|
+
else
|
514
|
+
nil
|
515
|
+
end
|
516
|
+
else
|
517
|
+
nil
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
# For elements like Fixnums, true, nil...
|
523
|
+
def safe_dup(e)
|
524
|
+
e.dup
|
525
|
+
rescue TypeError
|
526
|
+
e
|
527
|
+
end
|
528
|
+
|
529
|
+
# Deep merge all attribute levels using hash-only merging between different precidence
|
530
|
+
# levels (so override arrays completely replace arrays set at any default level).
|
531
|
+
#
|
532
|
+
# The path allows for selectively deep-merging a subtree of the node object.
|
533
|
+
#
|
534
|
+
# @param path [Array] Array of args to method chain to descend into the node object
|
535
|
+
# @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
|
536
|
+
def merge_all(path)
|
537
|
+
components = [
|
538
|
+
merge_defaults(path),
|
539
|
+
apply_path(@normal, path),
|
540
|
+
merge_overrides(path),
|
541
|
+
apply_path(@automatic, path),
|
542
|
+
]
|
543
|
+
|
544
|
+
components.map! do |component|
|
545
|
+
safe_dup(component)
|
546
|
+
end
|
547
|
+
|
548
|
+
return nil if components.compact.empty?
|
549
|
+
|
550
|
+
components.inject(ImmutableMash.new({})) do |merged, component|
|
551
|
+
Chef::Mixin::DeepMerge.hash_only_merge!(merged, component)
|
384
552
|
end
|
385
553
|
end
|
386
554
|
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
555
|
+
# Deep merge the default attribute levels with array merging.
|
556
|
+
#
|
557
|
+
# The path allows for selectively deep-merging a subtree of the node object.
|
558
|
+
#
|
559
|
+
# @param path [Array] Array of args to method chain to descend into the node object
|
560
|
+
# @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
|
561
|
+
def merge_defaults(path)
|
562
|
+
DEFAULT_COMPONENTS.inject(nil) do |merged, component_ivar|
|
563
|
+
component_value = apply_path(instance_variable_get(component_ivar), path)
|
564
|
+
Chef::Mixin::DeepMerge.deep_merge(component_value, merged)
|
391
565
|
end
|
392
566
|
end
|
393
567
|
|
568
|
+
# Deep merge the override attribute levels with array merging.
|
569
|
+
#
|
570
|
+
# The path allows for selectively deep-merging a subtree of the node object.
|
571
|
+
#
|
572
|
+
# @param path [Array] Array of args to method chain to descend into the node object
|
573
|
+
# @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
|
574
|
+
def merge_overrides(path)
|
575
|
+
OVERRIDE_COMPONENTS.inject(nil) do |merged, component_ivar|
|
576
|
+
component_value = apply_path(instance_variable_get(component_ivar), path)
|
577
|
+
Chef::Mixin::DeepMerge.deep_merge(component_value, merged)
|
578
|
+
end
|
579
|
+
end
|
394
580
|
|
395
581
|
end
|
396
582
|
|