chef 13.7.16 → 13.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/distro/common/man/man8/chef-solo.8 +1 -1
- data/lib/chef/chef_fs/data_handler/organization_invites_data_handler.rb +1 -1
- data/lib/chef/knife/bootstrap.rb +1 -1
- data/lib/chef/knife/search.rb +3 -1
- data/lib/chef/knife/ssh.rb +5 -7
- data/lib/chef/node/attribute.rb +70 -46
- data/lib/chef/node/attribute_collections.rb +5 -5
- data/lib/chef/node/common_api.rb +1 -1
- data/lib/chef/node/immutable_collections.rb +23 -180
- data/lib/chef/node/mixin/state_tracking.rb +6 -6
- data/lib/chef/node_map.rb +26 -0
- data/lib/chef/provider/remote_file/http.rb +8 -3
- data/lib/chef/resource/log.rb +1 -1
- data/lib/chef/resource/windows_task.rb +4 -4
- data/lib/chef/version.rb +1 -1
- data/spec/functional/mixin/powershell_out_spec.rb +5 -21
- data/spec/spec_helper.rb +19 -1
- data/spec/unit/daemon_spec.rb +21 -12
- data/spec/unit/mixin/powershell_type_coercions_spec.rb +6 -7
- data/spec/unit/node/attribute_spec.rb +24 -55
- data/spec/unit/node/immutable_collections_spec.rb +16 -30
- data/spec/unit/node/vivid_mash_spec.rb +10 -27
- data/spec/unit/node_map_spec.rb +29 -4
- data/spec/unit/provider/remote_file/http_spec.rb +6 -8
- data/spec/unit/resource/windows_task_spec.rb +9 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cf91005817c8edd084d2eef52e54b9a320c79e8
|
4
|
+
data.tar.gz: d64f227f12314884d0f77a6a16fac2465251cd1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6593a7a47e0e16c9bae832c21f7fe19eab191fb005160f8094b88303a42bb8c0709e806c9d35a18ae15155782b1936454c58ec426089c995ceafe8fd95442da6
|
7
|
+
data.tar.gz: 802c38b93e6acf6e95961f854aa14ae65eed72f8d4b64b4dd80ba7835812b87ae3239ee657cb2f501ff40987ae872908cb2106c7451e98b06f8dca1aaeed7f74
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
13.
|
1
|
+
13.8.0
|
@@ -79,7 +79,7 @@ The configuration file to use.
|
|
79
79
|
.B \fB\-d\fP, \fB\-\-daemonize\fP
|
80
80
|
Use to run the executable as a daemon. This option may not be used in the same command with the \fB\-\-[no\-]fork\fP option.
|
81
81
|
.sp
|
82
|
-
This option is only available on machines that run in UNIX or Linux environments. For machines that are running Microsoft Windows that require similar functionality, use the \fBchef\-client::service\fP recipe in the \fBchef\-client\fP cookbook: \fI\%http://community.opscode.com/cookbooks/chef\-client\fP\&.
|
82
|
+
This option is only available on machines that run in UNIX or Linux environments. For machines that are running Microsoft Windows that require similar functionality, use the \fBchef\-client::service\fP recipe in the \fBchef\-client\fP cookbook: \fI\%http://community.opscode.com/cookbooks/chef\-client\fP\&. This will install a chef\-client service under Microsoft Windows using the Windows Service Wrapper\&.
|
83
83
|
.TP
|
84
84
|
.B \fB\-E ENVIRONMENT_NAME\fP, \fB\-\-environment ENVIRONMENT_NAME\fP
|
85
85
|
The name of the environment.
|
@@ -5,7 +5,7 @@ class Chef
|
|
5
5
|
module DataHandler
|
6
6
|
class OrganizationInvitesDataHandler < DataHandlerBase
|
7
7
|
def normalize(invites, entry)
|
8
|
-
invites.map { |invite| invite.is_a?(Hash) ? invite["username"] : invite }.sort.uniq
|
8
|
+
invites.map { |invite| invite.is_a?(Hash) ? invite["username"] : invite }.compact.sort.uniq
|
9
9
|
end
|
10
10
|
|
11
11
|
def minimize(invites, entry)
|
data/lib/chef/knife/bootstrap.rb
CHANGED
@@ -448,7 +448,7 @@ class Chef
|
|
448
448
|
ssh.config[:ssh_identity_file] = config[:ssh_identity_file] || config[:identity_file]
|
449
449
|
ssh.config[:manual] = true
|
450
450
|
ssh.config[:host_key_verify] = config[:host_key_verify]
|
451
|
-
ssh.config[:on_error] =
|
451
|
+
ssh.config[:on_error] = true
|
452
452
|
ssh
|
453
453
|
end
|
454
454
|
|
data/lib/chef/knife/search.rb
CHANGED
@@ -98,7 +98,9 @@ class Chef
|
|
98
98
|
begin
|
99
99
|
q.search(@type, @query, search_args) do |item|
|
100
100
|
formatted_item = Hash.new
|
101
|
-
if
|
101
|
+
if config[:id_only]
|
102
|
+
formatted_item = format_for_display({ "id" => item["__display_name"] })
|
103
|
+
elsif item.is_a?(Hash)
|
102
104
|
# doing a little magic here to set the correct name
|
103
105
|
formatted_item[item["__display_name"]] = item.reject { |k| k == "__display_name" }
|
104
106
|
else
|
data/lib/chef/knife/ssh.rb
CHANGED
@@ -125,7 +125,7 @@ class Chef
|
|
125
125
|
:long => "--exit-on-error",
|
126
126
|
:description => "Immediately exit if an error is encountered",
|
127
127
|
:boolean => true,
|
128
|
-
:
|
128
|
+
:default => false
|
129
129
|
|
130
130
|
option :tmux_split,
|
131
131
|
:long => "--tmux-split",
|
@@ -134,15 +134,13 @@ class Chef
|
|
134
134
|
:default => false
|
135
135
|
|
136
136
|
def session
|
137
|
-
config[:on_error] ||= :skip
|
138
137
|
ssh_error_handler = Proc.new do |server|
|
139
|
-
|
140
|
-
when :skip
|
141
|
-
ui.warn "Failed to connect to #{server.host} -- #{$!.class.name}: #{$!.message}"
|
142
|
-
$!.backtrace.each { |l| Chef::Log.debug(l) }
|
143
|
-
when :raise
|
138
|
+
if config[:on_error]
|
144
139
|
#Net::SSH::Multi magic to force exception to be re-raised.
|
145
140
|
throw :go, :raise
|
141
|
+
else
|
142
|
+
ui.warn "Failed to connect to #{server.host} -- #{$!.class.name}: #{$!.message}"
|
143
|
+
$!.backtrace.each { |l| Chef::Log.debug(l) }
|
146
144
|
end
|
147
145
|
end
|
148
146
|
|
data/lib/chef/node/attribute.rb
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
+
require "chef/node/mixin/deep_merge_cache"
|
20
21
|
require "chef/node/mixin/immutablize_hash"
|
21
22
|
require "chef/node/mixin/state_tracking"
|
22
23
|
require "chef/node/immutable_collections"
|
@@ -44,6 +45,7 @@ class Chef
|
|
44
45
|
# expects. This include should probably be deleted?
|
45
46
|
include Enumerable
|
46
47
|
|
48
|
+
include Chef::Node::Mixin::DeepMergeCache
|
47
49
|
include Chef::Node::Mixin::StateTracking
|
48
50
|
include Chef::Node::Mixin::ImmutablizeHash
|
49
51
|
|
@@ -185,9 +187,6 @@ class Chef
|
|
185
187
|
# return the automatic level attribute component
|
186
188
|
attr_reader :automatic
|
187
189
|
|
188
|
-
# return the immutablemash deep merge cache
|
189
|
-
attr_reader :deep_merge_cache
|
190
|
-
|
191
190
|
def initialize(normal, default, override, automatic, node = nil)
|
192
191
|
@default = VividMash.new(default, self, node, :default)
|
193
192
|
@env_default = VividMash.new({}, self, node, :env_default)
|
@@ -203,8 +202,7 @@ class Chef
|
|
203
202
|
|
204
203
|
@automatic = VividMash.new(automatic, self, node, :automatic)
|
205
204
|
|
206
|
-
|
207
|
-
@__node__ = node
|
205
|
+
super(nil, self, node, :merged)
|
208
206
|
end
|
209
207
|
|
210
208
|
# Debug what's going on with an attribute. +args+ is a path spec to the
|
@@ -228,22 +226,6 @@ class Chef
|
|
228
226
|
end
|
229
227
|
end
|
230
228
|
|
231
|
-
def reset
|
232
|
-
@deep_merge_cache = ImmutableMash.new({}, self, @__node__, :merged)
|
233
|
-
end
|
234
|
-
|
235
|
-
def reset_cache(*path)
|
236
|
-
if path.empty?
|
237
|
-
reset
|
238
|
-
else
|
239
|
-
container = read(*path)
|
240
|
-
case container
|
241
|
-
when Hash, Array
|
242
|
-
container.reset
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
229
|
# Set the cookbook level default attribute component to +new_data+.
|
248
230
|
def default=(new_data)
|
249
231
|
reset
|
@@ -308,7 +290,7 @@ class Chef
|
|
308
290
|
|
309
291
|
# clears attributes from all precedence levels
|
310
292
|
def rm(*args)
|
311
|
-
with_deep_merged_return_value(
|
293
|
+
with_deep_merged_return_value(self, *args) do
|
312
294
|
rm_default(*args)
|
313
295
|
rm_normal(*args)
|
314
296
|
rm_override(*args)
|
@@ -355,9 +337,6 @@ class Chef
|
|
355
337
|
def with_deep_merged_return_value(obj, *path, last)
|
356
338
|
hash = obj.read(*path)
|
357
339
|
return nil unless hash.is_a?(Hash)
|
358
|
-
# coerce from immutablemash/vividmash to plain-old Hash
|
359
|
-
# also de-immutablizes and dup's the return value correctly in chef-13
|
360
|
-
hash = hash.to_hash
|
361
340
|
ret = hash[last]
|
362
341
|
yield
|
363
342
|
ret
|
@@ -419,16 +398,16 @@ class Chef
|
|
419
398
|
# all of node['foo'] even if the user only requires node['foo']['bar']['baz'].
|
420
399
|
#
|
421
400
|
|
422
|
-
def
|
423
|
-
|
401
|
+
def merged_attributes(*path)
|
402
|
+
merge_all(path)
|
424
403
|
end
|
425
404
|
|
426
|
-
def
|
427
|
-
|
405
|
+
def combined_override(*path)
|
406
|
+
immutablize(merge_overrides(path))
|
428
407
|
end
|
429
408
|
|
430
409
|
def combined_default(*path)
|
431
|
-
merge_defaults(path)
|
410
|
+
immutablize(merge_defaults(path))
|
432
411
|
end
|
433
412
|
|
434
413
|
def normal_unless(*args)
|
@@ -497,14 +476,6 @@ class Chef
|
|
497
476
|
merged_attributes.to_s
|
498
477
|
end
|
499
478
|
|
500
|
-
def [](key)
|
501
|
-
@deep_merge_cache[key]
|
502
|
-
end
|
503
|
-
|
504
|
-
def merged_attributes
|
505
|
-
@deep_merge_cache
|
506
|
-
end
|
507
|
-
|
508
479
|
def inspect
|
509
480
|
"#<#{self.class} " << (COMPONENTS + [:@merged_attributes, :@properties]).map do |iv|
|
510
481
|
"#{iv}=#{instance_variable_get(iv).inspect}"
|
@@ -513,14 +484,7 @@ class Chef
|
|
513
484
|
|
514
485
|
private
|
515
486
|
|
516
|
-
|
517
|
-
def safe_dup(e)
|
518
|
-
e.dup
|
519
|
-
rescue TypeError
|
520
|
-
e
|
521
|
-
end
|
522
|
-
|
523
|
-
# Helper method for merge_defaults/merge_overrides.
|
487
|
+
# Helper method for merge_all/merge_defaults/merge_overrides.
|
524
488
|
#
|
525
489
|
# apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"]
|
526
490
|
#
|
@@ -550,6 +514,34 @@ class Chef
|
|
550
514
|
end
|
551
515
|
end
|
552
516
|
|
517
|
+
# For elements like Fixnums, true, nil...
|
518
|
+
def safe_dup(e)
|
519
|
+
e.dup
|
520
|
+
rescue TypeError
|
521
|
+
e
|
522
|
+
end
|
523
|
+
|
524
|
+
# Deep merge all attribute levels using hash-only merging between different precidence
|
525
|
+
# levels (so override arrays completely replace arrays set at any default level).
|
526
|
+
#
|
527
|
+
# The path allows for selectively deep-merging a subtree of the node object.
|
528
|
+
#
|
529
|
+
# @param path [Array] Array of args to method chain to descend into the node object
|
530
|
+
# @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
|
531
|
+
def merge_all(path)
|
532
|
+
components = [
|
533
|
+
merge_defaults(path),
|
534
|
+
apply_path(@normal, path),
|
535
|
+
merge_overrides(path),
|
536
|
+
apply_path(@automatic, path),
|
537
|
+
]
|
538
|
+
|
539
|
+
ret = components.inject(NIL) do |merged, component|
|
540
|
+
hash_only_merge!(merged, component)
|
541
|
+
end
|
542
|
+
ret == NIL ? nil : ret
|
543
|
+
end
|
544
|
+
|
553
545
|
# Deep merge the default attribute levels with array merging.
|
554
546
|
#
|
555
547
|
# The path allows for selectively deep-merging a subtree of the node object.
|
@@ -621,6 +613,38 @@ class Chef
|
|
621
613
|
end
|
622
614
|
end
|
623
615
|
|
616
|
+
# @api private
|
617
|
+
def hash_only_merge!(merge_onto, merge_with)
|
618
|
+
# If there are two Hashes, recursively merge.
|
619
|
+
if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash)
|
620
|
+
merge_with.each do |key, merge_with_value|
|
621
|
+
value =
|
622
|
+
if merge_onto.has_key?(key)
|
623
|
+
hash_only_merge!(safe_dup(merge_onto[key]), merge_with_value)
|
624
|
+
else
|
625
|
+
merge_with_value
|
626
|
+
end
|
627
|
+
|
628
|
+
# internal_set bypasses converting keys, does convert values and allows writing to immutable mashes
|
629
|
+
merge_onto.internal_set(key, value)
|
630
|
+
end
|
631
|
+
merge_onto
|
632
|
+
|
633
|
+
# If merge_with is nil, don't replace merge_onto
|
634
|
+
elsif merge_with.nil?
|
635
|
+
merge_onto
|
636
|
+
|
637
|
+
# In all other cases, replace merge_onto with merge_with
|
638
|
+
else
|
639
|
+
if merge_with.kind_of?(Hash)
|
640
|
+
Chef::Node::ImmutableMash.new(merge_with)
|
641
|
+
elsif merge_with.kind_of?(Array)
|
642
|
+
Chef::Node::ImmutableArray.new(merge_with)
|
643
|
+
else
|
644
|
+
merge_with
|
645
|
+
end
|
646
|
+
end
|
647
|
+
end
|
624
648
|
end
|
625
649
|
end
|
626
650
|
end
|
@@ -63,13 +63,13 @@ class Chef
|
|
63
63
|
MUTATOR_METHODS.each do |mutator|
|
64
64
|
define_method(mutator) do |*args, &block|
|
65
65
|
ret = super(*args, &block)
|
66
|
-
send_reset_cache
|
66
|
+
send_reset_cache
|
67
67
|
ret
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
def delete(key, &block)
|
72
|
-
send_reset_cache(__path__)
|
72
|
+
send_reset_cache(__path__, key)
|
73
73
|
super
|
74
74
|
end
|
75
75
|
|
@@ -147,13 +147,13 @@ class Chef
|
|
147
147
|
# object.
|
148
148
|
|
149
149
|
def delete(key, &block)
|
150
|
-
send_reset_cache(__path__)
|
150
|
+
send_reset_cache(__path__, key)
|
151
151
|
super
|
152
152
|
end
|
153
153
|
|
154
154
|
MUTATOR_METHODS.each do |mutator|
|
155
155
|
define_method(mutator) do |*args, &block|
|
156
|
-
send_reset_cache
|
156
|
+
send_reset_cache
|
157
157
|
super(*args, &block)
|
158
158
|
end
|
159
159
|
end
|
@@ -174,7 +174,7 @@ class Chef
|
|
174
174
|
|
175
175
|
def []=(key, value)
|
176
176
|
ret = super
|
177
|
-
send_reset_cache(__path__)
|
177
|
+
send_reset_cache(__path__, key)
|
178
178
|
ret
|
179
179
|
end
|
180
180
|
|
data/lib/chef/node/common_api.rb
CHANGED
@@ -30,16 +30,22 @@ class Chef
|
|
30
30
|
e
|
31
31
|
end
|
32
32
|
|
33
|
-
def convert_value(value
|
33
|
+
def convert_value(value)
|
34
34
|
case value
|
35
35
|
when Hash
|
36
|
-
ImmutableMash.new(
|
36
|
+
ImmutableMash.new(value, __root__, __node__, __precedence__)
|
37
37
|
when Array
|
38
|
-
ImmutableArray.new(
|
38
|
+
ImmutableArray.new(value, __root__, __node__, __precedence__)
|
39
|
+
when ImmutableMash, ImmutableArray
|
40
|
+
value
|
39
41
|
else
|
40
42
|
safe_dup(value).freeze
|
41
43
|
end
|
42
44
|
end
|
45
|
+
|
46
|
+
def immutablize(value)
|
47
|
+
convert_value(value)
|
48
|
+
end
|
43
49
|
end
|
44
50
|
|
45
51
|
# == ImmutableArray
|
@@ -53,49 +59,15 @@ class Chef
|
|
53
59
|
# Chef::Node::Attribute's values, it overrides all reader methods to
|
54
60
|
# detect staleness and raise an error if accessed when stale.
|
55
61
|
class ImmutableArray < Array
|
56
|
-
alias_method :internal_clear, :clear
|
57
|
-
alias_method :internal_replace, :replace
|
58
|
-
alias_method :internal_push, :<<
|
59
|
-
alias_method :internal_to_a, :to_a
|
60
|
-
alias_method :internal_each, :each
|
61
|
-
private :internal_push, :internal_replace, :internal_clear, :internal_each
|
62
|
-
protected :internal_to_a
|
63
|
-
|
64
62
|
include Immutablize
|
65
63
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
methods.each do |method|
|
70
|
-
define_method method do |*args, &block|
|
71
|
-
ensure_generated_cache!
|
72
|
-
super(*args, &block)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def each
|
77
|
-
ensure_generated_cache!
|
78
|
-
# aggressively pre generate the cache, works around ruby being too smart and fiddling with internals
|
79
|
-
internal_each { |i| i.ensure_generated_cache! if i.respond_to?(:ensure_generated_cache!) }
|
80
|
-
super
|
81
|
-
end
|
82
|
-
|
83
|
-
# because sometimes ruby gives us back Arrays or ImmutableArrays out of objects from things like #uniq or array slices
|
84
|
-
def return_normal_array(array)
|
85
|
-
if array.respond_to?(:internal_to_a, true)
|
86
|
-
array.internal_to_a
|
87
|
-
else
|
88
|
-
array.to_a
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def uniq
|
93
|
-
ensure_generated_cache!
|
94
|
-
return_normal_array(super)
|
95
|
-
end
|
64
|
+
alias :internal_push :<<
|
65
|
+
private :internal_push
|
96
66
|
|
97
67
|
def initialize(array_data = [])
|
98
|
-
|
68
|
+
array_data.each do |value|
|
69
|
+
internal_push(immutablize(value))
|
70
|
+
end
|
99
71
|
end
|
100
72
|
|
101
73
|
# For elements like Fixnums, true, nil...
|
@@ -124,81 +96,8 @@ class Chef
|
|
124
96
|
|
125
97
|
alias_method :to_array, :to_a
|
126
98
|
|
127
|
-
def [](*args)
|
128
|
-
ensure_generated_cache!
|
129
|
-
args.length > 1 ? return_normal_array(super) : super # correctly handle array slices
|
130
|
-
end
|
131
|
-
|
132
|
-
def reset
|
133
|
-
@generated_cache = false
|
134
|
-
@short_circuit_attr_level = nil
|
135
|
-
internal_clear # redundant?
|
136
|
-
end
|
137
|
-
|
138
|
-
# @api private
|
139
|
-
def ensure_generated_cache!
|
140
|
-
generate_cache unless @generated_cache
|
141
|
-
@generated_cache = true
|
142
|
-
end
|
143
|
-
|
144
|
-
# This can be set to e.g. [ :@default ] by the parent container to cause this container
|
145
|
-
# to only use the default level and to bypass deep merging (the common case is either
|
146
|
-
# default-level or automatic-level and we aren't doing any deep merging). Right now it
|
147
|
-
# "optimized" for the case where we're no longer merging anything and only tracking a
|
148
|
-
# single level, and setting this to anything other than a size=1 array would behave
|
149
|
-
# in a broken fashion. That could be fixed, but the perf boost would likely not be
|
150
|
-
# that large in the typical case.
|
151
|
-
#
|
152
|
-
# @api private
|
153
|
-
attr_accessor :short_circuit_attr_levels
|
154
|
-
|
155
99
|
private
|
156
100
|
|
157
|
-
# deep merging of array attribute within normal and override where they are merged together
|
158
|
-
def combined_components(components)
|
159
|
-
combined_values = nil
|
160
|
-
components.each do |component|
|
161
|
-
values = __node__.attributes.instance_variable_get(component).read(*__path__)
|
162
|
-
next unless values.is_a?(Array)
|
163
|
-
@tracked_components << component
|
164
|
-
combined_values ||= []
|
165
|
-
combined_values += values
|
166
|
-
end
|
167
|
-
combined_values
|
168
|
-
end
|
169
|
-
|
170
|
-
def get_array(component)
|
171
|
-
array = __node__.attributes.instance_variable_get(component).read(*__path__)
|
172
|
-
if array.is_a?(Array)
|
173
|
-
@tracked_components << component
|
174
|
-
array
|
175
|
-
end # else nil
|
176
|
-
end
|
177
|
-
|
178
|
-
def generate_cache
|
179
|
-
internal_clear
|
180
|
-
components = []
|
181
|
-
@tracked_components = []
|
182
|
-
if short_circuit_attr_levels
|
183
|
-
components << get_array(short_circuit_attr_levels.first)
|
184
|
-
else
|
185
|
-
components << combined_components(Attribute::DEFAULT_COMPONENTS)
|
186
|
-
components << get_array(:@normal)
|
187
|
-
components << combined_components(Attribute::OVERRIDE_COMPONENTS)
|
188
|
-
components << get_array(:@automatic)
|
189
|
-
end
|
190
|
-
highest = components.compact.last
|
191
|
-
if highest.is_a?(Array)
|
192
|
-
internal_replace( highest.each_with_index.map { |x, i| convert_value(x, __path__ + [ i ] ) } )
|
193
|
-
end
|
194
|
-
if @tracked_components.size == 1
|
195
|
-
# tracked_components is accurate enough to tell us if we're not really merging
|
196
|
-
internal_each do |key, value|
|
197
|
-
value.short_circuit_attr_levels = @tracked_components if value.respond_to?(:short_circuit_attr_levels)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
101
|
# needed for __path__
|
203
102
|
def convert_key(key)
|
204
103
|
key
|
@@ -221,31 +120,19 @@ class Chef
|
|
221
120
|
# it is stale.
|
222
121
|
# * Values can be accessed in attr_reader-like fashion via method_missing.
|
223
122
|
class ImmutableMash < Mash
|
224
|
-
alias_method :internal_clear, :clear
|
225
|
-
alias_method :internal_key?, :key? # FIXME: could bypass convert_key in Mash for perf
|
226
|
-
alias_method :internal_each, :each
|
227
|
-
|
228
123
|
include Immutablize
|
229
124
|
include CommonAPI
|
230
125
|
|
231
|
-
methods = Hash.instance_methods - Object.instance_methods +
|
232
|
-
[ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key?, :inspect, :pretty_print, :pretty_print_inspect, :pretty_print_cycle, :pretty_print_instance_variables ]
|
233
|
-
|
234
|
-
methods.each do |method|
|
235
|
-
define_method method do |*args, &block|
|
236
|
-
ensure_generated_cache!
|
237
|
-
super(*args, &block)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
126
|
# this is for deep_merge usage, chef users must never touch this API
|
242
127
|
# @api private
|
243
128
|
def internal_set(key, value)
|
244
|
-
regular_writer(key, convert_value(value
|
129
|
+
regular_writer(key, convert_value(value))
|
245
130
|
end
|
246
131
|
|
247
132
|
def initialize(mash_data = {})
|
248
|
-
|
133
|
+
mash_data.each do |key, value|
|
134
|
+
internal_set(key, value)
|
135
|
+
end
|
249
136
|
end
|
250
137
|
|
251
138
|
alias :attribute? :has_key?
|
@@ -281,55 +168,11 @@ class Chef
|
|
281
168
|
|
282
169
|
alias_method :to_hash, :to_h
|
283
170
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
alias_method :to_hash, :to_h
|
290
|
-
|
291
|
-
def reset
|
292
|
-
@generated_cache = false
|
293
|
-
@short_circuit_attr_level = nil
|
294
|
-
internal_clear # redundant?
|
295
|
-
end
|
296
|
-
|
297
|
-
# @api private
|
298
|
-
def ensure_generated_cache!
|
299
|
-
generate_cache unless @generated_cache
|
300
|
-
@generated_cache = true
|
301
|
-
end
|
302
|
-
|
303
|
-
# @api private
|
304
|
-
attr_accessor :short_circuit_attr_levels
|
305
|
-
|
306
|
-
private
|
307
|
-
|
308
|
-
def generate_cache
|
309
|
-
internal_clear
|
310
|
-
components = short_circuit_attr_levels ? short_circuit_attr_levels : Attribute::COMPONENTS.reverse
|
311
|
-
# tracked_components is not entirely accurate due to the short-circuit
|
312
|
-
tracked_components = []
|
313
|
-
components.each do |component|
|
314
|
-
subhash = __node__.attributes.instance_variable_get(component).read(*__path__)
|
315
|
-
unless subhash.nil? # FIXME: nil is used for not present
|
316
|
-
tracked_components << component
|
317
|
-
if subhash.kind_of?(Hash)
|
318
|
-
subhash.keys.each do |key|
|
319
|
-
next if internal_key?(key)
|
320
|
-
internal_set(key, subhash[key])
|
321
|
-
end
|
322
|
-
else
|
323
|
-
break
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
327
|
-
if tracked_components.size == 1
|
328
|
-
# tracked_components is accurate enough to tell us if we're not really merging
|
329
|
-
internal_each do |key, value|
|
330
|
-
value.short_circuit_attr_levels = tracked_components if value.respond_to?(:short_circuit_attr_levels)
|
331
|
-
end
|
332
|
-
end
|
171
|
+
# For elements like Fixnums, true, nil...
|
172
|
+
def safe_dup(e)
|
173
|
+
e.dup
|
174
|
+
rescue TypeError
|
175
|
+
e
|
333
176
|
end
|
334
177
|
|
335
178
|
prepend Chef::Node::Mixin::StateTracking
|