chef 18.2.7-x64-mingw-ucrt → 18.3.0-x64-mingw-ucrt

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/chef-universal-mingw-ucrt.gemspec +1 -1
  3. data/lib/chef/application/base.rb +2 -0
  4. data/lib/chef/client.rb +2 -2
  5. data/lib/chef/cookbook/synchronizer.rb +20 -2
  6. data/lib/chef/cookbook_version.rb +1 -1
  7. data/lib/chef/http/ssl_policies.rb +2 -2
  8. data/lib/chef/mixin/homebrew_user.rb +12 -5
  9. data/lib/chef/monkey_patches/net-http.rb +127 -0
  10. data/lib/chef/node/attribute_collections.rb +8 -0
  11. data/lib/chef/node/immutable_collections.rb +5 -2
  12. data/lib/chef/node/mixin/state_tracking.rb +1 -1
  13. data/lib/chef/provider/launchd.rb +1 -1
  14. data/lib/chef/provider/mount/linux.rb +1 -1
  15. data/lib/chef/provider/mount/mount.rb +5 -5
  16. data/lib/chef/provider/package/chocolatey.rb +18 -1
  17. data/lib/chef/provider/package/zypper.rb +1 -0
  18. data/lib/chef/provider/remote_file/http.rb +1 -1
  19. data/lib/chef/provider/yum_repository.rb +1 -1
  20. data/lib/chef/resource/apt_repository.rb +25 -6
  21. data/lib/chef/resource/homebrew_cask.rb +6 -7
  22. data/lib/chef/resource/homebrew_package.rb +1 -1
  23. data/lib/chef/resource/homebrew_tap.rb +5 -5
  24. data/lib/chef/resource/launchd.rb +5 -1
  25. data/lib/chef/resource/windows_certificate.rb +1 -1
  26. data/lib/chef/resource/windows_security_policy.rb +2 -2
  27. data/lib/chef/resource.rb +11 -1
  28. data/lib/chef/version.rb +1 -1
  29. data/lib/chef/win32/security.rb +7 -1
  30. data/spec/functional/resource/chocolatey_package_spec.rb +32 -20
  31. data/spec/functional/resource/execute_spec.rb +1 -1
  32. data/spec/functional/resource/windows_certificate_spec.rb +25 -0
  33. data/spec/unit/client_spec.rb +2 -2
  34. data/spec/unit/mixin/homebrew_user_spec.rb +30 -7
  35. data/spec/unit/node/vivid_mash_spec.rb +42 -0
  36. data/spec/unit/provider/apt_repository_spec.rb +17 -7
  37. data/spec/unit/provider/launchd_spec.rb +2 -2
  38. data/spec/unit/provider/mount/aix_spec.rb +2 -2
  39. data/spec/unit/provider/mount/linux_spec.rb +6 -5
  40. data/spec/unit/provider/mount/mount_spec.rb +8 -8
  41. data/spec/unit/provider/package/chocolatey_spec.rb +19 -3
  42. data/spec/unit/provider/package/rpm_spec.rb +2 -2
  43. data/spec/unit/provider/package/zypper_spec.rb +10 -0
  44. data/spec/unit/provider/remote_file/http_spec.rb +4 -4
  45. data/spec/unit/resource/apt_repository_spec.rb +5 -0
  46. data/spec/unit/resource_spec.rb +86 -0
  47. metadata +13 -12
  48. /data/spec/functional/assets/chocolatey_feed/{test-A.1.0.nupkg → test-A.1.0.0.nupkg} +0 -0
  49. /data/spec/functional/assets/chocolatey_feed/{test-A.1.5.nupkg → test-A.1.5.0.nupkg} +0 -0
  50. /data/spec/functional/assets/chocolatey_feed/{test-A.2.0.nupkg → test-A.2.0.0.nupkg} +0 -0
  51. /data/spec/functional/assets/chocolatey_feed/{test-B.1.0.nupkg → test-B.1.0.0.nupkg} +0 -0
@@ -118,13 +118,13 @@ class Chef
118
118
  file.write("[Unicode]\r\nUnicode=yes\r\n[System Access]\r\n#{policy_line}\r\n[Version]\r\nsignature=\"$CHICAGO$\"\r\nRevision=1\r\n")
119
119
  file.close
120
120
  file_path = file.path.tr("/", "\\")
121
- cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg #{file_path} /areas SECURITYPOLICY"
121
+ cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg \"#{file_path}\" /areas SECURITYPOLICY"
122
122
  else
123
123
  policy_line = "#{security_option} = #{security_value}"
124
124
  file.write("[Unicode]\r\nUnicode=yes\r\n[System Access]\r\n#{policy_line}\r\n[Version]\r\nsignature=\"$CHICAGO$\"\r\nRevision=1\r\n")
125
125
  file.close
