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
@@ -20,6 +20,7 @@
20
20
 
21
21
  require "spec_helper"
22
22
  require "chef/data_collector"
23
+ require "chef/resource_builder"
23
24
 
24
25
  describe Chef::DataCollector do
25
26
  describe ".register_reporter?" do
@@ -193,10 +194,32 @@ describe Chef::DataCollector::Reporter do
193
194
  end
194
195
  end
195
196
 
197
+ describe '#converge_start' do
198
+ it "stashes the run_context for later use" do
199
+ reporter.converge_start("test_context")
200
+ expect(reporter.run_context).to eq("test_context")
201
+ end
202
+ end
203
+
204
+ describe '#converge_complete' do
205
+ it "detects and processes any unprocessed resources" do
206
+ expect(reporter).to receive(:detect_unprocessed_resources)
207
+ reporter.converge_complete
208
+ end
209
+ end
210
+
211
+ describe '#converge_failed' do
212
+ it "detects and processes any unprocessed resources" do
213
+ expect(reporter).to receive(:detect_unprocessed_resources)
214
+ reporter.converge_failed("exception")
215
+ end
216
+ end
217
+
196
218
  describe '#resource_current_state_loaded' do
197
219
  let(:new_resource) { double("new_resource") }
198
220
  let(:action) { double("action") }
199
221
  let(:current_resource) { double("current_resource") }
222
+ let(:resource_report) { double("resource_report") }
200
223
 
201
224
  context "when resource is a nested resource" do
202
225
  it "does not update the resource report" do
@@ -207,14 +230,12 @@ describe Chef::DataCollector::Reporter do
207
230
  end
208
231
 
209
232
  context "when resource is not a nested resource" do
210
- it "updates the resource report" do
233
+ it "creates the resource report and stores it as the current one" do
211
234
  allow(reporter).to receive(:nested_resource?).and_return(false)
212
- expect(Chef::DataCollector::ResourceReport).to receive(:new).with(
213
- new_resource,
214
- action,
215
- current_resource)
216
- .and_return("resource_report")
217
- expect(reporter).to receive(:update_current_resource_report).with("resource_report")
235
+ expect(reporter).to receive(:create_resource_report)
236
+ .with(new_resource, action, current_resource)
237
+ .and_return(resource_report)
238
+ expect(reporter).to receive(:update_current_resource_report).with(resource_report)
218
239
  reporter.resource_current_state_loaded(new_resource, action, current_resource)
219
240
  end
220
241
  end
@@ -226,17 +247,11 @@ describe Chef::DataCollector::Reporter do
226
247
  let(:resource_report) { double("resource_report") }
227
248
 
228
249
  before do
229
- allow(reporter).to receive(:increment_resource_count)
230
250
  allow(reporter).to receive(:nested_resource?)
231
251
  allow(reporter).to receive(:current_resource_report).and_return(resource_report)
232
252
  allow(resource_report).to receive(:up_to_date)
233
253
  end
234
254
 
235
- it "increments the resource count" do
236
- expect(reporter).to receive(:increment_resource_count)
237
- reporter.resource_up_to_date(new_resource, action)
238
- end
239
-
240
255
  context "when the resource is a nested resource" do
241
256
  it "does not mark the resource report as up-to-date" do
242
257
  allow(reporter).to receive(:nested_resource?).with(new_resource).and_return(true)
@@ -261,17 +276,11 @@ describe Chef::DataCollector::Reporter do
261
276
  let(:resource_report) { double("resource_report") }
262
277
 
263
278
  before do
264
- allow(reporter).to receive(:increment_resource_count)
265
279
  allow(reporter).to receive(:nested_resource?)
266
- allow(reporter).to receive(:current_resource_report).and_return(resource_report)
280
+ allow(reporter).to receive(:create_resource_report).and_return(resource_report)
267
281
  allow(resource_report).to receive(:skipped)
268
282
  end
269
283
 
270
- it "increments the resource count" do
271
- expect(reporter).to receive(:increment_resource_count)
272
- reporter.resource_skipped(new_resource, action, conditional)
273
- end
274
-
275
284
  context "when the resource is a nested resource" do
276
285
  it "does not mark the resource report as skipped" do
277
286
  allow(reporter).to receive(:nested_resource?).with(new_resource).and_return(true)
