chef 12.15.19-universal-mingw32 → 12.16.42-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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -1
  3. data/VERSION +1 -1
  4. data/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml +3 -1
  5. data/acceptance/Gemfile.lock +14 -14
  6. data/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb +3 -11
  7. data/distro/common/html/knife_bootstrap.html +1 -1
  8. data/distro/common/man/man1/README.md +2 -2
  9. data/distro/common/man/man1/knife-client.1 +1 -1
  10. data/lib/chef/application.rb +7 -15
  11. data/lib/chef/application/client.rb +2 -2
  12. data/lib/chef/application/solo.rb +1 -1
  13. data/lib/chef/chef_class.rb +1 -0
  14. data/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb +3 -7
  15. data/lib/chef/chef_fs/file_system/chef_server/versioned_cookbook_dir.rb +1 -1
  16. data/lib/chef/data_collector.rb +83 -9
  17. data/lib/chef/data_collector/messages.rb +2 -1
  18. data/lib/chef/dsl/core.rb +1 -1
  19. data/lib/chef/dsl/declare_resource.rb +10 -4
  20. data/lib/chef/dsl/method_missing.rb +1 -1
  21. data/lib/chef/dsl/recipe.rb +1 -1
  22. data/lib/chef/dsl/universal.rb +1 -1
  23. data/lib/chef/event_dispatch/base.rb +3 -0
  24. data/lib/chef/http.rb +3 -4
  25. data/lib/chef/knife.rb +20 -2
  26. data/lib/chef/knife/core/generic_presenter.rb +18 -4
  27. data/lib/chef/knife/node_show.rb +0 -5
  28. data/lib/chef/knife/osc_user_show.rb +0 -1
  29. data/lib/chef/knife/ssl_fetch.rb +9 -5
  30. data/lib/chef/mixin/powershell_out.rb +1 -1
  31. data/lib/chef/mixin/shell_out.rb +1 -1
  32. data/lib/chef/node.rb +1 -5
  33. data/lib/chef/node/attribute.rb +70 -98
  34. data/lib/chef/node/attribute_collections.rb +28 -19
  35. data/lib/chef/node/common_api.rb +0 -6
  36. data/lib/chef/node/immutable_collections.rb +16 -79
  37. data/lib/chef/node/mixin/deep_merge_cache.rb +61 -0
  38. data/lib/chef/node/mixin/immutablize_array.rb +67 -0
  39. data/lib/chef/node/mixin/immutablize_hash.rb +54 -0
  40. data/lib/chef/node/mixin/state_tracking.rb +93 -0
  41. data/lib/chef/property.rb +4 -4
  42. data/lib/chef/provider/cron.rb +1 -1
  43. data/lib/chef/provider/group/suse.rb +23 -4
  44. data/lib/chef/provider/package.rb +43 -5
  45. data/lib/chef/provider/package/apt.rb +20 -0
  46. data/lib/chef/provider/package/windows/exe.rb +4 -3
  47. data/lib/chef/provider/package/windows/msi.rb +4 -3
  48. data/lib/chef/provider/package/yum.rb +20 -0
  49. data/lib/chef/provider/package/zypper.rb +20 -0
  50. data/lib/chef/provider/ruby_block.rb +1 -1
  51. data/lib/chef/provider/service/upstart.rb +25 -9
  52. data/lib/chef/provider/user.rb +4 -6
  53. data/lib/chef/provider/user/dscl.rb +8 -3
  54. data/lib/chef/provider/user/solaris.rb +5 -12
  55. data/lib/chef/resource.rb +19 -0
  56. data/lib/chef/resource/file.rb +1 -1
  57. data/lib/chef/resource/package.rb +1 -1
  58. data/lib/chef/resource/scm.rb +1 -7
  59. data/lib/chef/resource/yum_repository.rb +1 -1
  60. data/lib/chef/rest.rb +1 -0
  61. data/lib/chef/run_context.rb +12 -0
  62. data/lib/chef/version.rb +1 -1
  63. data/spec/data/trusted_certs/example_no_cn.crt +36 -0
  64. data/spec/functional/resource/group_spec.rb +1 -0
  65. data/spec/functional/resource/user/useradd_spec.rb +4 -2
  66. data/spec/integration/knife/data_bag_create_spec.rb +0 -3
  67. data/spec/integration/knife/environment_show_spec.rb +24 -4
  68. data/spec/integration/knife/node_environment_set_spec.rb +4 -1
  69. data/spec/integration/recipes/accumulator_spec.rb +232 -0
  70. data/spec/integration/recipes/resource_action_spec.rb +1 -1
  71. data/spec/spec_helper.rb +2 -2
  72. data/spec/support/shared/context/client.rb +12 -3
  73. data/spec/support/shared/integration/app_server_support.rb +1 -1
  74. data/spec/support/shared/integration/knife_support.rb +4 -1
  75. data/spec/unit/data_collector/messages_spec.rb +2 -0
  76. data/spec/unit/data_collector_spec.rb +158 -21
  77. data/spec/unit/http_spec.rb +1 -1
  78. data/spec/unit/knife/core/gem_glob_loader_spec.rb +1 -1
  79. data/spec/unit/knife/core/ui_spec.rb +10 -0
  80. data/spec/unit/knife/ssl_fetch_spec.rb +38 -0
  81. data/spec/unit/knife_spec.rb +31 -0
  82. data/spec/unit/mixin/powershell_out_spec.rb +25 -1
  83. data/spec/unit/node/attribute_spec.rb +46 -1
  84. data/spec/unit/node/vivid_mash_spec.rb +27 -89
  85. data/spec/unit/node_spec.rb +134 -3
  86. data/spec/unit/provider/deploy_spec.rb +1 -1
  87. data/spec/unit/provider/group/suse_spec.rb +90 -0
  88. data/spec/unit/provider/package/apt_spec.rb +22 -0
  89. data/spec/unit/provider/package/windows/msi_spec.rb +13 -4
  90. data/spec/unit/provider/package/windows_spec.rb +3 -3
  91. data/spec/unit/provider/package/yum_spec.rb +18 -0
  92. data/spec/unit/provider/package/zypper_spec.rb +64 -0
  93. data/spec/unit/provider/package_spec.rb +58 -0
  94. data/spec/unit/provider/remote_file/content_spec.rb +1 -1
  95. data/spec/unit/provider/service/upstart_service_spec.rb +13 -6
  96. data/spec/unit/provider/user/solaris_spec.rb +36 -9
  97. data/spec/unit/provider/user_spec.rb +6 -0
  98. data/spec/unit/resource/apt_repository_spec.rb +1 -1
  99. metadata +12 -5
