chef 12.11.18-universal-mingw32 → 12.12.13-universal-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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/Rakefile +3 -2
  4. data/VERSION +1 -1
  5. data/acceptance/Gemfile.lock +22 -23
  6. data/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb +2 -41
  7. data/lib/chef/application/solo.rb +7 -0
  8. data/lib/chef/chef_fs/file_system/multiplexed_dir.rb +1 -1
  9. data/lib/chef/data_collector.rb +79 -43
  10. data/lib/chef/data_collector/messages.rb +4 -33
  11. data/lib/chef/data_collector/messages/helpers.rb +2 -2
  12. data/lib/chef/data_collector/resource_report.rb +21 -11
  13. data/lib/chef/decorator/unchain.rb +43 -0
  14. data/lib/chef/exceptions.rb +5 -0
  15. data/lib/chef/http.rb +5 -5
  16. data/lib/chef/knife/cookbook_create.rb +4 -0
  17. data/lib/chef/knife/cookbook_site_download.rb +8 -1
  18. data/lib/chef/knife/cookbook_site_install.rb +8 -0
  19. data/lib/chef/knife/cookbook_site_list.rb +8 -1
  20. data/lib/chef/knife/cookbook_site_search.rb +8 -1
  21. data/lib/chef/knife/cookbook_site_share.rb +8 -1
  22. data/lib/chef/knife/cookbook_site_show.rb +14 -3
  23. data/lib/chef/knife/cookbook_site_unshare.rb +8 -1
  24. data/lib/chef/knife/core/bootstrap_context.rb +1 -1
  25. data/lib/chef/knife/supermarket_download.rb +33 -0
  26. data/lib/chef/knife/supermarket_install.rb +33 -0
  27. data/lib/chef/knife/supermarket_list.rb +33 -0
  28. data/lib/chef/knife/supermarket_search.rb +33 -0
  29. data/lib/chef/knife/supermarket_share.rb +33 -0
  30. data/lib/chef/knife/supermarket_show.rb +33 -0
  31. data/lib/chef/knife/supermarket_unshare.rb +33 -0
  32. data/lib/chef/node.rb +13 -32
  33. data/lib/chef/node/attribute.rb +123 -70
  34. data/lib/chef/node/attribute_collections.rb +9 -130
  35. data/lib/chef/node/common_api.rb +124 -0
  36. data/lib/chef/node/immutable_collections.rb +27 -2
  37. data/lib/chef/property.rb +6 -2
  38. data/lib/chef/provider.rb +4 -5
  39. data/lib/chef/provider/batch.rb +1 -1
  40. data/lib/chef/provider/directory.rb +3 -1
  41. data/lib/chef/provider/package/openbsd.rb +1 -1
  42. data/lib/chef/provider/package/rubygems.rb +9 -3
  43. data/lib/chef/provider/package/windows/exe.rb +2 -5
  44. data/lib/chef/provider/powershell_script.rb +1 -1
  45. data/lib/chef/provider/remote_directory.rb +2 -0
  46. data/lib/chef/resource.rb +22 -17
  47. data/lib/chef/resource_builder.rb +9 -4
  48. data/lib/chef/shell.rb +1 -1
  49. data/lib/chef/version.rb +1 -1
  50. data/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb +2 -4
  51. data/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb +2 -3
  52. data/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb +2 -2
  53. data/spec/data/run_context/cookbooks/dependency1/attributes/default.rb +2 -2
  54. data/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb +2 -3
  55. data/spec/data/run_context/cookbooks/dependency2/attributes/default.rb +2 -3
  56. data/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb +2 -3
  57. data/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb +2 -3
  58. data/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb +2 -3
  59. data/spec/functional/assets/chocolatey_feed/test-A.1.0.nupkg +0 -0
  60. data/spec/functional/assets/chocolatey_feed/test-A.1.5.nupkg +0 -0
  61. data/spec/functional/assets/chocolatey_feed/test-A.2.0.nupkg +0 -0
  62. data/spec/functional/assets/chocolatey_feed/test-B.1.0.nupkg +0 -0
  63. data/spec/functional/resource/dsc_script_spec.rb +1 -0
  64. data/spec/functional/resource/package_spec.rb +1 -1
  65. data/spec/functional/resource/template_spec.rb +3 -3
  66. data/spec/functional/shell_spec.rb +1 -1
  67. data/spec/integration/knife/client_bulk_delete_spec.rb +130 -0
  68. data/spec/integration/knife/client_create_spec.rb +69 -0
  69. data/spec/integration/knife/client_delete_spec.rb +63 -0
  70. data/spec/integration/knife/client_key_create_spec.rb +65 -0
  71. data/spec/integration/knife/client_key_delete_spec.rb +42 -0
  72. data/spec/integration/knife/client_key_list_spec.rb +60 -0
  73. data/spec/integration/knife/client_key_show_spec.rb +44 -0
  74. data/spec/integration/knife/client_list_spec.rb +48 -0
  75. data/spec/integration/knife/client_show_spec.rb +36 -0
  76. data/spec/integration/knife/cookbook_bulk_delete_spec.rb +64 -0
  77. data/spec/integration/knife/cookbook_download_spec.rb +95 -0
  78. data/spec/integration/knife/cookbook_list_spec.rb +54 -0
  79. data/spec/integration/knife/cookbook_show_spec.rb +159 -0
  80. data/spec/integration/knife/cookbook_upload_spec.rb +90 -0
  81. data/spec/integration/knife/data_bag_create_spec.rb +58 -0
  82. data/spec/integration/knife/data_bag_delete_spec.rb +58 -0
  83. data/spec/integration/knife/data_bag_from_file_spec.rb +115 -0
  84. data/spec/integration/knife/data_bag_list_spec.rb +43 -0
  85. data/spec/integration/knife/data_bag_show_spec.rb +53 -0
  86. data/spec/integration/knife/environment_compare_spec.rb +74 -0
  87. data/spec/integration/knife/environment_create_spec.rb +40 -0
  88. data/spec/integration/knife/environment_delete_spec.rb +36 -0
  89. data/spec/integration/knife/environment_from_file_spec.rb +115 -0
  90. data/spec/integration/knife/environment_list_spec.rb +41 -0
  91. data/spec/integration/knife/environment_show_spec.rb +56 -0
  92. data/spec/integration/knife/node_bulk_delete_spec.rb +51 -0
  93. data/spec/integration/knife/node_create_spec.rb +46 -0
  94. data/spec/integration/knife/node_delete_spec.rb +47 -0
  95. data/spec/integration/knife/node_environment_set_spec.rb +42 -0
  96. data/spec/integration/knife/node_from_file_spec.rb +58 -0
  97. data/spec/integration/knife/node_list_spec.rb +44 -0
  98. data/spec/integration/knife/node_run_list_add_spec.rb +53 -0
  99. data/spec/integration/knife/node_run_list_remove_spec.rb +35 -0
  100. data/spec/integration/knife/node_run_list_set_spec.rb +40 -0
  101. data/spec/integration/knife/node_show_spec.rb +35 -0
  102. data/spec/integration/knife/role_bulk_delete_spec.rb +51 -0
  103. data/spec/integration/knife/role_create_spec.rb +40 -0
  104. data/spec/integration/knife/role_delete_spec.rb +47 -0
  105. data/spec/integration/knife/role_from_file_spec.rb +95 -0
  106. data/spec/integration/knife/role_list_spec.rb +44 -0
  107. data/spec/integration/knife/role_show_spec.rb +50 -0
  108. data/spec/support/shared/integration/knife_support.rb +10 -3
  109. data/spec/unit/application/solo_spec.rb +7 -0
  110. data/spec/unit/cookbook_version_spec.rb +4 -4
  111. data/spec/unit/data_collector/messages/helpers_spec.rb +3 -7
  112. data/spec/unit/data_collector/messages_spec.rb +28 -45
  113. data/spec/unit/data_collector_spec.rb +40 -47
  114. data/spec/unit/knife/cookbook_create_spec.rb +1 -0
  115. data/spec/unit/knife/cookbook_site_download_spec.rb +1 -0
  116. data/spec/unit/knife/node_environment_set_spec.rb +0 -24
  117. data/spec/unit/knife/node_run_list_set_spec.rb +0 -25
  118. data/spec/unit/node/attribute_spec.rb +7 -9
  119. data/spec/unit/node/immutable_collections_spec.rb +4 -0
  120. data/spec/unit/node/vivid_mash_spec.rb +344 -0
  121. data/spec/unit/node_spec.rb +115 -26
  122. data/spec/unit/provider/directory_spec.rb +11 -1
  123. data/spec/unit/provider/package/windows/exe_spec.rb +14 -9
  124. data/spec/unit/provider/powershell_script_spec.rb +4 -4
  125. data/spec/unit/provider/remote_directory_spec.rb +15 -0
  126. data/spec/unit/recipe_spec.rb +31 -6
  127. data/spec/unit/run_context_spec.rb +2 -2
  128. data/spec/unit/shell/shell_session_spec.rb +1 -1
  129. data/tasks/dependencies.rb +0 -2
  130. metadata +55 -786
  131. data/acceptance/.bundle/config +0 -2
  132. data/acceptance/basics/.kitchen/logs/chef-current-install-ubuntu-1404.log +0 -2
  133. data/acceptance/basics/.kitchen/logs/kitchen.log +0 -3
  134. data/acceptance/fips/.kitchen/logs/fips-integration-centos-6.log +0 -3
  135. data/acceptance/fips/.kitchen/logs/fips-integration-windows-2012r2.log +0 -3
  136. data/acceptance/fips/.kitchen/logs/fips-unit-functional-centos-6.log +0 -3
  137. data/acceptance/fips/.kitchen/logs/fips-unit-functional-windows-2012r2.log +0 -3
  138. data/acceptance/fips/.kitchen/logs/kitchen.log +0 -6
  139. data/acceptance/trivial/.kitchen/logs/chef-current-install-windows-2012r2.log +0 -2
  140. data/acceptance/trivial/.kitchen/logs/kitchen.log +0 -3
  141. data/acceptance/windows-service/.kitchen/logs/chef-windows-service-windows-2012r2.log +0 -2
  142. data/acceptance/windows-service/.kitchen/logs/kitchen.log +0 -3