@@ -281,13 +290,12 @@ describe Chef::DataCollector::Reporter do
281
290
  end
282
291
 
283
292
  context "when the resource is not a nested resource" do
284
- it "updates the resource report" do
293
+ it "creates the resource report and stores it as the current one" do
285
294
  allow(reporter).to receive(:nested_resource?).and_return(false)
286
- expect(Chef::DataCollector::ResourceReport).to receive(:new).with(
287
- new_resource,
288
- action)
289
- .and_return("resource_report")
290
- expect(reporter).to receive(:update_current_resource_report).with("resource_report")
295
+ expect(reporter).to receive(:create_resource_report)
296
+ .with(new_resource, action)
297
+ .and_return(resource_report)
298
+ expect(reporter).to receive(:update_current_resource_report).with(resource_report)
291
299
  reporter.resource_skipped(new_resource, action, conditional)
292
300
  end
293
301
 
@@ -307,11 +315,6 @@ describe Chef::DataCollector::Reporter do
307
315
  allow(resource_report).to receive(:updated)
308
316
  end
309
317
 
310
- it "increments the resource count" do
311
- expect(reporter).to receive(:increment_resource_count)
312
- reporter.resource_updated("new_resource", "action")
313
- end
314
-
315
318
  it "marks the resource report as updated" do
316
319
  expect(resource_report).to receive(:updated)
317
320
  reporter.resource_updated("new_resource", "action")
@@ -326,7 +329,6 @@ describe Chef::DataCollector::Reporter do
326
329
  let(:resource_report) { double("resource_report") }
327
330
 
328
331
  before do
329
- allow(reporter).to receive(:increment_resource_count)
330
332
  allow(reporter).to receive(:update_error_description)
331
333
  allow(reporter).to receive(:current_resource_report).and_return(resource_report)
332
334
  allow(resource_report).to receive(:failed)
@@ -334,11 +336,6 @@ describe Chef::DataCollector::Reporter do
334
336
  allow(error_mapper).to receive(:for_json)
335
337
  end
336
338
 
337
- it "increments the resource count" do
338
- expect(reporter).to receive(:increment_resource_count)
339
- reporter.resource_failed(new_resource, action, exception)
340
- end
341
-
342
339
  it "updates the error description" do