@@ -74,7 +74,7 @@ describe Chef::HTTP do
74
74
  expect(http.create_url("///api/endpoint?url=http://foo.bar")).to eql(URI.parse("http://www.getchef.com/organization/org/api/endpoint?url=http://foo.bar"))
75
75
  end
76
76
 
77
- # As per: https://github.com/opscode/chef/issues/2500
77
+ # As per: https://github.com/chef/chef/issues/2500
78
78
  it "should treat scheme part of the URI in a case-insensitive manner" do
79
79
  http = Chef::HTTP.allocate # Calling Chef::HTTP::new sets @url, don't want that.
80
80
  expect { http.create_url("HTTP://www1.chef.io/") }.not_to raise_error
@@ -78,7 +78,7 @@ describe Chef::Knife::SubcommandLoader::GemGlobLoader do
78
78
  expect(loader.site_subcommands).to include(expected_command)
79
79
  end
80
80
 
81
- # https://github.com/opscode/chef-dk/issues/227
81
+ # https://github.com/chef/chef-dk/issues/227
82
82
  #
83
83
  # `knife` in ChefDK isn't from a gem install, it's directly run from a clone
84
84
  # of the source, but there can be one or more versions of chef also installed
@@ -28,6 +28,7 @@ describe Chef::Knife::UI do
28
28
  :verbosity => 0,
29
29
  :yes => nil,
30
30
  :format => "summary",
31
+ :field_separator => ".",
31
32
  }
32
33
  @ui = Chef::Knife::UI.new(@out, @err, @in, @config)
33
34
  Chef::Config[:treat_deprecation_warnings_as_errors] = false
@@ -410,6 +411,15 @@ EOM
410
411
  @ui.config[:attribute] = non_existing_path
411
412
  expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { non_existing_path => nil } })
412
413
  end
414
+
415
+ describe "when --field-separator is passed" do
416
+ it "honors that separator" do
417
+ input = { "keys" => { "with spaces" => { "open" => { "doors" => { "with many.dots" => "when asked" } } } } }
418
+ @ui.config[:field_separator] = ";"
419
+ @ui.config[:attribute] = "keys;with spaces;open;doors;with many.dots"
420
+ expect(@ui.format_for_display(input)).to eq({ nil => { "keys;with spaces;open;doors;with many.dots" => "when asked" } })
421
+ end
422
+ end
413
423
  end