@@ -0,0 +1,33 @@
1
+ #
2
+ # Author:: Christopher Webber (<cwebber@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/knife"
20
+ require "chef/knife/cookbook_site_list"
21
+
22
+ class Chef
23
+ class Knife
24
+ class SupermarketList < Knife::CookbookSiteList
25
+ # Handle the subclassing (knife doesn't do this :()
26
+ dependency_loaders.concat(superclass.dependency_loaders)
27
+ options.merge!(superclass.options)
28
+
29
+ banner "knife supermarket list (options)"
30
+ category "supermarket"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ #
2
+ # Author:: Christopher Webber (<cwebber@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/knife"
20
+ require "chef/knife/cookbook_site_search"
21
+
22
+ class Chef
23
+ class Knife
24
+ class SupermarketSearch < Knife::CookbookSiteSearch
25
+ # Handle the subclassing (knife doesn't do this :()
26
+ dependency_loaders.concat(superclass.dependency_loaders)
27
+ options.merge!(superclass.options)
28
+
29
+ banner "knife supermarket search QUERY (options)"
30
+ category "supermarket"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ #
2
+ # Author:: Christopher Webber (<cwebber@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/knife"
20
+ require "chef/knife/cookbook_site_share"
21
+
22
+ class Chef
23
+ class Knife
24
+ class SupermarketShare < Knife::CookbookSiteShare
25
+ # Handle the subclassing (knife doesn't do this :()
26
+ dependency_loaders.concat(superclass.dependency_loaders)
27
+ options.merge!(superclass.options)
28
+
29
+ banner "knife supermarket share COOKBOOK [CATEGORY] (options)"
30
+ category "supermarket"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ #
2
+ # Author:: Christopher Webber (<cwebber@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/knife"
20
+ require "chef/knife/cookbook_site_show"
21
+
22
+ class Chef
23
+ class Knife
24
+ class SupermarketShow < Knife::CookbookSiteShow
25
+ # Handle the subclassing (knife doesn't do this :()
26
+ dependency_loaders.concat(superclass.dependency_loaders)
27
+ options.merge!(superclass.options)
28
+
29
+ banner "knife supermarket show COOKBOOK [VERSION] (options)"
30
+ category "supermarket"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ #
2
+ # Author:: Christopher Webber (<cwebber@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/knife"
20
+ require "chef/knife/cookbook_site_unshare"
21
+
22
+ class Chef
23
+ class Knife
24
+ class SupermarketUnshare < Knife::CookbookSiteUnshare
25
+ # Handle the subclassing (knife doesn't do this :()
26
+ dependency_loaders.concat(superclass.dependency_loaders)
27
+ options.merge!(superclass.options)
28
+
29
+ banner "knife supermarket unshare COOKBOOK (options)"
30
+ category "supermarket"
31
+ end
32
+ end
33
+ end
@@ -43,6 +43,8 @@ class Chef
43
43
  def_delegators :attributes, :keys, :each_key, :each_value, :key?, :has_key?