343
340
  expect(Chef::Formatters::ErrorMapper).to receive(:resource_failed).with(
344
341
  new_resource,
@@ -372,15 +369,16 @@ describe Chef::DataCollector::Reporter do
372
369
  let(:resource_report) { double("resource_report") }
373
370
 
374
371
  before do
375
- allow(reporter).to receive(:add_updated_resource)
376
372
  allow(reporter).to receive(:update_current_resource_report)
373
+ allow(reporter).to receive(:add_resource_report)
374
+ allow(reporter).to receive(:current_resource_report)
377
375
  allow(resource_report).to receive(:finish)
378
376
  end
379
377
 
380
378
  context "when there is no current resource report" do
381
- it "does not add the updated resource" do
379
+ it "does not touch the current resource report" do
382
380
  allow(reporter).to receive(:current_resource_report).and_return(nil)
383
- expect(reporter).not_to receive(:add_updated_resource)
381
+ expect(reporter).not_to receive(:update_current_resource_report)
384
382
  reporter.resource_completed(new_resource)
385
383
  end
386
384
  end
@@ -391,9 +389,9 @@ describe Chef::DataCollector::Reporter do
391
389
  end
392
390
 
393
391
  context "when the resource is a nested resource" do
394
- it "does not add the updated resource" do
392
+ it "does not mark the resource as finished" do
395
393
  allow(reporter).to receive(:nested_resource?).with(new_resource).and_return(true)
396
- expect(reporter).not_to receive(:add_updated_resource)
394
+ expect(resource_report).not_to receive(:finish)
397
395
  reporter.resource_completed(new_resource)
398
396
  end
399
397
  end
@@ -408,11 +406,6 @@ describe Chef::DataCollector::Reporter do
408
406
  reporter.resource_completed(new_resource)
409
407
  end
410
408
 
411
- it "adds the resource to the updated resource list" do
412
- expect(reporter).to receive(:add_updated_resource).with(resource_report)
413
- reporter.resource_completed(new_resource)
414
- end
415
-
416
409
  it "nils out the current resource report" do
417
410
  expect(reporter).to receive(:update_current_resource_report).with(nil)
418
411
  reporter.resource_completed(new_resource)
@@ -22,6 +22,7 @@ require "tmpdir"
22
22
  describe Chef::Knife::CookbookCreate do
23
23
  before(:each) do
24
24
  Chef::Config[:node_name] = "webmonkey.example.com"
25
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
25
26
  @knife = Chef::Knife::CookbookCreate.new
26
27
  @knife.config = {}
27
28
  @knife.name_args = ["foobar"]
@@ -38,6 +38,7 @@ describe Chef::Knife::CookbookSiteDownload do
38
38
  expect(@noauth_rest).to receive(:get).
39
39
  with("#{@cookbook_api_url}/apache2").
40
40
  and_return(@current_data)
41
+ @knife.configure_chef
41
42
  end
42
43
 
43
44
  context "when the cookbook is deprecated and not forced" do
@@ -52,29 +52,5 @@ describe Chef::Knife::NodeEnvironmentSet do
52
52
  @knife.run
53
53
  end
54
54
 
55
- describe "with no environment" do
56
- # Set up outputs for inspection later
57
- before(:each) do
58
- @stdout = StringIO.new
59
- @stderr = StringIO.new
60
-
61
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
62
- allow(@knife.ui).to receive(:stderr).and_return(@stderr)
63
- end
64
-
65
- it "should exit" do
66
- @knife.name_args = [ "adam" ]
67
- expect { @knife.run }.to raise_error SystemExit
68
- end
69
-
70
- it "should show the user the usage and an error" do
71
- @knife.name_args = [ "adam" ]
72
-
73
- begin ; @knife.run ; rescue SystemExit ; end
74
-
75
- expect(@stdout.string).to eq "USAGE: knife node environment set NODE ENVIRONMENT\n"
76
- expect(@stderr.string).to eq "FATAL: You must specify a node name and an environment.\n"
77
- end
78
- end
79
55
  end
80
56
  end
@@ -111,30 +111,5 @@ describe Chef::Knife::NodeRunListSet do
111
111
  end
112
112
  end
113
113
 
114
- describe "with no role or recipe" do
115
- # Set up outputs for inspection later
116
- before(:each) do
117
- @stdout = StringIO.new
118
- @stderr = StringIO.new
119
-
120
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
121
- allow(@knife.ui).to receive(:stderr).and_return(@stderr)
122
- end
123
-
124
- it "should exit" do
125
- @knife.name_args = [ "adam" ]
126
- expect { @knife.run }.to raise_error SystemExit
127
- end
128
-
129
- it "should show the user" do
130
- @knife.name_args = [ "adam" ]
131
-
132
- begin ; @knife.run ; rescue SystemExit ; end
133
-
134
- expect(@stdout.string).to eq "USAGE: knife node run_list set NODE ENTRIES (options)\n"
135
- expect(@stderr.string).to eq "FATAL: You must supply both a node name and a run list.\n"
136
- end
137
- end
138
-
139
114
  end
140
115
  end
@@ -218,7 +218,7 @@ describe Chef::Node::Attribute do
218
218
  end
219
219
 
220
220
  it "gives the value at each level of precedence for a path spec" do
221
- expected = [["set_unless_enabled?", false],
221
+ expected = [
222
222
  %w{default default},
223
223
  %w{env_default env_default},
224
224
  %w{role_default role_default},
@@ -417,12 +417,6 @@ describe Chef::Node::Attribute do
417
417
  expect(@attributes.normal["foo"]["bar"]).to eq(:baz)
418
418
  end
419
419
 
420
- it "should optionally skip setting the value if one already exists" do
421
- @attributes.set_unless_value_present = true
422
- @attributes.normal["hostname"] = "bar"
423
- expect(@attributes["hostname"]).to eq("latte")
424
- end
425
-
426
420
  it "does not support ||= when setting" do
427
421
  # This is a limitation of auto-vivification.
428
422
  # Users who need this behavior can use set_unless and friends
@@ -493,6 +487,7 @@ describe Chef::Node::Attribute do
493
487
  end
494
488
 
495
489
  it "should return true if an attribute exists but is set to nil using dot notation" do
490
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
496
491
  expect(@attributes.music.deeper.has_key?("gates_of_ishtar")).to eq(true)
497
492
  end
498
493
 
@@ -533,10 +528,12 @@ describe Chef::Node::Attribute do
533
528
 
534
529
  describe "method_missing" do
535
530
  it "should behave like a [] lookup" do
531
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
536
532
  expect(@attributes.music.mastodon).to eq("rocks")
537
533
  end
538
534
 
539
535
  it "should allow the last method to set a value if it has an = sign on the end" do
536
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
540
537
  @attributes.normal.music.mastodon = %w{dream still shining}
541
538
  expect(@attributes.normal.music.mastodon).to eq(%w{dream still shining})
542
539
  end
@@ -577,7 +574,7 @@ describe Chef::Node::Attribute do
577
574
 
578
575
  it "should yield lower if we go deeper" do
579
576
  collect = Array.new
580
- @attributes.one.keys.each do |k|
577
+ @attributes["one"].keys.each do |k|
581
578
  collect << k
582
579
  end
583
580
  expect(collect.include?("two")).to eq(true)
@@ -587,7 +584,7 @@ describe Chef::Node::Attribute do
587
584
  end
588
585
 
589
586
  it "should not raise an exception if one of the hashes has a nil value on a deep lookup" do
590
- expect { @attributes.place.keys { |k| } }.not_to raise_error
587
+ expect { @attributes["place"].keys { |k| } }.not_to raise_error
591
588
  end
592
589
  end
593
590
 
@@ -1171,6 +1168,7 @@ describe Chef::Node::Attribute do
1171
1168
  end
1172
1169
 
1173
1170
  it "raises an error when using `attr=value`" do
1171
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
1174
1172
  expect { @attributes.new_key = "new value" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
1175
1173
  end
1176
1174
 
@@ -95,6 +95,10 @@ describe Chef::Node::ImmutableMash do
95
95
  :replace,
96
96
  :select!,
97
97
  :shift,
98
+ :write,
99
+ :write!,
100
+ :unlink,
101
+ :unlink!,
98
102
  ].each do |mutator|
99
103
  it "doesn't allow mutation via `#{mutator}'" do
100
104
  expect { @immutable_mash.send(mutator) }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
@@ -0,0 +1,344 @@
1
+ #
2
+ # Copyright:: Copyright 2016, Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "spec_helper"
19
+ require "chef/node/attribute_collections"
20
+
21
+ describe Chef::Node::VividMash do
22
+ class Root
23
+ attr_accessor :top_level_breadcrumb
24
+ end
25
+
26
+ let(:root) { Root.new }
27
+
28
+ let(:vivid) do
29
+ expect(root).to receive(:reset_cache).at_least(:once).with(nil)
30
+ Chef::Node::VividMash.new(root,
31
+ { "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil }
32
+ )
33
+ end
34
+
35
+ context "#read" do
36
+ before do
37
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
38
+ vivid
39
+ expect(root).not_to receive(:reset_cache)
40
+ end
41
+
42
+ it "reads hashes deeply" do
43
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
44
+ expect(vivid.read("one", "two", "three")).to eql("four")
45
+ end
46
+
47
+ it "does not trainwreck when hitting hash keys that do not exist" do
48
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
49
+ expect(vivid.read("one", "five", "six")).to eql(nil)
50
+ end
51
+
52
+ it "does not trainwreck when hitting an array with an out of bounds index" do
53
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
54
+ expect(vivid.read("array", 5, "one")).to eql(nil)
55
+ end
56
+
57
+ it "does not trainwreck when hitting an array with a string key" do
58
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
59
+ expect(vivid.read("array", "one", "two")).to eql(nil)
60
+ end
61
+
62
+ it "does not trainwreck when traversing a nil" do
63
+ expect(root).to receive(:top_level_breadcrumb=).with("nil").and_call_original
64
+ expect(vivid.read("nil", "one", "two")).to eql(nil)
65
+ end
66
+ end
67
+
68
+ context "#exist?" do
69
+ before do
70
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
71
+ vivid
72
+ expect(root).not_to receive(:reset_cache)
73
+ end
74
+
75
+ it "true if there's a hash key there" do
76
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
77
+ expect(vivid.exist?("one", "two", "three")).to be true
78
+ end
79
+
80
+ it "true for intermediate hashes" do
81
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
82
+ expect(vivid.exist?("one")).to be true
83
+ end
84
+
85
+ it "true for arrays that exist" do
86
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
87
+ expect(vivid.exist?("array", 1)).to be true
88
+ end
89
+
90
+ it "true when the value of the key is nil" do
91
+ expect(root).to receive(:top_level_breadcrumb=).with("nil").and_call_original
92
+ expect(vivid.exist?("nil")).to be true
93
+ end
94
+
95
+ it "false when attributes don't exist" do
96
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
97
+ expect(vivid.exist?("one", "five", "six")).to be false
98
+ end
99
+
100
+ it "false when traversing a non-container" do
101
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
102
+ expect(vivid.exist?("one", "two", "three", "four")).to be false
103
+ end
104
+
105
+ it "false when an array index does not exist" do
106
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
107
+ expect(vivid.exist?("array", 3)).to be false
108
+ end
109
+
110
+ it "false when traversing a nil" do
111
+ expect(root).to receive(:top_level_breadcrumb=).with("nil").and_call_original
112
+ expect(vivid.exist?("nil", "foo", "bar")).to be false
113
+ end
114
+ end
115
+
116
+ context "#read!" do
117
+ before do
118
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
119
+ vivid
120
+ expect(root).not_to receive(:reset_cache)
121
+ end
122
+
123
+ it "reads hashes deeply" do
124
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
125
+ expect(vivid.read!("one", "two", "three")).to eql("four")
126
+ end
127
+
128
+ it "reads arrays deeply" do
129
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
130
+ expect(vivid.read!("array", 1)).to eql(1)
131
+ end
132
+
133
+ it "throws an exception when attributes do not exist" do
134
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
135
+ expect { vivid.read!("one", "five", "six") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
136
+ end
137
+
138
+ it "throws an exception when traversing a non-container" do
139
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
140
+ expect { vivid.read!("one", "two", "three", "four") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
141
+ end
142
+
143
+ it "throws an exception when an array element does not exist" do
144
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
145
+ expect { vivid.read!("array", 3) }.to raise_error(Chef::Exceptions::NoSuchAttribute)
146
+ end
147
+ end
148
+
149
+ context "#write" do
150
+ before do
151
+ vivid
152
+ expect(root).not_to receive(:reset_cache).with(nil)
153
+ end
154
+
155
+ it "should write into hashes" do
156
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
157
+ vivid.write("one", "five", "six")
158
+ expect(vivid["one"]["five"]).to eql("six")
159
+ end
160
+
161
+ it "should deeply autovivify" do
162
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
163
+ vivid.write("one", "five", "six", "seven", "eight", "nine", "ten")
164
+ expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
165
+ end
166
+
167
+ it "should raise an exception if you overwrite an array with a hash" do
168
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
169
+ vivid.write("array", "five", "six")
170
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => "six" }, "nil" => nil })
171
+ end
172
+
173
+ it "should raise an exception if you traverse through an array with a hash" do
174
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
175
+ vivid.write("array", "five", "six", "seven")
176
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => { "six" => "seven" } }, "nil" => nil })
177
+ end
178
+
179
+ it "should raise an exception if you overwrite a string with a hash" do
180
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
181
+ vivid.write("one", "two", "three", "four", "five")
182
+ expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => "five" } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
183
+ end
184
+
185
+ it "should raise an exception if you traverse through a string with a hash" do
186
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
187
+ vivid.write("one", "two", "three", "four", "five", "six")
188
+ expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => { "five" => "six" } } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
189
+ end
190
+
191
+ it "should raise an exception if you overwrite a nil with a hash" do
192
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
193
+ vivid.write("nil", "one", "two")
194
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => "two" } })
195
+ end
196
+
197
+ it "should raise an exception if you traverse through a nil with a hash" do
198
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
199
+ vivid.write("nil", "one", "two", "three")
200
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => { "two" => "three" } } })
201
+ end
202
+
203
+ it "writes with a block" do
204
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
205
+ vivid.write("one", "five") { "six" }
206
+ expect(vivid["one"]["five"]).to eql("six")
207
+ end
208
+ end
209
+
210
+ context "#write!" do
211
+ before do
212
+ vivid
213
+ expect(root).not_to receive(:reset_cache).with(nil)
214
+ end
215
+
216
+ it "should write into hashes" do
217
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
218
+ vivid.write!("one", "five", "six")
219
+ expect(vivid["one"]["five"]).to eql("six")
220
+ end
221
+
222
+ it "should deeply autovivify" do
223
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
224
+ vivid.write!("one", "five", "six", "seven", "eight", "nine", "ten")
225
+ expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
226
+ end
227
+
228
+ it "should raise an exception if you overwrite an array with a hash" do
229
+ expect(root).not_to receive(:reset_cache)
230
+ expect { vivid.write!("array", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
231
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
232
+ end
233
+
234
+ it "should raise an exception if you traverse through an array with a hash" do
235
+ expect(root).not_to receive(:reset_cache)
236
+ expect { vivid.write!("array", "five", "six", "seven") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
237
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
238
+ end
239
+
240
+ it "should raise an exception if you overwrite a string with a hash" do
241
+ expect(root).not_to receive(:reset_cache)
242
+ expect { vivid.write!("one", "two", "three", "four", "five") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
243
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
244
+ end
245
+
246
+ it "should raise an exception if you traverse through a string with a hash" do
247
+ expect(root).not_to receive(:reset_cache)
248
+ expect { vivid.write!("one", "two", "three", "four", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
249
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
250
+ end
251
+
252
+ it "should raise an exception if you overwrite a nil with a hash" do
253
+ expect(root).not_to receive(:reset_cache)
254
+ expect { vivid.write!("nil", "one", "two") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
255
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
256
+ end
257
+
258
+ it "should raise an exception if you traverse through a nil with a hash" do
259
+ expect(root).not_to receive(:reset_cache)
260
+ expect { vivid.write!("nil", "one", "two", "three") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
261
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
262
+ end
263
+
264
+ it "writes with a block" do
265
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
266
+ vivid.write!("one", "five") { "six" }
267
+ expect(vivid["one"]["five"]).to eql("six")
268
+ end
269
+ end
270
+
271
+ context "#unlink" do
272
+ before do
273
+ vivid
274
+ expect(root).not_to receive(:reset_cache).with(nil)
275
+ end
276
+
277
+ it "should return nil if the keys already don't exist" do
278
+ expect(root).not_to receive(:reset_cache)
279
+ expect(vivid.unlink("five", "six", "seven", "eight")).to eql(nil)
280
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
281
+ end
282
+
283
+ it "should unlink hashes" do
284
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
285
+ expect( vivid.unlink("one") ).to eql({ "two" => { "three" => "four" } })
286
+ expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
287
+ end
288
+
289
+ it "should unlink array elements" do
290
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
291
+ expect(vivid.unlink("array", 2)).to eql(2)
292
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
293
+ end
294
+
295
+ it "should unlink nil" do
296
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
297
+ expect(vivid.unlink("nil")).to eql(nil)
298
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
299
+ end
300
+
301
+ it "should traverse a nil and safely do nothing" do
302
+ expect(root).not_to receive(:reset_cache)
303
+ expect(vivid.unlink("nil", "foo")).to eql(nil)
304
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
305
+ end
306
+ end
307
+
308
+ context "#unlink!" do
309
+ before do
310
+ vivid
311
+ expect(root).not_to receive(:reset_cache).with(nil)
312
+ end
313
+
314
+ it "should raise an exception if the keys already don't exist" do
315
+ expect(root).not_to receive(:reset_cache)
316
+ expect { vivid.unlink!("five", "six", "seven", "eight") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
317
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
318
+ end
319
+
320
+ it "should unlink! hashes" do
321
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
322
+ expect( vivid.unlink!("one") ).to eql({ "two" => { "three" => "four" } })
323
+ expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
324
+ end
325
+
326
+ it "should unlink! array elements" do
327
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
328
+ expect(vivid.unlink!("array", 2)).to eql(2)
329
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
330
+ end
331
+
332
+ it "should unlink! nil" do
333
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
334
+ expect(vivid.unlink!("nil")).to eql(nil)
335
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
336
+ end
337
+
338
+ it "should raise an exception if it traverses a nil" do
339
+ expect(root).not_to receive(:reset_cache)
340
+ expect { vivid.unlink!("nil", "foo") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
341
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
342
+ end
343
+ end
344
+ end