414
424
 
415
425
  describe "with --run-list passed" do
@@ -108,6 +108,24 @@ E
108
108
 
109
109
  end
110
110
 
111
+ describe "#cn_of" do
112
+ let(:certificate) { double("Certificate", subject: subject) }
113
+
114
+ describe "when the certificate has a common name" do
115
+ let(:subject) { [["CN", "common name"]] }
116
+ it "returns the common name" do
117
+ expect(ssl_fetch.cn_of(certificate)).to eq("common name")
118
+ end
119
+ end
120
+
121
+ describe "when the certificate does not have a common name" do
122
+ let(:subject) { [] }
123
+ it "returns nil" do
124
+ expect(ssl_fetch.cn_of(certificate)).to eq(nil)
125
+ end
126
+ end
127
+ end
128
+
111
129
  describe "fetching the remote cert chain" do
112
130
 
113
131
  let(:name_args) { %w{https://foo.example.com:8443} }
@@ -180,5 +198,25 @@ ERROR_TEXT
180
198
 
181
199
  end
182
200
 
201
+ describe "when the certificate does not have a CN" do
202
+ let(:self_signed_crt_path) { File.join(CHEF_SPEC_DATA, "trusted_certs", "example_no_cn.crt") }
203
+ let(:self_signed_crt) { OpenSSL::X509::Certificate.new(File.read(self_signed_crt_path)) }
204
+
205
+ before do
206
+ expect(ssl_fetch).to receive(:proxified_socket).with("foo.example.com", 8443).and_return(tcp_socket)
207
+ expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(tcp_socket, ssl_fetch.noverify_peer_ssl_context).and_return(ssl_socket)
208
+ expect(ssl_socket).to receive(:connect)
209
+ expect(ssl_socket).to receive(:peer_cert_chain).and_return([self_signed_crt])
210
+ expect(Time).to receive(:new).and_return(1)
211
+ end
212
+
213
+ it "fetches the certificate and writes it to a file in the trusted_certs_dir" do
214
+ run
215
+ stored_cert_path = File.join(trusted_certs_dir, "foo.example.com_1.crt")
216
+ expect(File).to exist(stored_cert_path)
217
+ expect(File.read(stored_cert_path)).to eq(File.read(self_signed_crt_path))
218
+ end
219
+ end
220
+
183
221
  end
184
222
  end
@@ -349,6 +349,37 @@ describe Chef::Knife do
349
349
  expect { knife.run_with_pretty_exceptions }.to raise_error(Exception)
350
350
  end
351
351
  end
352
+
353
+ describe "setting arbitrary configuration with --config-option" do
354
+
355
+ let(:stdout) { StringIO.new }
356
+
357
+ let(:stderr) { StringIO.new }
358
+
359
+ let(:stdin) { StringIO.new }
360
+
361
+ let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, disable_editing: true) }
362
+
363
+ let(:subcommand) do
364
+ KnifeSpecs::TestYourself.options = Chef::Application::Knife.options.merge(KnifeSpecs::TestYourself.options)
365
+ KnifeSpecs::TestYourself.new(%w{--config-option badly_formatted_arg}).tap do |cmd|
366
+ cmd.ui = ui
367
+ end
368
+ end
369
+
370
+ it "sets arbitrary configuration via --config-option" do
371
+ Chef::Knife.run(%w{test yourself --config-option arbitrary_config_thing=hello}, Chef::Application::Knife.options)
372
+ expect(Chef::Config[:arbitrary_config_thing]).to eq("hello")
373
+ end
374
+
375
+ it "handles errors in arbitrary configuration" do
376
+ expect(subcommand).to receive(:exit).with(1)
377
+ subcommand.configure_chef
378
+ expect(stderr.string).to include("ERROR: Unparsable config option \"badly_formatted_arg\"")
379
+ expect(stdout.string).to include(subcommand.opt_parser.to_s)
380
+ end
381
+ end
382
+
352
383
  end
353
384
 
354
385
  describe "when first created" do
@@ -18,7 +18,7 @@
18
18
  require "spec_helper"
19
19
  require "chef/mixin/powershell_out"
20
20
 
21
- describe Chef::Mixin::PowershellOut do
21
+ describe Chef::Mixin::PowershellOut, :windows_only do
22
22
  let(:shell_out_class) { Class.new { include Chef::Mixin::PowershellOut } }
23
23
  subject(:object) { shell_out_class.new }
