chef 18.2.7 → 18.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/chef-universal-mingw-ucrt.gemspec +1 -1
  4. data/chef.gemspec +3 -3
  5. data/lib/chef/application/base.rb +2 -0
  6. data/lib/chef/chef_fs/file_pattern.rb +1 -1
  7. data/lib/chef/chef_fs/path_utils.rb +7 -9
  8. data/lib/chef/client.rb +2 -2
  9. data/lib/chef/cookbook/synchronizer.rb +19 -2
  10. data/lib/chef/cookbook_version.rb +1 -1
  11. data/lib/chef/delayed_evaluator.rb +4 -0
  12. data/lib/chef/file_access_control/windows.rb +4 -1
  13. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +2 -0
  14. data/lib/chef/http/ssl_policies.rb +2 -2
  15. data/lib/chef/mixin/homebrew_user.rb +15 -5
  16. data/lib/chef/monkey_patches/net-http.rb +127 -0
  17. data/lib/chef/node/attribute_collections.rb +10 -1
  18. data/lib/chef/node/immutable_collections.rb +7 -3
  19. data/lib/chef/node/mixin/state_tracking.rb +1 -1
  20. data/lib/chef/node/mixin/state_tracking_array.rb +41 -0
  21. data/lib/chef/node.rb +22 -0
  22. data/lib/chef/provider/launchd.rb +1 -1
  23. data/lib/chef/provider/mount/linux.rb +1 -1
  24. data/lib/chef/provider/mount/mount.rb +5 -5
  25. data/lib/chef/provider/package/apt.rb +11 -2
  26. data/lib/chef/provider/package/chocolatey.rb +239 -18
  27. data/lib/chef/provider/package/zypper.rb +6 -0
  28. data/lib/chef/provider/powershell_script.rb +96 -6
  29. data/lib/chef/provider/remote_file/http.rb +1 -1
  30. data/lib/chef/provider/service/systemd.rb +23 -8
  31. data/lib/chef/provider/service/windows.rb +1 -0
  32. data/lib/chef/provider/service.rb +14 -0
  33. data/lib/chef/provider/user.rb +5 -1
  34. data/lib/chef/provider/yum_repository.rb +1 -1
  35. data/lib/chef/recipe.rb +3 -11
  36. data/lib/chef/resource/_rest_resource.rb +1 -1
  37. data/lib/chef/resource/apt_package.rb +19 -0
  38. data/lib/chef/resource/apt_repository.rb +26 -6
  39. data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
  40. data/lib/chef/resource/chocolatey_installer.rb +207 -0
  41. data/lib/chef/resource/chocolatey_package.rb +8 -0
  42. data/lib/chef/resource/homebrew_cask.rb +6 -7
  43. data/lib/chef/resource/homebrew_package.rb +1 -1
  44. data/lib/chef/resource/homebrew_tap.rb +5 -5
  45. data/lib/chef/resource/launchd.rb +5 -1
  46. data/lib/chef/resource/locale.rb +5 -2
  47. data/lib/chef/resource/macos_pkg.rb +111 -0
  48. data/lib/chef/resource/powershell_script.rb +5 -1
  49. data/lib/chef/resource/service.rb +3 -0
  50. data/lib/chef/resource/sudo.rb +37 -2
  51. data/lib/chef/resource/support/ulimit.erb +40 -0
  52. data/lib/chef/resource/user_ulimit.rb +38 -0
  53. data/lib/chef/resource/windows_certificate.rb +1 -1
  54. data/lib/chef/resource/windows_security_policy.rb +2 -2
  55. data/lib/chef/resource.rb +11 -1
  56. data/lib/chef/resources.rb +2 -0
  57. data/lib/chef/version.rb +1 -1
  58. data/lib/chef/win32/security.rb +7 -1
  59. data/spec/data/trusted_certs/example.crt +29 -20
  60. data/spec/data/trusted_certs/example_no_cn.crt +30 -34
  61. data/spec/functional/resource/chocolatey_package_spec.rb +32 -20
  62. data/spec/functional/resource/execute_spec.rb +1 -1
  63. data/spec/functional/resource/windows_certificate_spec.rb +25 -0
  64. data/spec/functional/resource/zypper_package_spec.rb +10 -0
  65. data/spec/unit/client_spec.rb +2 -2
  66. data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +1 -1
  67. data/spec/unit/delayed_evaluator_spec.rb +35 -0
  68. data/spec/unit/mixin/homebrew_user_spec.rb +30 -7
  69. data/spec/unit/node/vivid_mash_spec.rb +42 -0
  70. data/spec/unit/node_spec.rb +6 -0
  71. data/spec/unit/provider/apt_repository_spec.rb +17 -7
  72. data/spec/unit/provider/launchd_spec.rb +2 -2
  73. data/spec/unit/provider/mount/aix_spec.rb +2 -2
  74. data/spec/unit/provider/mount/linux_spec.rb +6 -5
  75. data/spec/unit/provider/mount/mount_spec.rb +8 -8
  76. data/spec/unit/provider/package/apt_spec.rb +18 -13
  77. data/spec/unit/provider/package/chocolatey_spec.rb +53 -9
  78. data/spec/unit/provider/package/rpm_spec.rb +2 -2
  79. data/spec/unit/provider/package/zypper_spec.rb +10 -0
  80. data/spec/unit/provider/powershell_script_spec.rb +100 -4
  81. data/spec/unit/provider/remote_file/http_spec.rb +4 -4
  82. data/spec/unit/provider/service/systemd_service_spec.rb +1 -0
  83. data/spec/unit/provider/user/linux_spec.rb +10 -0
  84. data/spec/unit/resource/apt_repository_spec.rb +5 -0
  85. data/spec/unit/resource/chef_client_systemd_timer_spec.rb +1 -1
  86. data/spec/unit/resource/chocolatey_installer_spec.rb +151 -0
  87. data/spec/unit/resource/macos_pkg_spec.rb +38 -0
  88. data/spec/unit/resource/powershell_script_spec.rb +2 -2
  89. data/spec/unit/resource_spec.rb +86 -0
  90. metadata +29 -16
  91. /data/spec/functional/assets/chocolatey_feed/{test-A.1.0.nupkg → test-A.1.0.0.nupkg} +0 -0
  92. /data/spec/functional/assets/chocolatey_feed/{test-A.1.5.nupkg → test-A.1.5.0.nupkg} +0 -0
  93. /data/spec/functional/assets/chocolatey_feed/{test-A.2.0.nupkg → test-A.2.0.0.nupkg} +0 -0
  94. /data/spec/functional/assets/chocolatey_feed/{test-B.1.0.nupkg → test-B.1.0.0.nupkg} +0 -0