44
44
  def_delegators :attributes, :rm, :rm_default, :rm_normal, :rm_override
45
45
  def_delegators :attributes, :default!, :normal!, :override!, :force_default!, :force_override!
46
+ def_delegators :attributes, :default_unless, :normal_unless, :override_unless, :set_unless
47
+ def_delegators :attributes, :read, :read!, :write, :write!, :unlink, :unlink!
46
48
 
47
49
  attr_accessor :recipe_list, :run_state, :override_runlist
48
50
 
@@ -196,35 +198,18 @@ class Chef
196
198
  # might be missing
197
199
  def normal
198
200
  attributes.top_level_breadcrumb = nil
199
- attributes.set_unless_value_present = false
200
201
  attributes.normal
201
202
  end
202
203
 
203
- alias_method :set, :normal
204
-
205
- # Set a normal attribute of this node, auto-vivifying any mashes that are
206
- # missing, but if the final value already exists, don't set it
207
- def normal_unless
208
- attributes.top_level_breadcrumb = nil
209
- attributes.set_unless_value_present = true
210
- attributes.normal
204
+ def set
205
+ Chef.log_deprecation("node.set is deprecated and will be removed in Chef 14, please use node.default/node.override (or node.normal only if you really need persistence)")
206
+ normal
211
207
  end