24
24
  let(:architecture) { "something" }
@@ -44,6 +44,18 @@ describe Chef::Mixin::PowershellOut do
44
44
  ).and_return(ret)
45
45
  expect(object.powershell_out("Get-Process", timeout: 600)).to eql(ret)
46
46
  end
47
+
48
+ context "when double quote is passed in the powershell command" do
49
+ it "passes if double quote is appended with single escape" do
50
+ result = object.powershell_out("Write-Verbose \"Some String\" -Verbose")
51
+ expect(result.stderr).to be == ""
52
+ expect(result.stdout).to be == "VERBOSE: Some String\n"
53
+ end
54
+
55
+ it "suppresses error if double quote is passed with double escape characters" do
56
+ expect { object.powershell_out("Write-Verbose \\\"Some String\\\" -Verbose") }.not_to raise_error
57
+ end
58
+ end
47
59
  end
48
60
 
49
61
  describe "#powershell_out!" do
@@ -66,5 +78,17 @@ describe Chef::Mixin::PowershellOut do
66
78
  expect(mixlib_shellout).to receive(:error!)
67
79
  expect(object.powershell_out!("Get-Process", timeout: 600)).to eql(mixlib_shellout)
68
80
  end
81
+
82
+ context "when double quote is passed in the powershell command" do
83
+ it "passes if double quote is appended with single escape" do
84
+ result = object.powershell_out!("Write-Verbose \"Some String\" -Verbose")
85
+ expect(result.stderr).to be == ""
86
+ expect(result.stdout).to be == "VERBOSE: Some String\n"
87
+ end
88
+
89
+ it "raises error if double quote is passed with double escape characters" do
90
+ expect { object.powershell_out!("Write-Verbose \\\"Some String\\\" -Verbose") }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
91
+ end
92
+ end
69
93
  end
70
94
  end
@@ -21,7 +21,11 @@ require "spec_helper"
21
21
  require "chef/node/attribute"
22
22
 
23
23
  describe Chef::Node::Attribute do
24
+ let(:events) { instance_double(Chef::EventDispatch::Dispatcher) }
25
+ let(:run_context) { instance_double(Chef::RunContext, :events => events) }
26
+ let(:node) { instance_double(Chef::Node, :run_context => run_context) }
24
27
  before(:each) do
28
+ allow(events).to receive(:attribute_changed)
25
29
  @attribute_hash =
26
30
  { "dmi" => {},
27
31
  "command" => { "ps" => "ps -ef" },
@@ -166,7 +170,7 @@ describe Chef::Node::Attribute do
166
170
  },
167
171
  }
168
172
  @automatic_hash = { "week" => "friday" }
169
- @attributes = Chef::Node::Attribute.new(@attribute_hash, @default_hash, @override_hash, @automatic_hash)
173
+ @attributes = Chef::Node::Attribute.new(@attribute_hash, @default_hash, @override_hash, @automatic_hash, node)
170
174
  end
171
175
 
172
176
  describe "initialize" do
@@ -1196,4 +1200,45 @@ describe Chef::Node::Attribute do
1196
1200
  expect(@attributes["foo"]["baz"]["bar"]).to be true
1197
1201
  end
1198
1202
  end
1203
+
1204
+ describe "node state" do
1205
+ it "sets __root__ correctly" do
1206
+ @attributes.default["foo"]["bar"]["baz"] = "quux"
1207
+ expect(@attributes["foo"].__root__).to eql(@attributes)
1208
+ expect(@attributes["foo"]["bar"].__root__).to eql(@attributes)
1209
+ expect(@attributes.default["foo"].__root__).to eql(@attributes)
1210
+ expect(@attributes.default["foo"]["bar"].__root__).to eql(@attributes)
1211
+ end
1212
+
1213
+ it "sets __node__ correctly" do
1214
+ @attributes.default["foo"]["bar"]["baz"] = "quux"
1215
+ expect(@attributes["foo"].__node__).to eql(node)
1216
+ expect(@attributes["foo"]["bar"].__node__).to eql(node)
1217
+ expect(@attributes.default["foo"].__node__).to eql(node)
1218
+ expect(@attributes.default["foo"]["bar"].__node__).to eql(node)
1219
+ end
1220
+
1221
+ it "sets __path__ correctly" do
1222
+ @attributes.default["foo"]["bar"]["baz"] = "quux"
1223
+ expect(@attributes["foo"].__path__).to eql(["foo"])
1224
+ expect(@attributes["foo"]["bar"].__path__).to eql(%w{foo bar})
1225
+ expect(@attributes.default["foo"].__path__).to eql(["foo"])
1226
+ expect(@attributes.default["foo"]["bar"].__path__).to eql(%w{foo bar})
1227
+ end
1228
+
1229
+ it "sets __precedence__ correctly" do
1230
+ @attributes.default["foo"]["bar"]["baz"] = "quux"
1231
+ expect(@attributes["foo"].__precedence__).to eql(:merged)
1232
+ expect(@attributes["foo"]["bar"].__precedence__).to eql(:merged)
1233
+ expect(@attributes.default["foo"].__precedence__).to eql(:default)
1234
+ expect(@attributes.default["foo"]["bar"].__precedence__).to eql(:default)
1235
+ end
1236
+
1237
+ it "notifies on attribute changes" do
1238
+ expect(events).to receive(:attribute_changed).with(:default, ["foo"], {})
1239
+ expect(events).to receive(:attribute_changed).with(:default, %w{foo bar}, {})
1240
+ expect(events).to receive(:attribute_changed).with(:default, %w{foo bar baz}, "quux")
1241
+ @attributes.default["foo"]["bar"]["baz"] = "quux"
1242
+ end
1243
+ end
1199
1244
  end