126
126
  file_path = file.path.tr("/", "\\")
127
- cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg #{file_path} /areas SECURITYPOLICY"
127
+ cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg \"#{file_path}\" /areas SECURITYPOLICY"
128
128
  end
129
129
  shell_out!(cmd)
130
130
  file.unlink
data/lib/chef/resource.rb CHANGED
@@ -1508,7 +1508,17 @@ class Chef
1508
1508
  dirname = ::File.dirname(partial)
1509
1509
  basename = ::File.basename(partial, ".rb")
1510
1510
  basename = basename[1..] if basename.start_with?("_")
1511
- class_eval IO.read(::File.expand_path("#{dirname}/_#{basename}.rb", ::File.dirname(caller_locations.first.path)))
1511
+
1512
+ # Support recursive `use`
1513
+ callers = caller_locations
1514
+ used_from = if callers.first.label == "use"
1515
+ callers.detect { |caller| caller.label == "class_from_file" }.path
1516
+ else
1517
+ callers.first.path
1518
+ end
1519
+
1520
+ fullpath = ::File.expand_path("#{dirname}/_#{basename}.rb", ::File.dirname(used_from))
1521
+ class_eval IO.read(fullpath)
1512
1522
  end
1513
1523
  end
1514
1524
 
data/lib/chef/version.rb CHANGED
@@ -23,7 +23,7 @@ require_relative "version_string"
23
23
 
24
24
  class Chef
25
25
  CHEF_ROOT = File.expand_path("..", __dir__)
26
- VERSION = Chef::VersionString.new("18.2.7")
26
+ VERSION = Chef::VersionString.new("18.3.0")
27
27
  end
28
28
 
29
29
  #
@@ -721,7 +721,13 @@ class Chef
721
721
  unless LogonUserW(username, domain, password, logon_type, logon_provider, token)
722
722
  Chef::ReservedNames::Win32::Error.raise!
723
723
  end
724
- Token.new(Handle.new(token.read_pointer))
724
+
725
+ # originally this was .read_pointer, but that is interpreted as a non-primitive
726
+ # class (FFI::Pointer) and causes an ArgumentError (Invalid Memory Object) when
727
+ # compared to GetCurrentProcess(), which returns a HANDLE (void *). Since a
728
+ # HANDLE is not a pointer to allocated memory that Ruby C extensions can understand,
729
+ # the Invalid Memory Object error is raised.
730
+ Token.new(Handle.new(token.read_ulong))
725
731
  end
726
732
 
727
733
  def self.test_and_raise_lsa_nt_status(result)
@@ -22,8 +22,16 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
22
22
  include Chef::Mixin::ShellOut
23
23
 
24
24
  let(:package_name) { "test-A" }
25
- let(:package_list) { proc { shell_out!("choco list -lo -r #{Array(package_name).join(" ")}").stdout.chomp } }
26
25
  let(:package_source) { File.join(CHEF_SPEC_ASSETS, "chocolatey_feed") }
26
+ let(:package_list) do
27
+ if Chef::Provider::Package::Chocolatey.query_command == "list"
28
+ # using result of query_command because that indicates which "search" command to use
29
+ # which coincides with the package list output
30
+ proc { shell_out!("choco search -lo #{Array(package_name).join(" ")}").stdout.chomp }
31
+ else
32
+ proc { shell_out!("choco list #{Array(package_name).join(" ")}").stdout.chomp }
33
+ end
34
+ end
27
35
 
28
36
  let(:run_context) do
29
37
  Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new)
@@ -54,12 +62,16 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
54
62
  ENV["Path"] = ENV.delete("Path")
55
63
  end
56
64
 
65
+ after(:each) do
66
+ described_class.instance_variable_set(:@get_choco_version, nil)
67
+ end
68
+
57
69
  context "installing a package" do
58
70
  after { remove_package }
59
71
 
60
72
  it "installs the latest version" do
61
73
  subject.run_action(:install)