212
208
 
213
- alias_method :set_unless, :normal_unless
214
-
215
209
  # Set a default of this node, but auto-vivify any Mashes that might
216
210
  # be missing
217
211
  def default
218
212
  attributes.top_level_breadcrumb = nil
219
- attributes.set_unless_value_present = false
220
- attributes.default
221
- end
222
-
223
- # Set a default attribute of this node, auto-vivifying any mashes that are
224
- # missing, but if the final value already exists, don't set it
225
- def default_unless
226
- attributes.top_level_breadcrumb = nil
227
- attributes.set_unless_value_present = true
228
213
  attributes.default
229
214
  end
230
215
 
@@ -232,15 +217,6 @@ class Chef
232
217
  # might be missing
233
218
  def override
234
219
  attributes.top_level_breadcrumb = nil
235
- attributes.set_unless_value_present = false
236
- attributes.override
237
- end
238
-
239
- # Set an override attribute of this node, auto-vivifying any mashes that
240
- # are missing, but if the final value already exists, don't set it
241
- def override_unless
242
- attributes.top_level_breadcrumb = nil
243
- attributes.set_unless_value_present = true
244
220
  attributes.override
245
221
  end
246
222
 
@@ -262,7 +238,6 @@ class Chef
262
238
 
263
239
  def automatic_attrs
264
240
  attributes.top_level_breadcrumb = nil
265
- attributes.set_unless_value_present = false
266
241
  attributes.automatic
267
242
  end
268
243
 
@@ -290,8 +265,14 @@ class Chef
290
265
  end
291
266
 
292
267
  # Only works for attribute fetches, setting is no longer supported
293
- def method_missing(symbol, *args)
294
- attributes.send(symbol, *args)
268
+ # XXX: this should be deprecated
269
+ def method_missing(method, *args, &block)
270
+ attributes.public_send(method, *args, &block)
271
+ end
272
+
273
+ # Fix respond_to + method so that it works with method_missing delegation
274
+ def respond_to_missing?(method, include_private = false)
275
+ attributes.respond_to?(method, false)
295
276
  end