@@ -19,36 +19,46 @@ require "spec_helper"
19
19
  require "chef/node/attribute_collections"
20
20
 
21
21
  describe Chef::Node::VividMash do
22
- class Root
23
- attr_accessor :top_level_breadcrumb
24
- end
25
-
26
- let(:root) { Root.new }
22
+ let(:root) { instance_double(Chef::Node::Attribute) }
27
23
 
28
24
  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 }
25
+ Chef::Node::VividMash.new(
26
+ { "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil },
27
+ root
32
28
  )
33
29
  end
34
30
 
35
- def with_breadcrumb(key)
36
- expect(root).to receive(:top_level_breadcrumb=).with(nil).at_least(:once).and_call_original
37
- expect(root).to receive(:top_level_breadcrumb=).with(key).at_least(:once).and_call_original
31
+ context "without a root node" do
32
+ let(:vivid) do
33
+ Chef::Node::VividMash.new(
34
+ { "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil }
35
+ )
36
+ end
37
+
38
+ it "sets the root to the root object" do
39
+ expect(vivid["one"]["two"].__root__).to eql(vivid)
40
+ end
41
+
42
+ it "does not send reset cache" do
43
+ # if we setup the expectation here then the object winds up responding to :reset_cache and then it fails...
44
+ # expect(vivid).not_to receive(:reset_cache)
45
+ # but even so we expect to blow up here with NoMethodError if we screw up and send :reset_cache to a root VividMash
46
+ vivid["one"]["foo"] = "bar"
47
+ end
38
48
  end
39
49
 
40
50
  context "#[]=" do
41
51
  it "deep converts values through arrays" do
42
- allow(root).to receive(:reset_cache)
43
- vivid[:foo] = [ { :bar => true } ]
52
+ expect(root).to receive(:reset_cache).with("foo")
53
+ vivid["foo"] = [ { :bar => true } ]
44
54
  expect(vivid["foo"].class).to eql(Chef::Node::AttrArray)
45
55
  expect(vivid["foo"][0].class).to eql(Chef::Node::VividMash)
46
56
  expect(vivid["foo"][0]["bar"]).to be true
47
57
  end
48
58
 
49
59
  it "deep converts values through nested arrays" do
50
- allow(root).to receive(:reset_cache)
51
- vivid[:foo] = [ [ { :bar => true } ] ]
60
+ expect(root).to receive(:reset_cache).with("foo")
61
+ vivid["foo"] = [ [ { :bar => true } ] ]
52
62
  expect(vivid["foo"].class).to eql(Chef::Node::AttrArray)
53
63
  expect(vivid["foo"][0].class).to eql(Chef::Node::AttrArray)
54
64
  expect(vivid["foo"][0][0].class).to eql(Chef::Node::VividMash)
@@ -56,8 +66,8 @@ describe Chef::Node::VividMash do
56
66
  end
57
67
 
58
68
  it "deep converts values through hashes" do
59
- allow(root).to receive(:reset_cache)
60
- vivid[:foo] = { baz: { :bar => true } }
69
+ expect(root).to receive(:reset_cache).with("foo")
70
+ vivid["foo"] = { baz: { :bar => true } }
61
71
  expect(vivid["foo"]).to be_an_instance_of(Chef::Node::VividMash)
62
72
  expect(vivid["foo"]["baz"]).to be_an_instance_of(Chef::Node::VividMash)
63
73
  expect(vivid["foo"]["baz"]["bar"]).to be true
@@ -66,182 +76,144 @@ describe Chef::Node::VividMash do
66
76
 
67
77
  context "#read" do
68
78
  before do
69
- # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
70
- vivid
71
79
  expect(root).not_to receive(:reset_cache)
72
80
  end
73
81
 
74
82
  it "reads hashes deeply" do
75
- with_breadcrumb("one")
76
83
  expect(vivid.read("one", "two", "three")).to eql("four")
77
84
  end
78
85
 
79
86
  it "does not trainwreck when hitting hash keys that do not exist" do
80
- with_breadcrumb("one")
81
87
  expect(vivid.read("one", "five", "six")).to eql(nil)
82
88
  end
83
89
 
84
90
  it "does not trainwreck when hitting an array with an out of bounds index" do
85
- with_breadcrumb("array")
86
91
  expect(vivid.read("array", 5, "one")).to eql(nil)
87
92
  end
88
93
 
89
94
  it "does not trainwreck when hitting an array with a string key" do
90
- with_breadcrumb("array")
91
95
  expect(vivid.read("array", "one", "two")).to eql(nil)
92
96
  end
93
97
 
94
98
  it "does not trainwreck when traversing a nil" do
95
- with_breadcrumb("nil")
96
99
  expect(vivid.read("nil", "one", "two")).to eql(nil)
97
100
  end
98
101
  end
99
102
 
100
103
  context "#exist?" do
101
104
  before do
102
- # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
103
- vivid
104
105
  expect(root).not_to receive(:reset_cache)
105
106
  end
106
107
 
107
108
  it "true if there's a hash key there" do
108
- with_breadcrumb("one")
109
109
  expect(vivid.exist?("one", "two", "three")).to be true
110
110
  end
111
111
 
112
112
  it "true for intermediate hashes" do
113
- with_breadcrumb("one")
114
113
  expect(vivid.exist?("one")).to be true
115
114
  end
116
115
 
117
116
  it "true for arrays that exist" do
118
- with_breadcrumb("array")
119
117
  expect(vivid.exist?("array", 1)).to be true
120
118
  end
121
119
 
122
120
  it "true when the value of the key is nil" do
123
- with_breadcrumb("nil")
124
121
  expect(vivid.exist?("nil")).to be true
125
122
  end
126
123
 
127
124
  it "false when attributes don't exist" do
128
- with_breadcrumb("one")
129
125
  expect(vivid.exist?("one", "five", "six")).to be false
130
126
  end
131
127
 
132
128
  it "false when traversing a non-container" do
133
- with_breadcrumb("one")
134
129
  expect(vivid.exist?("one", "two", "three", "four")).to be false
135
130
  end
136
131
 
137
132
  it "false when an array index does not exist" do
138
- with_breadcrumb("array")
139
133
  expect(vivid.exist?("array", 3)).to be false
140
134
  end
141
135
 
142
136
  it "false when traversing a nil" do
143
- with_breadcrumb("nil")
144
137
  expect(vivid.exist?("nil", "foo", "bar")).to be false
145
138
  end
146
139
  end
147
140
 
148
141
  context "#read!" do
149
142
  before do
150
- # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
151
- vivid
152
143
  expect(root).not_to receive(:reset_cache)
153
144
  end
154
145
 
155
146
  it "reads hashes deeply" do
156
- with_breadcrumb("one")
157
147
  expect(vivid.read!("one", "two", "three")).to eql("four")
158
148
  end
159
149
 
160
150
  it "reads arrays deeply" do
161
- with_breadcrumb("array")
162
151
  expect(vivid.read!("array", 1)).to eql(1)
163
152
  end
164
153
 
165
154
  it "throws an exception when attributes do not exist" do
166
- with_breadcrumb("one")
167
155
  expect { vivid.read!("one", "five", "six") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
168
156
  end
169
157
 
170
158
  it "throws an exception when traversing a non-container" do
171
- with_breadcrumb("one")
172
159
  expect { vivid.read!("one", "two", "three", "four") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
173
160
  end
174
161
 
175
162
  it "throws an exception when an array element does not exist" do
176
- with_breadcrumb("array")
177
163
  expect { vivid.read!("array", 3) }.to raise_error(Chef::Exceptions::NoSuchAttribute)
178
164
  end
179
165
  end
180
166
 
181
167
  context "#write" do
182
- before do
183
- vivid
184
- expect(root).not_to receive(:reset_cache).with(nil)
185
- end
186
-
187
168
  it "should write into hashes" do
188
- with_breadcrumb("one")
189
169
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
190
170
  vivid.write("one", "five", "six")
191
171
  expect(vivid["one"]["five"]).to eql("six")
192
172
  end
193
173
 
194
174
  it "should deeply autovivify" do
195
- with_breadcrumb("one")
196
175
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
197
176
  vivid.write("one", "five", "six", "seven", "eight", "nine", "ten")
198
177
  expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
199
178
  end
200
179
 
201
180
  it "should raise an exception if you overwrite an array with a hash" do
202
- with_breadcrumb("array")
203
181
  expect(root).to receive(:reset_cache).at_least(:once).with("array")
204
182
  vivid.write("array", "five", "six")
205
183
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => "six" }, "nil" => nil })
206
184
  end
207
185
 
208
186
  it "should raise an exception if you traverse through an array with a hash" do
209
- with_breadcrumb("array")
210
187
  expect(root).to receive(:reset_cache).at_least(:once).with("array")
211
188
  vivid.write("array", "five", "six", "seven")
212
189
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => { "six" => "seven" } }, "nil" => nil })
213
190
  end