62
- expect(package_list.call).to eq("#{package_name}|2.0")
74
+ expect(package_list.call).to match(/^#{package_name}|2.0.0$/)
63
75
  end
64
76
 
65
77
  it "does not install if already installed" do
@@ -69,19 +81,19 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
69
81
  end
70
82
 
71
83
  it "installs version given" do
72
- subject.version "1.0"
84
+ subject.version "1.0.0"
73
85
  subject.run_action(:install)
74
- expect(package_list.call).to eq("#{package_name}|1.0")
86
+ expect(package_list.call).to match(/^#{package_name}|1.0.0$/)
75
87
  end
76
88
 
77
89
  it "installs new version if one is already installed" do
78
- subject.version "1.0"
90
+ subject.version "1.0.0"
79
91
  subject.run_action(:install)
80
- expect(package_list.call).to eq("#{package_name}|1.0")
92
+ expect(package_list.call).to match(/^#{package_name}|1.0.0$/)
81
93
 
82
- subject.version "2.0"
94
+ subject.version "2.0.0"
83
95
  subject.run_action(:install)
84
- expect(package_list.call).to eq("#{package_name}|2.0")
96
+ expect(package_list.call).to match(/^#{package_name}|2.0.0$/)
85
97
  end
86
98
 
87
99
  context "installing multiple packages" do
@@ -89,7 +101,7 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
89
101
 
90
102
  it "installs both packages" do
91
103
  subject.run_action(:install)
92
- expect(package_list.call).to eq("test-A|2.0\r\ntest-B|1.0")
104
+ expect(package_list.call).to match(/^test-A|2.0.0\r\ntest-B|1.0.0$/)
93
105
  end
94
106
  end
95
107
 
@@ -101,13 +113,13 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
101
113
  it "installs with an option as a string" do
102
114
  subject.options "--force --confirm"
103
115
  subject.run_action(:install)
104
- expect(package_list.call).to eq("#{package_name}|2.0")
116
+ expect(package_list.call).to match(/^#{package_name}|2.0.0$/)
105
117
  end
106
118
 
107
119
  it "installs with multiple options as a string" do
108
120
  subject.options "--force --confirm"
109
121
  subject.run_action(:install)
110
- expect(package_list.call).to eq("#{package_name}|2.0")
122
+ expect(package_list.call).to match(/^#{package_name}|2.0.0$/)
111
123
  end
112
124
 
113
125
  context "when multiple options passed as string" do
@@ -137,7 +149,7 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
137
149
  it "installs with multiple options as an array" do
138
150
  subject.options [ "--force", "--confirm" ]
139
151
  subject.run_action(:install)
140
- expect(package_list.call).to eq("#{package_name}|2.0")
152
+ expect(package_list.call).to match(/^#{package_name}|2.0.0$/)
141
153
  end
142
154
  end
143
155
 
@@ -145,24 +157,24 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
145
157
  after { remove_package }
146
158
 
147
159
  it "upgrades to a specific version" do
148
- subject.version "1.0"
160
+ subject.version "1.0.0"
149
161
  subject.run_action(:install)
150
- expect(package_list.call).to eq("#{package_name}|1.0")
162
+ expect(package_list.call).to match(/^#{package_name}|1.0.0$/)
151
163
 
152
- subject.version "1.5"
164
+ subject.version "1.5.0"
153
165
  subject.run_action(:upgrade)
154
- expect(package_list.call).to eq("#{package_name}|1.5")
166
+ expect(package_list.call).to match(/^#{package_name}|1.5.0$/)
155
167
  end
156
168
 
157
169
  it "upgrades to the latest version if no version given" do
158
- subject.version "1.0"
170
+ subject.version "1.0.0"
159
171
  subject.run_action(:install)
160
- expect(package_list.call).to eq("#{package_name}|1.0")
172
+ expect(package_list.call).to match(/^#{package_name}|1.0.0$/)
161
173
 
162
174
  subject2 = Chef::Resource::ChocolateyPackage.new("test-A", run_context)
163
175
  subject2.source package_source
164
176
  subject2.run_action(:upgrade)
165
- expect(package_list.call).to eq("#{package_name}|2.0")
177
+ expect(package_list.call).to match(/^#{package_name}|2.0.0$/)
166
178
  end
167
179
  end
168
180
 
@@ -170,7 +182,7 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
170
182
  it "removes an installed package" do
171
183
  subject.run_action(:install)
172
184
  remove_package
173
- expect(package_list.call).to eq("")
185
+ expect(package_list.call).to match(/0 packages installed/)
174
186
  end
175
187
  end
176
188
 
@@ -62,7 +62,7 @@ describe Chef::Resource::Execute do
62
62
  end
63
63
 
64
64
  describe "when parent resource sets :cwd" do
65
- let(:guard) { %{ruby -e 'exit 1 unless File.exists?("./nested.json")'} }
65
+ let(:guard) { %{ruby -e 'exit 1 unless File.exist?("./nested.json")'} }
66
66
 
67
67
  it "guard inherits :cwd from resource and runs" do
68
68
  resource.cwd CHEF_SPEC_DATA
@@ -56,6 +56,30 @@ describe Chef::Resource::WindowsCertificate, :windows_only do
56
56
  let(:store) { "Chef-Functional-Test" }
57
57
  let(:store_name) { "MY" }
58
58
  let(:store_location) { "LocalMachine" }
59
+ let(:test_cert_body) do
60
+ <<~CERT
61
+ -----BEGIN CERTIFICATE-----
62
+ MIIDQTCCAimgAwIBAgIQX3zqNCJbsKlEvzCz3Z9aNDANBgkqhkiG9w0BAQsFADAh
63
+ MR8wHQYDVQQDDBZ3d3cuZHVtbXljaGVmdGVzdHMuY29tMCAXDTIwMDMwNTEwMjcw
64
+ NVoYDzIxMjAwMzA1MTAzNzA2WjAhMR8wHQYDVQQDDBZ3d3cuZHVtbXljaGVmdGVz
65
+ dHMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtuYKDb6woWIH
66
+ HPPOrcVpgJFVxbkjgk+tsYwbIiqR9jtRaKE6nM/awOgn9/dFF4k8KB8Em0sUx7Vq
67
+ J3YhK2N2cAacgP2Frqqf5znpNBBOg968RoZzGx0EiXFvLsqC4y8ggApWTbMXPRk4
68
+ 1a7GlpUpSqI3y5cLeEbzwGQKu8I1I+v7P2fTlnJPHarM7sBbL8bieukkFHYu78iV
69
+ u1wpKOCCfs5DTmJu8WN+z1Mar9vyrWMBlt2wBBgNHPz5mcXUzJHTzaI/D9RGgBgF
70
+ V0IkNqISx/IzR62jjj2g6MgTH4G/0mM6O5sxduM4yGmWZNZpVzh0yMLgH619MZlj
71
+ SMQIN3U/SQIDAQABo3MwcTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYB
72
+ BQUHAwIGCCsGAQUFBwMBMCEGA1UdEQQaMBiCFnd3dy5kdW1teWNoZWZ0ZXN0cy5j
73
+ b20wHQYDVR0OBBYEFHwS3gs03m6RcpR+66u4OqGiZdYnMA0GCSqGSIb3DQEBCwUA
74
+ A4IBAQCFHqMjHUfBZahIsKHQIcFCbC1NFh1ZHlJKZzrRBRwRzX19OttHGMyLpDd6
75
+ tM9Ac6LLR8S4QIWg+HF3IrkN+vfTRDZAccj+tIwBRstmdsEz/rAJ79Vb/00mXZQx
76
+ 0FPiBDR3hE7On2oo24DU8kJP3v6TrunwtIomVGqrrkwZzvxqyW+WJMB2shGNFw5J
77
+ mKYBiiXsHl4Bi7V4zhXssrLp877sqpNLeXloXBmAlT39SwQTP9ImZaV5R6udqlvo
78
+ Gfgm5PH/WeK6MV3n5ik0v1rS0LwR2o82WlIB6a4iSEbzY3qSLsWOwt8o5QjAVzCR
79
+ tNdbdS3U8nrG73iA2clmF57ARQWC
80
+ -----END CERTIFICATE-----
81
+ CERT
82
+ end
59
83
  let(:download_cert_url) { "https://testingchef.blob.core.windows.net/files/test.cer" }
60
84
  let(:cert_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.cer") }
61
85
  let(:pfx_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.pfx") }
@@ -128,6 +152,7 @@ describe Chef::Resource::WindowsCertificate, :windows_only do
128
152
  end
129
153
 
130
154
  it "can add a certificate from a valid url" do
155
+ stub_request(:get, download_cert_url).to_return(body: test_cert_body)
131
156
  resource.source = download_cert_url
132
157
  resource.run_action(:create)
133
158
 
@@ -119,8 +119,8 @@ shared_context "a client run" do
119
119
  # Make sure Client#register thinks the client key doesn't
120
120
  # exist, so it tries to register and create one.
121
121
  allow(Chef::HTTP::Authenticator).to receive(:detect_certificate_key).with(fqdn).and_return(false)
122
- allow(File).to receive(:exists?).and_call_original
123
- expect(File).to receive(:exists?)
122
+ allow(File).to receive(:exist?).and_call_original
123
+ expect(File).to receive(:exist?)
124
124
  .with(Chef::Config[:client_key])
125
125
  .exactly(:once)
126
126
  .and_return(api_client_exists?)
@@ -47,6 +47,8 @@ describe Chef::Mixin::HomebrewUser do
47
47
  let(:user) { nil }
48
48
  let(:brew_owner) { 2001 }
49
49
  let(:default_brew_path) { "/usr/local/bin/brew" }
50
+ let(:default_brew_path_arm) { "/opt/homebrew/bin/brew" }
51
+ let(:default_brew_path_linux) { "/home/linuxbrew/.linuxbrew/bin/brew" }
50
52
  let(:stat_double) do
51
53
  d = double
52
54
  expect(d).to receive(:uid).and_return(brew_owner)
@@ -59,16 +61,38 @@ describe Chef::Mixin::HomebrewUser do
59
61
  expect(Etc).to receive(:getpwuid).with(brew_owner).and_return(OpenStruct.new(name: "name"))
60
62
  end
61
63
 
62
- it "returns the owner of the brew executable when it is at a default location" do
63
- expect(File).to receive(:exist?).with(default_brew_path).and_return(true)
64
- expect(File).to receive(:stat).with(default_brew_path).and_return(stat_double)
64
+ def false_unless_specific_value(object, method, value)
65
+ allow(object).to receive(method).and_return(false)
66
+ allow(object).to receive(method).with(value).and_return(true)
67
+ end
68
+
69
+ it "returns the owner of the brew executable when it is at a default location for x86_64 machines" do
70
+ false_unless_specific_value(File, :exist?, default_brew_path)
71
+ false_unless_specific_value(File, :executable?, default_brew_path)
72
+ allow(File).to receive(:stat).with(default_brew_path).and_return(stat_double)
73
+ expect(homebrew_user.find_homebrew_uid(user)).to eq(brew_owner)
74
+ end
75
+
76
+ it "returns the owner of the brew executable when it is at a default location for arm machines" do
77
+ false_unless_specific_value(File, :exist?, default_brew_path_arm)
78
+ false_unless_specific_value(File, :executable?, default_brew_path_arm)
79
+ allow(File).to receive(:stat).with(default_brew_path_arm).and_return(stat_double)
80
+ expect(homebrew_user.find_homebrew_uid(user)).to eq(brew_owner)
81
+ end
82
+
83
+ it "returns the owner of the brew executable when it is at a default location for linux machines" do
84
+ false_unless_specific_value(File, :exist?, default_brew_path_linux)
85
+ false_unless_specific_value(File, :executable?, default_brew_path_linux)
86
+ allow(File).to receive(:stat).with(default_brew_path_linux).and_return(stat_double)
65
87
  expect(homebrew_user.find_homebrew_uid(user)).to eq(brew_owner)
66
88
  end
67
89
 
68
90
  it "returns the owner of the brew executable when it is not at a default location" do
69
- expect(File).to receive(:exist?).with(default_brew_path).and_return(false)
91
+ allow_any_instance_of(ExampleHomebrewUser).to receive(:which).and_return("/foo")
92
+ false_unless_specific_value(File, :exist?, "/foo")
93
+ false_unless_specific_value(File, :executable?, "/foo")
70
94
  allow(homebrew_user).to receive_message_chain(:shell_out, :stdout, :strip).and_return("/foo")
71
- expect(File).to receive(:stat).with("/foo").and_return(stat_double)
95
+ allow(File).to receive(:stat).with("/foo").and_return(stat_double)
72
96
  expect(homebrew_user.find_homebrew_uid(user)).to eq(brew_owner)
73
97
  end
74
98
 
@@ -78,8 +102,7 @@ describe Chef::Mixin::HomebrewUser do
78
102
  describe "when the homebrew user is not provided" do
79
103
 
80
104
  it "raises an error if no executable is found" do
81
- expect(File).to receive(:exist?).with(default_brew_path).and_return(false)
82
- allow(homebrew_user).to receive_message_chain(:shell_out, :stdout, :strip).and_return("")
105
+ expect(File).to receive(:exist?).and_return(nil).at_least(:once)
83
106
  expect { homebrew_user.find_homebrew_uid(user) }.to raise_error(Chef::Exceptions::CannotDetermineHomebrewOwner)
84
107
  end
85
108
 
@@ -364,20 +364,53 @@ describe Chef::Node::AttrArray do
364
364
 
365
365
  context "#<<" do
366
366
  it "converts a Hash appended with #<< to a VividMash" do
367
+ expect(root).to receive(:reset_cache).with(nil)
367
368
  array << { "three" => "four" }
368
369
  expect(array[3].class).to eql(Chef::Node::VividMash)
369
370
  end
370
371
 
371
372
  it "deeply converts objects appended with #<<" do
373
+ expect(root).to receive(:reset_cache).with(nil)
372
374
  array << [ { "three" => [ 0, 1] } ]
373
375
  expect(array[3].class).to eql(Chef::Node::AttrArray)
374
376
  expect(array[3][0].class).to eql(Chef::Node::VividMash)
375
377
  expect(array[3][0]["three"].class).to eql(Chef::Node::AttrArray)
376
378
  end
379
+
380
+ it "does not invalidate root DeepMergeCache if VividMash top-level key" do
381
+ # We're checking that __path__ is used to avoid full DeepMergeCache invalidation
382
+ expect(root).to receive(:reset_cache).with("array")
383
+ expect(root).not_to receive(:reset_cache).with(nil)
384
+
385
+ attr_array = Chef::Node::AttrArray.new([ 0, 1, 2 ])
386
+ vivid = Chef::Node::VividMash.new(
387
+ { "one" => { "two" => { "three" => "four" } }, "array" => attr_array },
388
+ root
389
+ )
390
+ vivid["array"] << 3
391
+ end
392
+
393
+ it "does not send reset_cache with nil if VividMashi nested key" do
394
+ # We're checking that __path__ is used to avoid full DeepMergeCache invalidation,
395
+ # and that it is invalidating the top-level key
396
+ expect(root).to receive(:reset_cache).with("array")
397
+ expect(root).not_to receive(:reset_cache).with(nil)
398
+
399
+ attr_array = Chef::Node::AttrArray.new([ 0, 1, 2 ])
400
+ vivid = Chef::Node::VividMash.new(
401
+ {
402
+ "one" => { "two" => { "three" => "four" } },
403
+ "array" => { "nested" => attr_array },
404
+ },
405
+ root
406
+ )
407
+ vivid["array"]["nested"] << 3
408
+ end
377
409
  end
378
410
 
379
411
  context "#[]=" do
380
412
  it "assigning a Hash into an array converts it to VividMash" do
413
+ expect(root).to receive(:reset_cache).with(nil)
381
414
  array[0] = { "zero" => "zero2" }
382
415
  expect(array[0].class).to eql(Chef::Node::VividMash)
383
416
  end
@@ -385,6 +418,7 @@ describe Chef::Node::AttrArray do
385
418
 
386
419
  context "#push" do
387
420
  it "pushing a Hash into an array converts it to VividMash" do
421
+ expect(root).to receive(:reset_cache).with(nil)
388
422
  array.push({ "three" => "four" })
389
423
  expect(array[3].class).to eql(Chef::Node::VividMash)
390
424
  end
@@ -392,6 +426,7 @@ describe Chef::Node::AttrArray do
392
426
 
393
427
  context "#unshift" do
394
428
  it "unshifting a Hash into an array converts it to VividMash" do
429
+ expect(root).to receive(:reset_cache).with(nil)
395
430
  array.unshift({ "zero" => "zero2" })
396
431
  expect(array[0].class).to eql(Chef::Node::VividMash)
397
432
  end
@@ -399,6 +434,7 @@ describe Chef::Node::AttrArray do
399
434
 
400
435
  context "#insert" do
401
436
  it "inserting a Hash into an array converts it to VividMash" do
437
+ expect(root).to receive(:reset_cache).with(nil)
402
438
  array.insert(1, { "zero" => "zero2" })
403
439
  expect(array[1].class).to eql(Chef::Node::VividMash)
404
440
  end
@@ -406,6 +442,7 @@ describe Chef::Node::AttrArray do
406
442
 
407
443
  context "#collect!" do
408
444
  it "converts Hashes" do
445
+ expect(root).to receive(:reset_cache).at_least(:once).with(nil)
409
446
  array.collect! { |x| { "zero" => "zero2" } }
410
447
  expect(array[1].class).to eql(Chef::Node::VividMash)
411
448
  end
@@ -413,6 +450,7 @@ describe Chef::Node::AttrArray do
413
450
 
414
451
  context "#map!" do
415
452
  it "converts Hashes" do
453
+ expect(root).to receive(:reset_cache).with(nil)
416
454
  array.map! { |x| { "zero" => "zero2" } }
417
455
  expect(array[1].class).to eql(Chef::Node::VividMash)
418
456
  end
@@ -420,6 +458,7 @@ describe Chef::Node::AttrArray do
420
458
 
421
459
  context "#compact!" do
422
460
  it "VividMashes remain VividMashes" do
461
+ expect(root).to receive(:reset_cache).with(nil)
423
462
  array = Chef::Node::AttrArray.new(
424
463
  [ nil, { "one" => "two" }, nil ],
425
464
  root
@@ -432,6 +471,7 @@ describe Chef::Node::AttrArray do
432
471
 
433
472
  context "#fill" do
434
473
  it "inserts VividMashes for Hashes" do
474
+ expect(root).to receive(:reset_cache).at_least(:once).with(nil)
435
475
  array.fill({ "one" => "two" })
436
476
  expect(array[0].class).to eql(Chef::Node::VividMash)
437
477
  end
@@ -439,6 +479,7 @@ describe Chef::Node::AttrArray do
439
479
 
440
480
  context "#flatten!" do
441
481
  it "flattens sub-arrays maintaining VividMashes in them" do
482
+ expect(root).to receive(:reset_cache).with(nil)
442
483
  array = Chef::Node::AttrArray.new(
443
484
  [ [ { "one" => "two" } ], [ { "one" => "two" } ] ],
444
485
  root
@@ -451,6 +492,7 @@ describe Chef::Node::AttrArray do
451
492
 
452
493
  context "#replace" do
453
494
  it "replaces the array converting hashes to mashes" do
495
+ expect(root).to receive(:reset_cache).with(nil)
454
496
  array.replace([ { "foo" => "bar" } ])
455
497
  expect(array[0].class).to eql(Chef::Node::VividMash)
456
498
  end
@@ -246,33 +246,43 @@ C5986B4F1257FFA86632CBA746181433FBB75451
246
246
  describe "#build_repo" do
247
247
  it "creates a repository string" do
248
248
  target = "deb http://test/uri unstable main\n"
249
- expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil)).to eql(target)
249
+ expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil, [])).to eql(target)
250
250
  end
251
251
 
252
252
  it "creates a repository string with spaces" do
253
253
  target = "deb http://test/uri%20with%20spaces unstable main\n"
254
- expect(provider.build_repo("http://test/uri with spaces", "unstable", "main", false, nil)).to eql(target)
254
+ expect(provider.build_repo("http://test/uri with spaces", "unstable", "main", false, nil, [])).to eql(target)
255
255
  end
256
256
 
257
257
  it "creates a repository string with no distribution" do
258
258
  target = "deb http://test/uri main\n"
259
- expect(provider.build_repo("http://test/uri", nil, "main", false, nil)).to eql(target)
259
+ expect(provider.build_repo("http://test/uri", nil, "main", false, nil, [])).to eql(target)
260
260
  end
261
261
 
262
262
  it "creates a repository string with source" do
263
263
  target = "deb http://test/uri unstable main\ndeb-src http://test/uri unstable main\n"
264
- expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil, true)).to eql(target)
264
+ expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil, [], true)).to eql(target)
265
265
  end
266
266
 
267
- it "creates a repository string with options" do
267
+ it "creates a repository string with trusted" do
268
268
  target = "deb [trusted=yes] http://test/uri unstable main\n"
269
- expect(provider.build_repo("http://test/uri", "unstable", "main", true, nil)).to eql(target)
269
+ expect(provider.build_repo("http://test/uri", "unstable", "main", true, nil, [])).to eql(target)
270
+ end
271
+
272
+ it "creates a repository string with custom options" do
273
+ target = "deb [by-hash=no] http://test/uri unstable main\n"
274
+ expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil, ["by-hash=no"])).to eql(target)
275
+ end
276
+
277
+ it "creates a repository string with trusted, arch, and custom options" do
278
+ target = "deb [arch=amd64 trusted=yes by-hash=no] http://test/uri unstable main\n"
279
+ expect(provider.build_repo("http://test/uri", "unstable", "main", true, "amd64", ["by-hash=no"])).to eql(target)
270
280
  end
271
281
 
272
282
  it "handles a ppa repo" do
273
283
  target = "deb http://ppa.launchpad.net/chef/main/ubuntu unstable main\n"
274
284
  expect(provider).to receive(:make_ppa_url).with("ppa:chef/main").and_return("http://ppa.launchpad.net/chef/main/ubuntu")
275
- expect(provider.build_repo("ppa:chef/main", "unstable", "main", false, nil)).to eql(target)
285
+ expect(provider.build_repo("ppa:chef/main", "unstable", "main", false, nil, [])).to eql(target)
276
286
  end
277
287
  end
278
288
  end
@@ -197,7 +197,7 @@ describe Chef::Provider::Launchd do
197
197
  describe "with an :delete action" do
198
198
  describe "and the ld file is present" do
199
199
  before(:each) do
200
- allow(File).to receive(:exists?).and_return(true)
200
+ allow(File).to receive(:exist?).and_return(true)
201
201
  allow(provider).to receive(
202
202
  :manage_service
203
203
  ).with(:disable).and_return(true)
@@ -218,7 +218,7 @@ describe Chef::Provider::Launchd do
218
218
 
219
219
  describe "and the ld file is not present" do
220
220
  before(:each) do
221
- allow(File).to receive(:exists?).and_return(false)
221
+ allow(File).to receive(:exist?).and_return(false)
222
222
  allow(provider).to receive(
223
223
  :manage_plist
224
224
  ).with(:delete).and_return(true)
@@ -65,8 +65,8 @@ describe Chef::Provider::Mount::Aix do
65
65
 
66
66
  @provider = Chef::Provider::Mount::Aix.new(@new_resource, @run_context)
67
67
 
68
- allow(::File).to receive(:exists?).with("/dev/sdz1").and_return true
69
- allow(::File).to receive(:exists?).with("/tmp/foo").and_return true
68
+ allow(::File).to receive(:exist?).with("/dev/sdz1").and_return true
69
+ allow(::File).to receive(:exist?).with("/tmp/foo").and_return true
70
70
  end
71
71
 
72
72
  def stub_mounted(provider, mounted_output)
@@ -22,10 +22,11 @@ describe Chef::Provider::Mount::Linux do
22
22
  end
23
23
 
24
24
  before(:each) do
25
- allow(::File).to receive(:exists?).with("/dev/sdz1").and_return true
26
- allow(::File).to receive(:exists?).with("/tmp/foo").and_return true
27
- allow(::File).to receive(:exists?).with("//192.168.11.102/Share/backup").and_return true
28
- allow(::File).to receive(:exists?).with("//192.168.11.102/Share/backup folder").and_return true
25
+ allow(::File).to receive(:exist?).with("/etc/fstab").and_call_original
26
+ allow(::File).to receive(:exist?).with("/dev/sdz1").and_return true
27
+ allow(::File).to receive(:exist?).with("/tmp/foo").and_return true
28
+ allow(::File).to receive(:exist?).with("//192.168.11.102/Share/backup").and_return true
29
+ allow(::File).to receive(:exist?).with("//192.168.11.102/Share/backup folder").and_return true
29
30
  allow(::File).to receive(:realpath).with("/dev/sdz1").and_return "/dev/sdz1"
30
31
  allow(::File).to receive(:realpath).with("/tmp/foo").and_return "/tmp/foo"
31
32
  end
@@ -127,4 +128,4 @@ describe Chef::Provider::Mount::Linux do
127
128
  end
128
129
  end
129
130
 
130
- end
131
+ end
@@ -34,8 +34,8 @@ describe Chef::Provider::Mount::Mount do
34
34
 
35
35
  @provider = Chef::Provider::Mount::Mount.new(@new_resource, @run_context)
36
36
 
37
- allow(::File).to receive(:exists?).with("/dev/sdz1").and_return true
38
- allow(::File).to receive(:exists?).with("/tmp/foo").and_return true
37
+ allow(::File).to receive(:exist?).with("/dev/sdz1").and_return true
38
+ allow(::File).to receive(:exist?).with("/tmp/foo").and_return true
39
39
  allow(::File).to receive(:realpath).with("/dev/sdz1").and_return "/dev/sdz1"
40
40
  allow(::File).to receive(:realpath).with("/tmp/foo").and_return "/tmp/foo"
41
41
  end
@@ -83,12 +83,12 @@ describe Chef::Provider::Mount::Mount do
83
83
  end
84
84
 
85
85
  it "should raise an error if the mount device does not exist" do
86
- allow(::File).to receive(:exists?).with("/dev/sdz1").and_return false
86
+ allow(::File).to receive(:exist?).with("/dev/sdz1").and_return false
87
87
  expect { @provider.load_current_resource; @provider.mountable? }.to raise_error(Chef::Exceptions::Mount)
88
88
  end
89
89
 
90
90
  it "should not call mountable? with load_current_resource - CHEF-1565" do
91
- allow(::File).to receive(:exists?).with("/dev/sdz1").and_return false
91
+ allow(::File).to receive(:exist?).with("/dev/sdz1").and_return false
92
92
  expect(@provider).to receive(:mounted?).and_return(true)
93
93
  expect(@provider).to receive(:enabled?).and_return(true)
94
94
  expect(@provider).not_to receive(:mountable?)
@@ -100,12 +100,12 @@ describe Chef::Provider::Mount::Mount do
100
100
  @new_resource.device_type :uuid
101
101
  @new_resource.device "d21afe51-a0fe-4dc6-9152-ac733763ae0a"
102
102
  expect(@provider).to receive(:shell_out_compacted).with("/sbin/findfs", "UUID=d21afe51-a0fe-4dc6-9152-ac733763ae0a").and_return(status)
103
- expect(::File).to receive(:exists?).with("").and_return(false)
103
+ expect(::File).to receive(:exist?).with("").and_return(false)
104
104
  expect { @provider.load_current_resource; @provider.mountable? }.to raise_error(Chef::Exceptions::Mount)
105
105
  end
106
106
 
107
107
  it "should raise an error if the mount point does not exist" do
108
- allow(::File).to receive(:exists?).with("/tmp/foo").and_return false
108
+ allow(::File).to receive(:exist?).with("/tmp/foo").and_return false
109
109
  expect { @provider.load_current_resource; @provider.mountable? }.to raise_error(Chef::Exceptions::Mount)
110
110
  end
111
111
 
@@ -521,8 +521,8 @@ describe Chef::Provider::Mount::Mount do
521
521
 
522
522
  @provider = Chef::Provider::Mount::Mount.new(@new_resource, @run_context)
523
523
 
524
- allow(::File).to receive(:exists?).with("cephserver:6789:/").and_return true
525
- allow(::File).to receive(:exists?).with("/tmp/bar").and_return true
524
+ allow(::File).to receive(:exist?).with("cephserver:6789:/").and_return true
525
+ allow(::File).to receive(:exist?).with("/tmp/bar").and_return true
526
526
  allow(::File).to receive(:realpath).with("cephserver:6789:/").and_return "cephserver:6789:/"
527
527
  allow(::File).to receive(:realpath).with("/tmp/bar").and_return "/tmp/foo"
528
528
  end