296
277
 
297
278
  # Returns true if this Node expects a given recipe, false if not.
@@ -19,6 +19,7 @@
19
19
 
20
20
  require "chef/node/immutable_collections"
21
21
  require "chef/node/attribute_collections"
22
+ require "chef/decorator/unchain"
22
23
  require "chef/mixin/deep_merge"
23
24
  require "chef/log"
24
25
 
@@ -132,6 +133,7 @@ class Chef
132
133
  :take,
133
134
  :take_while,
134
135
  :to_a,
136
+ :to_h,
135
137
  :to_hash,
136
138
  :to_set,
137
139
  :value?,
@@ -187,8 +189,6 @@ class Chef
187
189
  attr_accessor :deep_merge_cache
188
190
 
189
191
  def initialize(normal, default, override, automatic)
190
- @set_unless_present = false
191
-
192
192
  @default = VividMash.new(self, default)
193
193
  @env_default = VividMash.new(self, {})
194
194
  @role_default = VividMash.new(self, {})
@@ -214,15 +214,13 @@ class Chef
214
214
  # attribute you're interested in. For example, to debug where the value
215
215
  # of `node[:network][:default_interface]` is coming from, use:
216
216
  # debug_value(:network, :default_interface).
217
- # The return value is an Array of Arrays. The first element is
218
- # `["set_unless_enabled?", Boolean]`, which describes whether the
219
- # attribute collection is in "set_unless" mode. The rest of the Arrays
217
+ # The return value is an Array of Arrays. The Arrays
220
218
  # are pairs of `["precedence_level", value]`, where precedence level is
221
219
  # the component, such as role default, normal, etc. and value is the
222
220
  # attribute value set at that precedence level. If there is no value at
223
221
  # that precedence level, +value+ will be the symbol +:not_present+.
224
222
  def debug_value(*args)
225
- components = COMPONENTS.map do |component|
223
+ COMPONENTS.map do |component|
226
224
  ivar = instance_variable_get(component)
227
225
  value = args.inject(ivar) do |so_far, key|
228
226
  if so_far == :not_present
@@ -235,12 +233,6 @@ class Chef
235
233
  end
236
234
  [component.to_s.sub(/^@/, ""), value]
237
235
  end
238
- [["set_unless_enabled?", @set_unless_present]] + components
239
- end
240
-
241
- # Enables or disables `||=`-like attribute setting. See, e.g., Node#set_unless
242
- def set_unless_value_present=(setting)
243
- @set_unless_present = setting
244
236
  end
245
237
 
246
238
  # Invalidate a key in the deep_merge_cache. If called with nil, or no arg, this will invalidate
@@ -321,94 +313,134 @@ class Chef
321
313
 
322
314
  # clears attributes from all precedence levels
323
315
  def rm(*args)
324
- reset(args[0])
325
- # just easier to compute our retval, rather than collect+merge sub-retvals
326
- ret = args.inject(merged_attributes) do |attr, arg|
327
- if attr.nil? || !attr.respond_to?(:[])
328
- nil
329
- else
330
- begin
331
- attr[arg]
332
- rescue TypeError
333
- raise TypeError, "Wrong type in index of attribute (did you use a Hash index on an Array?)"
334
- end
335
- end
316
+ with_deep_merged_return_value(self, *args) do
317
+ rm_default(*args)
318
+ rm_normal(*args)
319
+ rm_override(*args)
336
320
  end
337
- rm_default(*args)
338
- rm_normal(*args)
339
- rm_override(*args)
340
- ret
341
321
  end
342
322
 
343
- # does <level>['foo']['bar'].delete('baz')
344
- def remove_from_precedence_level(level, *args, key)
345
- multimash = level.element(*args)
346
- multimash.nil? ? nil : multimash.delete(key)
347
- end
348
-
349
- private :remove_from_precedence_level
350
-
351
323
  # clears attributes from all default precedence levels
352
324
  #