214
191
 
215
192
  it "should raise an exception if you overwrite a string with a hash" do
216
- with_breadcrumb("one")
217
193
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
218
194
  vivid.write("one", "two", "three", "four", "five")
219
195
  expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => "five" } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
220
196
  end
221
197
 
222
198
  it "should raise an exception if you traverse through a string with a hash" do
223
- with_breadcrumb("one")
224
199
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
225
200
  vivid.write("one", "two", "three", "four", "five", "six")
226
201
  expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => { "five" => "six" } } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
227
202
  end
228
203
 
229
204
  it "should raise an exception if you overwrite a nil with a hash" do
230
- with_breadcrumb("nil")
231
205
  expect(root).to receive(:reset_cache).at_least(:once).with("nil")
232
206
  vivid.write("nil", "one", "two")
233
207
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => "two" } })
234
208
  end
235
209
 
236
210
  it "should raise an exception if you traverse through a nil with a hash" do
237
- with_breadcrumb("nil")
238
211
  expect(root).to receive(:reset_cache).at_least(:once).with("nil")
239
212
  vivid.write("nil", "one", "two", "three")
240
213
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => { "two" => "three" } } })
241
214
  end
242
215
 
243
216
  it "writes with a block" do
244
- with_breadcrumb("one")
245
217
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
246
218
  vivid.write("one", "five") { "six" }