@@ -41,7 +41,7 @@ describe Chef::Provider::Package::Rpm do
41
41
  let(:rpm_q_status) { instance_double("Mixlib::ShellOut", exitstatus: rpm_q_exitstatus, stdout: rpm_q_stdout) }
42
42
 
43
43
  before(:each) do
44
- allow(::File).to receive(:exist?).with("PLEASE STUB File.exists? EXACTLY").and_return(true)
44
+ allow(::File).to receive(:exist?).with("PLEASE STUB File.exist? EXACTLY").and_return(true)
45
45
 
46
46
  # Ensure all shell out usage is stubbed with exact arguments
47
47
  allow(provider).to receive(:shell_out_compacted!).with("PLEASE STUB YOUR SHELLOUT CALLS").and_return(nil)
@@ -412,7 +412,7 @@ describe Chef::Provider::Package::Rpm do
412
412
 
413
413
  let(:new_resource) do
414
414
  # When we pass a source in as the name, then #initialize in the
415
- # provider will call File.exists?. Because of the ordering in our
415
+ # provider will call File.exist?. Because of the ordering in our
416
416
  # let() bindings and such, we have to set the stub here and not in a
417
417
  # before block.
418
418
  allow(::File).to receive(:exist?).with(package_source).and_return(true)
@@ -491,4 +491,14 @@ describe Chef::Provider::Package::Zypper do
491
491
  provider.remove_package(%w{emacs vim}, ["1.0", "2.0"])
492
492
  end
493
493
  end
494
+
495
+ describe "resolve_available_version" do
496
+ it "should return correct version if multiple packages are shown" do
497
+ status = double(stdout: "S | Name | Type | Version | Arch | Repository\n---+--------------------------+---------+---------------------+--------+-------------------------------------------------------------\n | apache2-mod_wsgi | package | 4.7.1-150400.3.3.1 | x86_64 | Update repository with updates from SUSE Linux Enterprise 15\n | apache2-mod_wsgi | package | 4.7.1-150400.1.52 | x86_64 | Main Repository\ni+ | apache2-mod_wsgi-python3 | package | 4.5.18-150000.4.6.1 | x86_64 | Update repository with updates from SUSE Linux Enterprise 15\nv | apache2-mod_wsgi-python3 | package | 4.5.18-4.3.1 | x86_64 | Main Repository\n", exitstatus: 0)
498
+
499
+ allow(provider).to receive(:shell_out_compacted!).and_return(status)
500
+ result = provider.send(:resolve_available_version, "apache2-mod_wsgi-python3", nil)
501
+ expect(result).to eq("4.5.18-150000.4.6.1")
502
+ end
503
+ end
494
504
  end
@@ -17,10 +17,14 @@
17
17
  #
18
18
 
19
19
  require "spec_helper"
20
- describe Chef::Provider::PowershellScript, "action_run" do
20
+ describe Chef::Provider::PowershellScript, "action_run", windows_only: true do
21
21
  let(:events) { Chef::EventDispatch::Dispatcher.new }
22
22
 
23
- let(:run_context) { Chef::RunContext.new(Chef::Node.new, {}, events) }
23
+ let(:run_context) {
24
+ @node = Chef::Node.new
25
+ @node.consume_external_attrs(OHAI_SYSTEM.data.dup, {})
26
+ Chef::RunContext.new(@node, {}, events)
27
+ }
24
28
 
25
29
  let(:new_resource) do
26
30
  Chef::Resource::PowershellScript.new("run some powershell code", run_context)
@@ -44,7 +48,7 @@ describe Chef::Provider::PowershellScript, "action_run" do
44
48
  "C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe" -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass -InputFormat None -InputFormat Fabulous -File "C:\\Temp\\Script.ps1"
45
49
  CMD
46
50
 
47
- expect(provider.command).to eq(expected)
51
+ expect(provider.send(:command)).to eq(expected)
48
52
  end
49
53
 
50
54
  it "uses pwsh when given the pwsh interpreter" do
@@ -55,7 +59,99 @@ describe Chef::Provider::PowershellScript, "action_run" do
55
59
  "pwsh" -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass -InputFormat None -File "C:\\Temp\\Script.ps1"
56
60
  CMD
57
61
 
58
- expect(provider.command).to eq(expected)
62
+ expect(provider.send(:command)).to eq(expected)
63
+ end
64
+
65
+ it "returns the script specific to the inline interpreter when using use_inline_interpreter" do
66
+ new_resource.code = "test script"
67
+ new_resource.use_inline_powershell = true
68
+ # This is a string that is ONLY in the use_inline_interpreter version of this
69
+ expect(provider.send(:powershell_wrapper_script)).to include("$interpolatedexitcode = $")
70
+ end
71
+
72
+ it "returns the script specific to the normal interpreter when not using use_inline_interpreter" do
73
+ new_resource.code = "test script"
74
+ new_resource.use_inline_powershell = false
75
+ # This is a string that is ONLY in the non use_inline_interpreter version of this
76
+ expect(provider.send(:powershell_wrapper_script)).to include("new-variable -name interpolatedexitcode -visibility private")
77
+ end
78
+
79
+ it "Correctly returns for $True for regular powershell" do
80
+ new_resource.code = "$True"
81
+ new_resource.use_inline_powershell = false
82
+ new_resource.convert_boolean_return = true
83
+ expect(provider.run_action(:run)).to eq(nil)
84
+ end
85
+
86
+ it "Correctly returns for $True for inline powershell with convert_boolean_return" do
87
+ new_resource.code = "$True"
88
+ new_resource.use_inline_powershell = true
89
+ new_resource.convert_boolean_return = true
90
+ expect(provider.run_action(:run)).to eq(nil)
91
+ end
92
+
93
+ it "Correctly throws exception for $False for regular powershell" do
94
+ new_resource.code = "$False"
95
+ new_resource.use_inline_powershell = false
96
+ new_resource.convert_boolean_return = true
97
+ expect { provider.run_action(:run) }.to raise_error(an_instance_of(Mixlib::ShellOut::ShellCommandFailed))
98
+ end
99
+
100
+ it "Correctly throws exception for $False for inline powershell" do
101
+ new_resource.code = "$False"
102
+ new_resource.use_inline_powershell = true
103
+ new_resource.convert_boolean_return = true
104
+ expect { provider.run_action(:run) }.to raise_error(an_instance_of(ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed))
105
+ end
106
+
107
+ it "return 1 fails correctly for non-inline" do
108
+ new_resource.code = "return 1"
109
+ new_resource.use_inline_powershell = false
110
+ expect { provider.run_action(:run) }.to raise_error(an_instance_of(Mixlib::ShellOut::ShellCommandFailed))
111
+ end
112
+
113
+ it "return 1 fails correctly for inline" do
114
+ new_resource.code = "return 1"
115
+ new_resource.use_inline_powershell = true
116
+ expect { provider.run_action(:run) }.to raise_error(an_instance_of(ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed))
117
+ end
118
+
119
+ it "return 1 is valid when returns includes 1 for non-inline" do
120
+ new_resource.code = "return 1"
121
+ new_resource.use_inline_powershell = false
122
+ new_resource.returns = [1]
123
+ expect(provider.run_action(:run)).to eq(nil)
124
+ end
125
+ it "return 1 is valid when returns includes 1 for inline" do
126
+ new_resource.code = "return 1"
127
+ new_resource.use_inline_powershell = true
128
+ new_resource.returns = [1]
129
+ expect(provider.run_action(:run)).to eq(nil)
130
+ end
131
+
132
+ it "bad powershell exceptions for non-inline" do
133
+ new_resource.code = "xyzzy"
134
+ new_resource.use_inline_powershell = false
135
+ expect { provider.run_action(:run) }.to raise_error(an_instance_of(Mixlib::ShellOut::ShellCommandFailed))
136
+ end
137
+
138
+ it "bad powershell exceptions for inline" do
139
+ new_resource.code = "xyzzy"
140
+ new_resource.use_inline_powershell = true
141
+ expect { provider.run_action(:run) }.to raise_error(an_instance_of(ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed))
142
+ end
143
+
144
+ it "uses powershell for inline by default" do
145
+ new_resource.code = "$host.version.major -lt 7"
146
+ new_resource.use_inline_powershell = true
147
+ expect(provider.run_action(:run)).to eq(nil)
148
+ end
149
+
150
+ it "uses pwsh for inline when asked" do
151
+ new_resource.code = "$host.version.major -ge 7"
152
+ new_resource.use_inline_powershell = true
153
+ new_resource.interpreter = "pwsh"
154
+ expect(provider.run_action(:run)).to eq(nil)
59
155
  end
60
156
  end
61
157
  end
@@ -251,7 +251,7 @@ describe Chef::Provider::RemoteFile::HTTP do
251
251
  end
252
252
 
253
253
  context "and the response has no Date or Last-Modified header" do
254
- let(:last_response) { { "date" => nil, "last_modified" => nil } }
254
+ let(:last_response) { { "date" => nil, "last-modified" => nil } }
255
255
  it "does not set an mtime in the result" do
256
256
  # RFC 2616 suggests that servers that do not set a Date header do not
257
257
  # have a reliable clock, so no use in making them deal with dates.
@@ -265,19 +265,19 @@ describe Chef::Provider::RemoteFile::HTTP do
265
265
  context "and the response has a Last-Modified header" do
266
266
  let(:last_response) do
267
267
  # Last-Modified should be preferred to Date if both are set
268
- { "date" => "Fri, 17 May 2013 23:23:23 GMT", "last_modified" => "Fri, 17 May 2013 11:11:11 GMT" }
268
+ { "date" => "Fri, 17 May 2013 23:23:23 GMT", "last-modified" => "Fri, 17 May 2013 11:11:11 GMT" }
269
269
  end
270
270
 
271
271
  it "sets the mtime to the Last-Modified time in the response" do
272
272
  fetcher.fetch
273
273
  expect(cache_control_data.etag).to be_nil
274
- expect(cache_control_data.mtime).to eq(last_response["last_modified"])
274
+ expect(cache_control_data.mtime).to eq(last_response["last-modified"])
275
275
  end
276
276
  end
277
277
 
278
278
  context "and the response has a Date header but no Last-Modified header" do
279
279
  let(:last_response) do
280
- { "date" => "Fri, 17 May 2013 23:23:23 GMT", "last_modified" => nil }
280
+ { "date" => "Fri, 17 May 2013 23:23:23 GMT", "last-modified" => nil }
281
281
  end
282
282
 
283
283
  it "sets the mtime to the Date in the response" do
@@ -56,6 +56,7 @@ describe Chef::Provider::Service::Systemd do
56
56
  allow(provider).to receive(:is_active?).and_return(false)
57
57
  allow(provider).to receive(:is_enabled?).and_return(false)
58
58
  allow(provider).to receive(:is_masked?).and_return(false)
59
+ allow(provider).to receive(:is_static?).and_return(false)
59
60
  allow(provider).to receive(:is_indirect?).and_return(false)
60
61
  end
61
62
 
@@ -136,6 +136,7 @@ describe Chef::Provider::User::Linux, linux_only: true do
136
136
  "home" => ["/home/notarealuser", "/Users/notarealuser"],
137
137
  "shell" => ["/usr/bin/zsh", "/bin/bash"],
138
138
  "password" => %w{abcd 12345},
139
+ "sensitive" => [true],
139
140
  }
140
141
  end
141
142
 
@@ -147,6 +148,15 @@ describe Chef::Provider::User::Linux, linux_only: true do
147
148
  end
148
149
  end
149
150
 
151
+ it "should show a blank for password if sensitive set to true" do
152
+ @new_resource.password mapping["password"][0]
153
+ @current_resource.password mapping["password"][1]
154
+ @new_resource.sensitive true
155
+ @current_resource.sensitive true
156
+ provider.compare_user
157
+ expect(provider.change_desc).to eql(["change password from ******** to ********"])
158
+ end
159
+
150
160
  %w{uid gid}.each do |property|
151
161
  it "should return false if string #{property} matches fixnum" do
152
162
  @new_resource.send(property, "100")
@@ -68,6 +68,11 @@ describe Chef::Resource::AptRepository do
68
68
  expect(resource.key).to eql(["key1"])
69
69
  end
70
70
 
71
+ it "allows setting options to a String and coerces it to an Array" do
72
+ resource.options = "by-hash=no"
73
+ expect(resource.options).to eql(["by-hash=no"])
74
+ end
75
+
71
76
  it "fails if the user provides a repo_name with a forward slash" do
72
77
  expect { resource.repo_name "foo/bar" }.to raise_error(ArgumentError)
73
78
  end
@@ -102,7 +102,7 @@ describe Chef::Resource::ChefClientSystemdTimer do
102
102
 
103
103
  it "sets CPUQuota if cpu_quota property is set" do
104
104
  resource.cpu_quota 50
105
- expect(provider.service_content["Service"]["CPUQuota"]).to eq(50)
105
+ expect(provider.service_content["Service"]["CPUQuota"]).to eq("50%")
106
106
  end
107
107
  end
108
108
  end
@@ -0,0 +1,151 @@
1
+ #
2
+ # Copyright:: Copyright (c) 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
+
20
+ describe Chef::Resource::ChocolateyInstaller do
21
+ include RecipeDSLHelper
22
+
23
+ let(:resource) { Chef::Resource::ChocolateyInstaller.new("fakey_fakerton") }
24
+ let(:config) do
25
+ <<-CONFIG
26
+ <?xml version="1.0" encoding="utf-8"?>
27
+ <chocolatey xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
28
+ <config>
29
+ <add key="containsLegacyPackageInstalls" value="true" description="Install has packages installed prior to 0.9.9 series." />
30
+ </config>
31
+ <sources>
32
+ <source id="chocolatey" value="https://chocolatey.org/api/v2/" disabled="false" bypassProxy="false" selfService="false" adminOnly="false" priority="0" />
33
+ </sources>
34
+ <features>
35
+ <feature name="checksumFiles" enabled="true" setExplicitly="false" description="Checksum files when pulled in from internet (based on package)." />
36
+ </features>
37
+ <apiKeys />
38
+ </chocolatey>
39
+ CONFIG
40
+ end
41
+
42
+ # we save off the ENV and set ALLUSERSPROFILE so these specs will work on *nix and non-C drive Windows installs
43
+ before(:each) do
44
+ @original_env = ENV.to_hash
45
+ ENV["ALLUSERSPROFILE"] = "C:\\ProgramData"
46
+ end
47
+
48
+ after(:each) do
49
+ ENV.clear
50
+ ENV.update(@original_env)
51
+ end
52
+
53
+ describe "Basic Resource Settings" do
54
+ context "on windows", :windows_only do
55
+ it "supports :install, :uninstall, :upgrade actions" do
56
+ expect { resource.action :install }.not_to raise_error
57
+ expect { resource.action :uninstall }.not_to raise_error
58
+ expect { resource.action :upgrade }.not_to raise_error
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "Basic chocolatey settings" do
64
+ context "on windows", :windows_only do
65
+ it "has a resource name of :chocolatey_installer" do
66
+ expect(resource.resource_name).to eql(:chocolatey_installer)
67
+ end
68
+
69
+ it "sets the default action as :install" do
70
+ expect(resource.action).to eql([:install])
71
+ end
72
+
73
+ it "supports :install and :uninstall actions" do
74
+ expect { resource.action :install }.not_to raise_error
75
+ expect { resource.action :uninstall }.not_to raise_error
76
+ end
77
+
78
+ it "does not support bologna install options" do
79
+ expect { resource.action :foo }.to raise_error(Chef::Exceptions::ValidationFailed)
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "Installing chocolatey" do
85
+ context "on windows", :windows_only do
86
+ it "can install Chocolatey with parameters" do
87
+ resource.chocolatey_version = "1.4.0"
88
+ expect { resource.action :install }.not_to raise_error
89
+ end
90
+
91
+ it "logs a warning if a chocolatey install cannot be found" do
92
+ allow(::File).to receive(:exist?).with('C:\ProgramData\chocolatey\bin\choco.exe').and_return(false)
93
+ expect { Chef::Log.warn("Chocolatey is already uninstalled.") }.not_to output.to_stderr
94
+ end
95
+ end
96
+ end
97
+
98
+ describe "Chocolatey is idempotent because" do
99
+ context "on windows", :windows_only do
100
+ it "it does not install choco again if it is already installed" do
101
+ install_choco
102
+ chocolatey_installer "install" do
103
+ action :install
104
+ end.should_not_be_updated
105
+ end
106
+ end
107
+ end
108
+
109
+ describe "upgrading choco versions" do
110
+
111
+ context "on windows", :windows_only do
112
+ describe "when the versions do not match" do
113
+ it "upgrades if the proposed version is newer" do
114
+ allow(resource).to receive(:get_choco_version).and_return(Gem::Version.new("1.2.2"))
115
+ allow(resource).to receive(:chocolatey_version).and_return(Gem::Version.new("4.2.2"))
116
+ expect { resource.action :upgrade }.not_to raise_error
117
+ allow(resource).to receive(:get_choco_version).and_return(Gem::Version.new("4.2.2"))
118
+ expect(resource.get_choco_version).to eql(Gem::Version.new("4.2.2"))
119
+ end
120
+ end
121
+ describe "when the versions match" do
122
+ it "does not upgrade if the old version is identical" do
123
+ allow(resource).to receive(:get_choco_version).and_return(Gem::Version.new("2.2.2"))
124
+ allow(resource).to receive(:chocolatey_version).and_return(Gem::Version.new("2.2.2"))
125
+ expect { resource.action :upgrade }.not_to raise_error
126
+ expect(resource).not_to be_updated
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "Uninstalling chocolatey" do
133
+ context "on windows", :windows_only do
134
+ it "doesn't error out uninstalling chocolatey if chocolatey is not installed" do
135
+ allow(::File).to receive(:exist?).with('C:\ProgramData\chocolatey\bin\choco.exe').and_return(false)
136
+ expect { resource.action :uninstall }.not_to raise_error
137
+ end
138
+ end
139
+ end
140
+
141
+ def install_choco
142
+ require "chef-powershell"
143
+ include ChefPowerShell::ChefPowerShellModule::PowerShellExec
144
+ powershell_code = <<-CODE
145
+ Set-ExecutionPolicy Bypass -Scope Process -Force;
146
+ [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
147
+ iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
148
+ CODE
149
+ powershell_exec(powershell_code)
150
+ end
151
+ end
@@ -0,0 +1,38 @@
1
+ #
2
+ # Copyright:: Copyright (c) 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
+
20
+ describe Chef::Resource::MacosPkg do
21
+ let(:resource) { Chef::Resource::MacosPkg.new("fakey_fakerton") }
22
+
23
+ it "has a resource name of :macos_pkg" do
24
+ expect(resource.resource_name).to eql(:macos_pkg)
25
+ end
26
+
27
+ it "sets the default action as :install" do
28
+ expect(resource.action).to eql([:install])
29
+ end
30
+
31
+ it "supports :install action" do
32
+ expect { resource.action :install }.not_to raise_error
33
+ end
34
+
35
+ it "target property defaults to /" do
36
+ expect(resource.target).to eql("/")
37
+ end
38
+ end
@@ -47,9 +47,9 @@ describe Chef::Resource::PowershellScript do
47
47
  expect(resource.convert_boolean_return).to eq(false)
48
48
  end
49
49
 
50
- it "inherits exactly the :cwd, :domain, :environment, :group, :password, :path, :user, :umask, :architecture, :elevated, :interpreter, :login properties from a parent resource class" do
50
+ it "inherits exactly the :cwd, :domain, :environment, :group, :password, :path, :user, :umask, :architecture, :elevated, :interpreter, :login, :use_inline_powershell properties from a parent resource class" do
51
51
  inherited_difference = Chef::Resource::PowershellScript.guard_inherited_attributes -
52
- %i{cwd domain environment group password path user umask architecture elevated interpreter login}
52
+ %i{cwd domain environment group password path user umask architecture elevated interpreter login use_inline_powershell}
53
53
 
54
54
  expect(inherited_difference).to eq([])
55
55
  end
@@ -803,6 +803,92 @@ describe Chef::Resource do
803
803
  end
804
804
  end
805
805
 
806
+ describe "when using resource partials" do
807
+ let(:resource_using_core_partial) do
808
+ Class.new(Chef::Resource) do
809
+ use "core::core_partial"
810
+ end
811
+ end
812
+
813
+ let(:resource_using_cookbook_partial) do
814
+ Class.new(Chef::Resource) do
815
+ use "my_local_partial"
816
+ end
817
+ end
818
+
819
+ let(:resource_using_nested_partials) do
820
+ FakeCaller = Struct.new(:label, :path, keyword_init: true)
821
+ NonDynamicResource = Chef::Resource.dup
822
+
823
+ # Fake a caller_locations array, as RSpec uses a different execution path
824
+ NonDynamicResource.define_singleton_method(:caller_locations) do
825
+ [
826
+ FakeCaller.new(label: "use", path: File.join(__dir__, "resource.rb")),
827
+ FakeCaller.new(label: "noise", path: File.join(__dir__, "no_file")),
828
+ FakeCaller.new(label: "class_from_file", path: File.join(__dir__, "_level3_partial.rb")),
829
+ FakeCaller.new(label: "noise", path: File.join(__dir__, "no_file")),
830
+ FakeCaller.new(label: "class_from_file", path: File.join(__dir__, "_level2_partial.rb")),
831
+ FakeCaller.new(label: "noise", path: File.join(__dir__, "no_file")),
832
+ FakeCaller.new(label: "class_from_file", path: File.join(__dir__, "_level1_partial.rb")),
833
+ FakeCaller.new(label: "noise", path: File.join(__dir__, "no_file")),
834
+ FakeCaller.new(label: "class_from_file", path: File.join(__dir__, "_level0_partial.rb")),
835
+ ]
836
+ end
837
+
838
+ Class.new(NonDynamicResource) do
839
+ use "level3_partial"
840
+ end
841
+ end
842
+
843
+ it "correcly includes a core partial" do
844
+ expected_path = File.expand_path(File.join(__dir__, "../..", "lib/chef", "resource/_core_partial.rb"))
845
+ partial = "property :addon_property, default: true"
846
+
847
+ expect(IO).to receive(:read).with(expected_path).and_return(partial)
848
+ expect(resource_using_core_partial.properties.keys).to include(:addon_property)
849
+ end
850
+
851
+ it "correctly includes a cookbook partial" do
852
+ expected_path = File.expand_path(File.join(__dir__, "_my_local_partial.rb"))
853
+ partial = "property :addon_property, default: true"
854
+
855
+ expect(IO).to receive(:read).with(expected_path).and_return(partial)
856
+ expect(resource_using_cookbook_partial.properties.keys).to include(:addon_property)
857
+ end
858
+
859
+ it "correctly includes nested partials" do
860
+ level0_path = File.expand_path(File.join(__dir__, "_level0_partial.rb"))
861
+ level0_partial = "property :level0_property, default: true"
862
+ expect(IO).to receive(:read).with(level0_path).and_return(level0_partial)
863
+
864
+ level1_path = File.expand_path(File.join(__dir__, "_level1_partial.rb"))
865
+ level1_partial = <<-EOF
866
+ use 'level0_partial'
867
+ property :level1_property, default: true
868
+ EOF
869
+ expect(IO).to receive(:read).with(level1_path).and_return(level1_partial)
870
+
871
+ level2_path = File.expand_path(File.join(__dir__, "_level2_partial.rb"))
872
+ level2_partial = <<-EOF
873
+ use 'level1_partial'
874
+ property :level2_property, default: true
875
+ EOF
876
+ expect(IO).to receive(:read).with(level2_path).and_return(level2_partial)
877
+
878
+ level3_path = File.expand_path(File.join(__dir__, "_level3_partial.rb"))
879
+ level3_partial = <<-EOF
880
+ use 'level2_partial'
881
+ property :level3_property, default: true
882
+ EOF
883
+ expect(IO).to receive(:read).with(level3_path).and_return(level3_partial)
884
+
885
+ expect(resource_using_nested_partials.properties.keys).to include(:level0_property)
886
+ expect(resource_using_nested_partials.properties.keys).to include(:level1_property)
887
+ expect(resource_using_nested_partials.properties.keys).to include(:level2_property)
888
+ expect(resource_using_nested_partials.properties.keys).to include(:level3_property)
889
+ end
890
+ end
891
+
806
892
  describe "should_skip?" do
807
893
  before do
808
894
  resource = Chef::Resource::Cat.new("sugar", run_context)