353
- # equivalent to: force_default!['foo']['bar'].delete('baz')
325
+ # similar to: force_default!['foo']['bar'].delete('baz')
326
+ # - does not autovivify
327
+ # - does not trainwreck if interior keys do not exist
354
328
  def rm_default(*args)
355
- reset(args[0])
356
- remove_from_precedence_level(force_default!(autovivify: false), *args)
329
+ with_deep_merged_return_value(combined_default, *args) do
330
+ default.unlink(*args)
331
+ role_default.unlink(*args)
332
+ env_default.unlink(*args)
333
+ force_default.unlink(*args)
334
+ end
357
335
  end
358
336
 
359
337
  # clears attributes from normal precedence
360
338
  #
361
339
  # equivalent to: normal!['foo']['bar'].delete('baz')
340
+ # - does not autovivify
341
+ # - does not trainwreck if interior keys do not exist
362
342
  def rm_normal(*args)
363
- reset(args[0])
364
- remove_from_precedence_level(normal!(autovivify: false), *args)
343
+ normal.unlink(*args)
365
344
  end
366
345
 
367
346
  # clears attributes from all override precedence levels
368
347
  #
369
348
  # equivalent to: force_override!['foo']['bar'].delete('baz')
349
+ # - does not autovivify
350
+ # - does not trainwreck if interior keys do not exist
370
351
  def rm_override(*args)
371
- reset(args[0])
372
- remove_from_precedence_level(force_override!(autovivify: false), *args)
352
+ with_deep_merged_return_value(combined_override, *args) do
353
+ override.unlink(*args)
354
+ role_override.unlink(*args)
355
+ env_override.unlink(*args)
356
+ force_override.unlink(*args)
357
+ end
358
+ end
359
+
360
+ def with_deep_merged_return_value(obj, *path, last)
361
+ hash = obj.read(*path)
362
+ return nil unless hash.is_a?(Hash)
363
+ ret = hash[last]
364
+ yield
365
+ ret
373
366
  end
374
367
 
368
+ private :with_deep_merged_return_value
369
+
375
370
  #
376
371
  # Replacing attributes without merging
377
372
  #
378
373
 
379
374
  # sets default attributes without merging
380
- def default!(opts = {})
381
- # FIXME: do not flush whole cache
382
- reset
383
- MultiMash.new(self, @default, [], opts)
375
+ #
376
+ # - this API autovivifies (and cannot trainwreck)
377
+ def default!(*args)
378
+ return Decorator::Unchain.new(self, :default!) unless args.length > 0
379
+ write(:default, *args)
384
380
  end
385
381
 
386
382
  # sets normal attributes without merging
387
- def normal!(opts = {})
388
- # FIXME: do not flush whole cache
389
- reset
390
- MultiMash.new(self, @normal, [], opts)
383
+ #
384
+ # - this API autovivifies (and cannot trainwreck)
385
+ def normal!(*args)
386
+ return Decorator::Unchain.new(self, :normal!) unless args.length > 0
387
+ write(:normal, *args)
391
388
  end
392
389
 
393
390
  # sets override attributes without merging
394
- def override!(opts = {})
395
- # FIXME: do not flush whole cache
396
- reset
397
- MultiMash.new(self, @override, [], opts)
391
+ #
392
+ # - this API autovivifies (and cannot trainwreck)
393
+ def override!(*args)
394
+ return Decorator::Unchain.new(self, :override!) unless args.length > 0
395
+ write(:override, *args)
398
396
  end
399
397
 
400
398
  # clears from all default precedence levels and then sets force_default
401
- def force_default!(opts = {})
402
- # FIXME: do not flush whole cache
403
- reset
404
- MultiMash.new(self, @force_default, [@default, @env_default, @role_default], opts)
399
+ #
400
+ # - this API autovivifies (and cannot trainwreck)
401
+ def force_default!(*args)
402
+ return Decorator::Unchain.new(self, :force_default!) unless args.length > 0
403
+ value = args.pop
404
+ rm_default(*args)
405
+ write(:force_default, *args, value)
405
406
  end
406
407
 
407
408
  # clears from all override precedence levels and then sets force_override
408
- def force_override!(opts = {})
409
- # FIXME: do not flush whole cache
410
- reset
411
- MultiMash.new(self, @force_override, [@override, @env_override, @role_override], opts)
409
+ def force_override!(*args)
410
+ return Decorator::Unchain.new(self, :force_override!) unless args.length > 0
411
+ value = args.pop
412
+ rm_override(*args)
413
+ write(:force_override, *args, value)
414
+ end
415
+
416
+ # method-style access to attributes
417
+
418
+ def read(*path)
419
+ merged_attributes.read(*path)
420
+ end
421
+
422
+ def read!(*path)
423
+ merged_attributes.read!(*path)
424
+ end
425
+
426
+ def exist?(*path)
427
+ merged_attributes.exist?(*path)
428
+ end
429
+
430
+ def write(level, *args, &block)
431
+ self.send(level).write(*args, &block)
432
+ end
433
+
434
+ def write!(level, *args, &block)
435
+ self.send(level).write!(*args, &block)
436
+ end
437
+
438
+ def unlink(level, *path)
439
+ self.send(level).unlink(*path)
440
+ end
441
+
442
+ def unlink!(level, *path)
443
+ self.send(level).unlink!(*path)
412
444
  end
413
445
 
414
446
  #
@@ -420,9 +452,9 @@ class Chef
420
452
  #
421
453
 
422
454
  def merged_attributes(*path)
423
- # immutablize(
455
+ # immutablize(
424
456
  merge_all(path)
425
- # )
457
+ # )
426
458
  end
427
459
 
428
460
  def combined_override(*path)
@@ -433,6 +465,27 @@ class Chef
433
465
  immutablize(merge_defaults(path))
434
466
  end
435
467
 
468
+ def normal_unless(*args)
469
+ return Decorator::Unchain.new(self, :normal_unless) unless args.length > 0
470
+ write(:normal, *args) if read(*args[0...-1]).nil?
471
+ end
472
+
473
+ def default_unless(*args)
474
+ return Decorator::Unchain.new(self, :default_unless) unless args.length > 0
475
+ write(:default, *args) if read(*args[0...-1]).nil?
476
+ end
477
+
478
+ def override_unless(*args)
479
+ return Decorator::Unchain.new(self, :override_unless) unless args.length > 0
480
+ write(:override, *args) if read(*args[0...-1]).nil?
481
+ end
482
+
483
+ def set_unless(*args)
484
+ Chef.log_deprecation("node.set_unless is deprecated and will be removed in Chef 14, please use node.default_unless/node.override_unless (or node.normal_unless if you really need persistence)")
485
+ return Decorator::Unchain.new(self, :default_unless) unless args.length > 0
486
+ write(:normal, *args) if read(*args[0...-1]).nil?
487
+ end
488
+
436
489
  def [](key)
437
490
  if deep_merge_cache.has_key?(key.to_s)
438
491
  # return the cache of the deep merged values by top-level key
@@ -461,13 +514,17 @@ class Chef
461
514
  alias :each_attribute :each
462
515
 
463
516
  def method_missing(symbol, *args)
464
- if args.empty?
517
+ if symbol == :to_ary
518
+ merged_attributes.send(symbol, *args)
519
+ elsif args.empty?
520
+ Chef.log_deprecation %q{"method access to node attributes (node.foo.bar) is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]["bar"])}
465
521
  if key?(symbol)
466
522
  self[symbol]
467
523
  else
468
524
  raise NoMethodError, "Undefined method or attribute `#{symbol}' on `node'"
469
525
  end
470
526
  elsif symbol.to_s =~ /=$/
527
+ Chef.log_deprecation %q{"method setting of node attributes (node.foo="bar") is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]="bar")}
471
528
  key_to_set = symbol.to_s[/^(.+)=$/, 1]
472
529
  self[key_to_set] = (args.length == 1 ? args[0] : args)
473
530
  else
@@ -485,10 +542,6 @@ class Chef
485
542
  }.join(", ") << ">"
486
543
  end
487
544
 
488
- def set_unless?
489
- @set_unless_present
490
- end
491
-
492
545
  private
493
546
 
494
547
  # Helper method for merge_all/merge_defaults/merge_overrides.