247
219
  expect(vivid["one"]["five"]).to eql("six")
@@ -249,69 +221,55 @@ describe Chef::Node::VividMash do
249
221
  end
250
222
 
251
223
  context "#write!" do
252
- before do
253
- vivid
254
- expect(root).not_to receive(:reset_cache).with(nil)
255
- end
256
-
257
224
  it "should write into hashes" do
258
- with_breadcrumb("one")
259
225
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
260
226
  vivid.write!("one", "five", "six")
261
227
  expect(vivid["one"]["five"]).to eql("six")
262
228
  end
263
229
 
264
230
  it "should deeply autovivify" do
265
- with_breadcrumb("one")
266
231
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
267
232
  vivid.write!("one", "five", "six", "seven", "eight", "nine", "ten")
268
233
  expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
269
234
  end
270
235
 
271
236
  it "should raise an exception if you overwrite an array with a hash" do
272
- with_breadcrumb("array")
273
237
  expect(root).not_to receive(:reset_cache)
274
238
  expect { vivid.write!("array", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
275
239
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
276
240
  end
277
241
 
278
242
  it "should raise an exception if you traverse through an array with a hash" do
279
- with_breadcrumb("array")
280
243
  expect(root).not_to receive(:reset_cache)
281
244
  expect { vivid.write!("array", "five", "six", "seven") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
282
245
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
283
246
  end
284
247
 
285
248
  it "should raise an exception if you overwrite a string with a hash" do
286
- with_breadcrumb("one")
287
249
  expect(root).not_to receive(:reset_cache)
288
250
  expect { vivid.write!("one", "two", "three", "four", "five") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
289
251
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
290
252
  end
291
253
 
292
254
  it "should raise an exception if you traverse through a string with a hash" do
293
- with_breadcrumb("one")
294
255
  expect(root).not_to receive(:reset_cache)
295
256
  expect { vivid.write!("one", "two", "three", "four", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
296
257
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
297
258
  end
298
259
 
299
260
  it "should raise an exception if you overwrite a nil with a hash" do
300
- with_breadcrumb("nil")
301
261
  expect(root).not_to receive(:reset_cache)
302
262
  expect { vivid.write!("nil", "one", "two") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
303
263
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
304
264
  end
305
265
 
306
266
  it "should raise an exception if you traverse through a nil with a hash" do
307
- with_breadcrumb("nil")
308
267
  expect(root).not_to receive(:reset_cache)
309
268
  expect { vivid.write!("nil", "one", "two", "three") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
310
269
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
311
270
  end
312
271
 
313
272
  it "writes with a block" do
314
- with_breadcrumb("one")
315
273
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
316
274
  vivid.write!("one", "five") { "six" }
317
275
  expect(vivid["one"]["five"]).to eql("six")
@@ -319,41 +277,31 @@ describe Chef::Node::VividMash do
319
277
  end
320
278
 
321
279
  context "#unlink" do
322
- before do
323
- vivid
324
- expect(root).not_to receive(:reset_cache).with(nil)
325
- end
326
-
327
280
  it "should return nil if the keys don't already exist" do
328
- expect(root).to receive(:top_level_breadcrumb=).with(nil).at_least(:once).and_call_original
329
281
  expect(root).not_to receive(:reset_cache)
330
282
  expect(vivid.unlink("five", "six", "seven", "eight")).to eql(nil)
331
283
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
332
284
  end
333
285
 
334
286
  it "should unlink hashes" do
335
- with_breadcrumb("one")
336
287
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
337
288
  expect( vivid.unlink("one") ).to eql({ "two" => { "three" => "four" } })
338
289
  expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
339
290
  end
340
291
 
341
292
  it "should unlink array elements" do
342
- with_breadcrumb("array")
343
293
  expect(root).to receive(:reset_cache).at_least(:once).with("array")
344
294
  expect(vivid.unlink("array", 2)).to eql(2)
345
295
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
346
296
  end
347
297
 
348
298
  it "should unlink nil" do
349
- with_breadcrumb("nil")
350
299
  expect(root).to receive(:reset_cache).at_least(:once).with("nil")
351
300
  expect(vivid.unlink("nil")).to eql(nil)
352
301
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
353
302
  end
354
303
 
355
304
  it "should traverse a nil and safely do nothing" do
356
- with_breadcrumb("nil")
357
305
  expect(root).not_to receive(:reset_cache)
358
306
  expect(vivid.unlink("nil", "foo")).to eql(nil)
359
307
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
@@ -361,41 +309,31 @@ describe Chef::Node::VividMash do
361
309
  end
362
310
 
363
311
  context "#unlink!" do
364
- before do
365
- vivid
366
- expect(root).not_to receive(:reset_cache).with(nil)
367
- end
368
-
369
312
  it "should raise an exception if the keys don't already exist" do
370
- expect(root).to receive(:top_level_breadcrumb=).with(nil).at_least(:once).and_call_original
371
313
  expect(root).not_to receive(:reset_cache)
372
314
  expect { vivid.unlink!("five", "six", "seven", "eight") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
373
315
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
374
316
  end
375
317
 
376
318
  it "should unlink! hashes" do
377
- with_breadcrumb("one")
378
319
  expect(root).to receive(:reset_cache).at_least(:once).with("one")
379
320
  expect( vivid.unlink!("one") ).to eql({ "two" => { "three" => "four" } })
380
321
  expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
381
322
  end
382
323
 
383
324
  it "should unlink! array elements" do
384
- with_breadcrumb("array")
385
325
  expect(root).to receive(:reset_cache).at_least(:once).with("array")
386
326
  expect(vivid.unlink!("array", 2)).to eql(2)
387
327
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
388
328
  end
389
329
 
390
330
  it "should unlink! nil" do
391
- with_breadcrumb("nil")
392
331
  expect(root).to receive(:reset_cache).at_least(:once).with("nil")
393
332
  expect(vivid.unlink!("nil")).to eql(nil)
394
333
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
395
334
  end
396
335
 
397
336
  it "should raise an exception if it traverses a nil" do
398
- with_breadcrumb("nil")
399
337
  expect(root).not_to receive(:reset_cache)
400
338
  expect { vivid.unlink!("nil", "foo") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
401
339
  expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })