chef 16.14.1 → 16.17.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/action_collection.rb +1 -1
  3. data/lib/chef/application.rb +1 -1
  4. data/lib/chef/cookbook_version.rb +26 -4
  5. data/lib/chef/data_collector/run_end_message.rb +2 -2
  6. data/lib/chef/deprecated.rb +14 -4
  7. data/lib/chef/exceptions.rb +3 -0
  8. data/lib/chef/formatters/error_mapper.rb +2 -2
  9. data/lib/chef/http.rb +5 -5
  10. data/lib/chef/knife/bootstrap.rb +1 -1
  11. data/lib/chef/node.rb +20 -19
  12. data/lib/chef/policy_builder/policyfile.rb +5 -0
  13. data/lib/chef/provider/group/dscl.rb +1 -1
  14. data/lib/chef/provider/package/powershell.rb +5 -0
  15. data/lib/chef/provider/template/content.rb +1 -1
  16. data/lib/chef/resource/chef_client_trusted_certificate.rb +1 -0
  17. data/lib/chef/resource/homebrew_cask.rb +13 -7
  18. data/lib/chef/resource/mount.rb +1 -1
  19. data/lib/chef/resource/rhsm_subscription.rb +5 -5
  20. data/lib/chef/resource/support/client.erb +6 -0
  21. data/lib/chef/resource/systemd_unit.rb +1 -1
  22. data/lib/chef/resource/user_ulimit.rb +1 -0
  23. data/lib/chef/resource/windows_security_policy.rb +55 -39
  24. data/lib/chef/resource/windows_uac.rb +3 -1
  25. data/lib/chef/resource/windows_user_privilege.rb +1 -1
  26. data/lib/chef/resource.rb +1 -1
  27. data/lib/chef/resource_reporter.rb +1 -1
  28. data/lib/chef/shell/ext.rb +3 -3
  29. data/lib/chef/version.rb +1 -1
  30. data/lib/chef/win32/api.rb +9 -2
  31. data/lib/chef/win32/version.rb +2 -1
  32. data/spec/functional/resource/group_spec.rb +5 -1
  33. data/spec/functional/resource/link_spec.rb +8 -0
  34. data/spec/integration/knife/delete_spec.rb +1 -1
  35. data/spec/integration/knife/download_spec.rb +2 -2
  36. data/spec/integration/knife/upload_spec.rb +5 -6
  37. data/spec/unit/cookbook_version_spec.rb +52 -0
  38. data/spec/unit/data_collector_spec.rb +71 -2
  39. data/spec/unit/policy_builder/policyfile_spec.rb +11 -1
  40. data/spec/unit/provider/package/powershell_spec.rb +74 -12
  41. data/spec/unit/resource/chef_client_trusted_certificate_spec.rb +14 -0
  42. data/spec/unit/resource/homebrew_cask_spec.rb +29 -11
  43. data/spec/unit/resource/mount_spec.rb +10 -0
  44. data/spec/unit/resource/rhsm_subscription_spec.rb +50 -3
  45. data/spec/unit/resource/systemd_unit_spec.rb +1 -1
  46. data/spec/unit/resource/user_ulimit_spec.rb +14 -1
  47. data/spec/unit/resource_spec.rb +5 -0
  48. metadata +6 -6
@@ -43,6 +43,8 @@ class Chef
43
43
 
44
44
  host.ffi_convention :stdcall
45
45
 
46
+ win64 = ENV["PROCESSOR_ARCHITECTURE"] == "AMD64" || ENV["PROCESSOR_ARCHITEW6432"] == "AMD64"
47
+
46
48
  # Windows-specific type defs (ms-help://MS.MSDNQTR.v90.en/winprog/winprog/windows_data_types.htm):
47
49
  host.typedef :ushort, :ATOM # Atom ~= Symbol: Atom table stores strings and corresponding identifiers. Application
48
50
  # places a string in an atom table and receives a 16-bit integer, called an atom, that
@@ -120,10 +122,15 @@ class Chef
120
122
  host.typedef :int32, :LONG32 # 32-bit signed integer. The range is -2,147,483,648 through +...647 decimal.
121
123
  host.typedef :int64, :LONG64 # 64-bit signed integer. The range is –9,223,372,036,854,775,808 through +...807
122
124
  host.typedef :int64, :LONGLONG # 64-bit signed integer. The range is –9,223,372,036,854,775,808 through +...807
123
- host.typedef :long, :LONG_PTR # Signed long type for pointer precision. Use when casting a pointer to a long to
124
125
  # perform pointer arithmetic. BaseTsd.h:
125
126
  # if defined(_WIN64) host.typedef __int64 LONG_PTR; #else host.typedef long LONG_PTR;
126
- host.typedef :long, :LPARAM # Message parameter. WinDef.h as follows: #host.typedef LONG_PTR LPARAM;
127
+ if win64
128
+ host.typedef :int64, :LONG_PTR # Signed long type for pointer precision. Use when casting a pointer to a long to
129
+ host.typedef :int64, :LPARAM # Message parameter. WinDef.h as follows: #host.typedef LONG_PTR LPARAM;
130
+ else
131
+ host.typedef :long, :LONG_PTR # Signed long type for pointer precision. Use when casting a pointer to a long to
132
+ host.typedef :long, :LPARAM # Message parameter. WinDef.h as follows: #host.typedef LONG_PTR LPARAM;
133
+ end
127
134
  host.typedef :pointer, :LPBOOL # Pointer to a BOOL. WinDef.h as follows: #host.typedef BOOL far *LPBOOL;
128
135
  host.typedef :pointer, :LPBYTE # Pointer to a BYTE. WinDef.h as follows: #host.typedef BYTE far *LPBYTE;
129
136
  host.typedef :pointer, :LPCOLORREF # Pointer to a COLORREF value. WinDef.h as follows: #host.typedef DWORD *LPCOLORREF;
@@ -49,7 +49,8 @@ class Chef
49
49
  private_class_method :method_name_from_marketing_name
50
50
 
51
51
  WIN_VERSIONS = {
52
- "Windows Server 2019" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 17763 } },
52
+ "Windows Server 2022" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 20348 } },
53
+ "Windows Server 2019" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 17763 && build_number < 20348 } },
53
54
  "Windows 10" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type == VER_NT_WORKSTATION } },
54
55
  "Windows Server 2016" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number <= 14393 } },
55
56
  "Windows 8.1" => { major: 6, minor: 3, callable: lambda { |product_type, suite_mask, build_number| product_type == VER_NT_WORKSTATION } },
@@ -44,6 +44,10 @@ describe Chef::Resource::Group, :requires_root_or_running_windows do
44
44
  members.shift # Get rid of GroupMembership: string
45
45
  members.include?(user)
46
46
  else
47
+ # TODO For some reason our temporary AIX 7.2 system does not correctly report group membership immediately after changes have been made.
48
+ # Adding a 2 second delay for this platform is enough to get correct results.
49
+ # We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
50
+ sleep 2 if aix? && (ohai[:platform_version] == "7.2")
47
51
  Etc.getgrnam(group_name).mem.include?(user)
48
52
  end
49
53
  end
@@ -181,7 +185,7 @@ describe Chef::Resource::Group, :requires_root_or_running_windows do
181
185
 
182
186
  describe "when the users exist" do
183
187
  before do
184
- high_uid = 30000
188
+ high_uid = 40000
185
189
  (spec_members).each do |member|
186
190
  remove_user(member)
187
191
  create_user(member, high_uid)
@@ -345,9 +345,17 @@ describe Chef::Resource::Link do
345
345
  let(:test_user) { "test-link-user" }
346
346
  before do
347
347
  user(test_user).run_action(:create)
348
+ # TODO For some reason our temporary AIX 7.2 system does not correctly report user existence immediately after changes have been made.
349
+ # Adding a 2 second delay for this platform is enough to get correct results.
350
+ # We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
351
+ sleep 2 if aix? && (ohai[:platform_version] == "7.2")
348
352
  end
349
353
  after do
350
354
  user(test_user).run_action(:remove)
355
+ # TODO For some reason our temporary AIX 7.2 system does not correctly report user existence immediately after changes have been made.
356
+ # Adding a 2 second delay for this platform is enough to get correct results.
357
+ # We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
358
+ sleep 2 if aix? && (ohai[:platform_version] == "7.2")
351
359
  end
352
360
  before(:each) do
353
361
  resource.owner(test_user)
@@ -992,7 +992,7 @@ describe "knife delete", :workstation do
992
992
  end
993
993
 
994
994
  it "knife delete /policies/x-1.2.3.json succeeds" do
995
- knife("raw /policies/x/revisions/1.2.3").should_succeed "{\n \"name\": \"x\",\n \"revision_id\": \"1.2.3\",\n \"run_list\": [\n\n ],\n \"cookbook_locks\": {\n\n }\n}\n"
995
+ knife("raw /policies/x/revisions/1.2.3").should_succeed "{\n \"policy_group_list\": [\n \"x\"\n ],\n \"name\": \"x\",\n \"revision_id\": \"1.2.3\",\n \"run_list\": [\n\n ],\n \"cookbook_locks\": {\n\n }\n}\n"
996
996
  knife("delete /policies/x-1.2.3.json").should_succeed "Deleted /policies/x-1.2.3.json\n"
997
997
  knife("raw /policies/x/revisions/1.2.3").should_fail(/404/)
998
998
  end
@@ -1276,8 +1276,8 @@ describe "knife download", :workstation do
1276
1276
  file "members.json", [ "bar" ]
1277
1277
  file "nodes/x.json", { "normal" => { "tags" => [] } }
1278
1278
  file "org.json", { "full_name" => "Something" }
1279
- file "policies/x-1.0.0.json", {}
1280
- file "policies/blah-1.0.0.json", {}
1279
+ file "policies/x-1.0.0.json", { "policy_group_list" => [ "x" ] }
1280
+ file "policies/blah-1.0.0.json", { "policy_group_list" => [ "x" ] }
1281
1281
  file "policy_groups/x.json", { "policies" => { "x" => { "revision_id" => "1.0.0" }, "blah" => { "revision_id" => "1.0.0" } } }
1282
1282
  file "roles/x.json", {}
1283
1283
  end
@@ -1383,8 +1383,8 @@ describe "knife upload", :workstation do
1383
1383
  file "members.json", [ "bar" ]
1384
1384
  file "org.json", { "full_name" => "wootles" }
1385
1385
  file "nodes/x.json", { "normal" => { "tags" => [] } }
1386
- file "policies/x-1.0.0.json", {}
1387
- file "policies/blah-1.0.0.json", {}
1386
+ file "policies/x-1.0.0.json", { "policy_group_list" => [ "x" ] }
1387
+ file "policies/blah-1.0.0.json", { "policy_group_list" => [ "x" ] }
1388
1388
  file "policy_groups/x.json", { "policies" => { "x" => { "revision_id" => "1.0.0" }, "blah" => { "revision_id" => "1.0.0" } } }
1389
1389
  file "roles/x.json", {}
1390
1390
  end
@@ -1484,12 +1484,11 @@ describe "knife upload", :workstation do
1484
1484
  environment "x", { "description" => "foo" }
1485
1485
  group "x", { "groups" => [ "admin" ] }
1486
1486
  node "x", { "run_list" => [ "blah" ] }
1487
- policy "x", "1.0.0", {}
1488
- policy "x", "1.0.1", {}
1489
- policy "y", "1.0.0", {}
1487
+ policy "x", "1.0.0", { "policy_group_list" => [ "x" ] }
1488
+ policy "y", "1.0.0", { "policy_group_list" => [ "x" ] }
1490
1489
  policy_group "x", {
1491
1490
  "policies" => {
1492
- "x" => { "revision_id" => "1.0.1" },
1491
+ "x" => { "revision_id" => "1.0.0" },
1493
1492
  "y" => { "revision_id" => "1.0.0" },
1494
1493
  },
1495
1494
  }
@@ -41,7 +41,59 @@ describe Chef::CookbookVersion do
41
41
  it "has empty metadata" do
42
42
  expect(cookbook_version.metadata).to eq(Chef::Cookbook::Metadata.new)
43
43
  end
44
+ end
45
+
46
+ describe "#recipe_yml_filenames_by_name" do
47
+ let(:cookbook_version) { Chef::CookbookVersion.new("mycb", "/tmp/mycb") }
48
+
49
+ def files_for_recipe(extension)
50
+ [
51
+ { name: "recipes/default.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipes/default.#{extension}" },
52
+ { name: "recipes/other.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipes/other.#{extension}" },
53
+ ]
54
+ end
55
+ context "and YAML files present include both a recipes/default.yml and a recipes/default.yaml" do
56
+ before(:each) do
57
+ allow(cookbook_version).to receive(:files_for).with("recipes").and_return(
58
+ [
59
+ { name: "recipes/default.yml", full_path: "/home/user/repo/cookbooks/test/recipes/default.yml" },
60
+ { name: "recipes/default.yaml", full_path: "/home/user/repo/cookbooks/test/recipes/default.yaml" },
61
+ ]
62
+ )
63
+ end
64
+ it "because both are valid and we can't pick, it raises an error that contains the info needed to fix the problem" do
65
+ expect { cookbook_version.recipe_yml_filenames_by_name }
66
+ .to raise_error(Chef::Exceptions::AmbiguousYAMLFile, /.*default.yml.*default.yaml.*update the cookbook to remove/)
67
+ end
68
+ end
69
+
70
+ %w{yml yaml}.each do |extension|
71
+
72
+ context "and YAML files are present including a recipes/default.#{extension}" do
73
+ before(:each) do
74
+ allow(cookbook_version).to receive(:files_for).with("recipes").and_return(files_for_recipe(extension))
75
+ end
76
+
77
+ context "and manifest does not include a root_files/recipe.#{extension}" do
78
+ it "returns all YAML recipes with a correct default of default.#{extension}" do
79
+ expect(cookbook_version.recipe_yml_filenames_by_name).to eq({ "default" => "/home/user/repo/cookbooks/test/recipes/default.#{extension}",
80
+ "other" => "/home/user/repo/cookbooks/test/recipes/other.#{extension}" })
81
+ end
82
+ end
83
+
84
+ context "and manifest also includes a root_files/recipe.#{extension}" do
85
+ let(:root_files) { [{ name: "root_files/recipe.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipe.#{extension}" } ] }
86
+ before(:each) do
87
+ allow(cookbook_version.cookbook_manifest).to receive(:root_files).and_return(root_files)
88
+ end
44
89
 
90
+ it "returns all YAML recipes with a correct default of recipe.#{extension}" do
91
+ expect(cookbook_version.recipe_yml_filenames_by_name).to eq({ "default" => "/home/user/repo/cookbooks/test/recipe.#{extension}",
92
+ "other" => "/home/user/repo/cookbooks/test/recipes/other.#{extension}" })
93
+ end
94
+ end
95
+ end
96
+ end
45
97
  end
46
98
 
47
99
  describe "with a cookbook directory named tatft" do
@@ -142,11 +142,17 @@ describe Chef::DataCollector do
142
142
  def expect_converge_message(keys)
143
143
  keys["message_type"] = "run_converge"
144
144
  keys["message_version"] = "1.1.0"
145
+ # if (keys.key?("node") && !keys["node"].empty?)
146
+ # expect(rest_client).to receive(:post) do |_a, hash, _b|
147
+ # require 'pry'; binding.pry
148
+ # end
149
+ # else
145
150
  expect(rest_client).to receive(:post).with(
146
151
  nil,
147
152
  hash_including(keys),
148
153
  { "Content-Type" => "application/json" }
149
154
  )
155
+ # end
150
156
  end
151
157
 
152
158
  def resource_has_diff(new_resource, status)
@@ -158,7 +164,7 @@ describe Chef::DataCollector do
158
164
  "after" => after_resource&.state_for_resource_reporter || {},
159
165
  "before" => before_resource&.state_for_resource_reporter || {},
160
166
  "cookbook_name" => cookbook_name,
161
- "cookbook_version" => cookbook_version.version,
167
+ "cookbook_version" => cookbook_version&.version,
162
168
  "delta" => resource_has_diff(new_resource, status) ? new_resource.diff : "",
163
169
  "duration" => duration,
164
170
  "id" => new_resource.identity,
@@ -202,7 +208,7 @@ describe Chef::DataCollector do
202
208
  end
203
209
 
204
210
  it "has a node" do
205
- expect_converge_message("node" => expected_node)
211
+ expect_converge_message("node" => expected_node.is_a?(Chef::Node) ? expected_node.data_for_save : expected_node)
206
212
  send_run_failed_or_completed_event
207
213
  end
208
214
 
@@ -561,6 +567,29 @@ describe Chef::DataCollector do
561
567
  it_behaves_like "sends a converge message"
562
568
  end
563
569
 
570
+ context "when the run contains a file resource that is up-to-date from a @recipe_files, returns nil for the version" do
571
+ let(:total_resource_count) { 1 }
572
+ let(:updated_resource_count) { 0 }
573
+ let(:cookbook_name) { "@recipe_files" }
574
+ let(:resource_record) { [ resource_record_for(new_resource, current_resource, after_resource, :create, "up-to-date", "1234") ] }
575
+ let(:status) { "success" }
576
+ let(:cookbook_version) { nil }
577
+
578
+ before do
579
+ allow(new_resource).to receive(:cookbook_version).and_call_original
580
+ events.resource_action_start(new_resource, :create)
581
+ events.resource_current_state_loaded(new_resource, :create, current_resource)
582
+ events.resource_up_to_date(new_resource, :create)
583
+ events.resource_after_state_loaded(new_resource, :create, after_resource)
584
+ new_resource.instance_variable_set(:@elapsed_time, 1.2345)
585
+ events.resource_completed(new_resource)
586
+ events.converge_complete
587
+ run_status.stop_clock
588
+ end
589
+
590
+ it_behaves_like "sends a converge message"
591
+ end
592
+
564
593
  context "when the run contains a file resource that is updated" do
565
594
  let(:total_resource_count) { 1 }
566
595
  let(:updated_resource_count) { 1 }
@@ -808,6 +837,46 @@ describe Chef::DataCollector do
808
837
  it_behaves_like "sends a converge message"
809
838
  end
810
839
 
840
+ context "when node attributes are block-listed" do
841
+ let(:status) { "success" }
842
+ before do
843
+ Chef::Config[:blocked_default_attributes] = [
844
+ %w{secret key_to_the_kingdom},
845
+ ]
846
+ node.default = {
847
+ "secret" => { "key_to_the_kingdom" => "under the flower pot to the left of the drawbridge" },
848
+ "publicinfo" => { "num_flower_pots" => 18 },
849
+ }
850
+ end
851
+
852
+ it "payload should exclude blocked attributes" do
853
+ expect(rest_client).to receive(:post) do |_addr, hash, _headers|
854
+ expect(hash["node"]["default"]).to eq({ "secret" => {}, "publicinfo" => { "num_flower_pots" => 18 } })
855
+ end
856
+ send_run_failed_or_completed_event
857
+ end
858
+ end
859
+
860
+ context "when node attributes are allow-listed" do
861
+ let(:status) { "success" }
862
+ before do
863
+ Chef::Config[:allowed_default_attributes] = [
864
+ %w{public entrance},
865
+ ]
866
+ node.default = {
867
+ "public" => { "entrance" => "is the drawbridge" },
868
+ "secret" => { "entrance" => "is the tunnel" },
869
+ }
870
+ end
871
+
872
+ it "payload should include only allowed attributes" do
873
+ expect(rest_client).to receive(:post) do |_addr, hash, _headers|
874
+ expect(hash["node"]["default"]).to eq({ "public" => { "entrance" => "is the drawbridge" } })
875
+ end
876
+ send_run_failed_or_completed_event
877
+ end
878
+ end
879
+
811
880
  end
812
881
  end
813
882
 
@@ -206,7 +206,7 @@ describe Chef::PolicyBuilder::Policyfile do
206
206
  end
207
207
 
208
208
  before do
209
- Chef::Config[:policy_document_native_api] = false
209
+ Chef::Config[:policy_document_native_api] = true
210
210
  Chef::Config[:deployment_group] = "example-policy-stage"
211
211
  allow(policy_builder).to receive(:api_service).and_return(api_service)
212
212
  end
@@ -214,6 +214,8 @@ describe Chef::PolicyBuilder::Policyfile do
214
214
  describe "when using compatibility mode (policy_document_native_api == false)" do
215
215
 
216
216
  before do
217
+ Chef::Config[:policy_document_native_api] = false
218
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
217
219
  Chef::Config[:deployment_group] = "example-policy-stage"
218
220
  end
219
221
 
@@ -339,6 +341,10 @@ describe Chef::PolicyBuilder::Policyfile do
339
341
  end
340
342
 
341
343
  describe "validating the Policyfile.lock" do
344
+ before do
345
+ Chef::Config[:policy_group] = "policy-stage"
346
+ Chef::Config[:policy_name] = "example"
347
+ end
342
348
 
343
349
  it "errors if the policyfile json contains any non-recipe items" do
344
350
  parsed_policyfile_json["run_list"] = ["role[foo]"]
@@ -806,6 +812,10 @@ describe Chef::PolicyBuilder::Policyfile do
806
812
  context "when using compatibility mode (policy_document_native_api == false)" do
807
813
  let(:cookbook1_url) { "cookbooks/example1/#{example1_xyz_version}" }
808
814
  let(:cookbook2_url) { "cookbooks/example2/#{example2_xyz_version}" }
815
+ before do
816
+ Chef::Config[:policy_document_native_api] = false
817
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
818
+ end
809
819
 
810
820
  context "when the cookbooks don't exist on the server" do
811
821
  include_examples "fetching cookbooks when they don't exist"
@@ -105,6 +105,10 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
105
105
  let(:generated_install_cmdlet) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version" }
106
106
  let(:generated_install_cmdlet_with_version) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 ).Version" }
107
107
  let(:generated_install_cmdlet_with_source) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -Source MyGallery ).Version" }
108
+ let(:generated_install_cmdlet_with_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -AcceptLicense -Verbose ).Version" }
109
+ let(:generated_install_cmdlet_with_version_and_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 -AcceptLicense -Verbose ).Version" }
110
+ let(:generated_install_cmdlet_with_source_and_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -Source MyGallery -AcceptLicense -Verbose ).Version" }
111
+ let(:generated_install_cmdlet_with_source_and_version_and_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 -Source MyGallery -AcceptLicense -Verbose ).Version" }
108
112
  let(:generated_install_cmdlet_with_source_and_version) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 -Source MyGallery ).Version" }
109
113
  let(:generated_uninstall_cmdlet) { "#{tls_set_command} ( Uninstall-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version" }
110
114
  let(:generated_uninstall_cmdlet_with_version) { "#{tls_set_command} ( Uninstall-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 ).Version" }
@@ -204,11 +208,11 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
204
208
  end
205
209
 
206
210
  context "when source is nil" do
207
- it "build get commands correctly" do
211
+ it "builds get commands correctly" do
208
212
  expect(provider.build_powershell_package_command("Get-Package xNetworking")).to eql(generated_get_cmdlet)
209
213
  end
210
214
 
211
- it "build get commands correctly when a version is passed" do
215
+ it "builds get commands correctly when a version is passed" do
212
216
  expect(provider.build_powershell_package_command("Get-Package xNetworking", "1.0.0.0")).to eql(generated_get_cmdlet_with_version)
213
217
  end
214
218
 
@@ -220,30 +224,45 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
220
224
  expect(provider.build_powershell_package_command("Find-Package xNetworking", "1.0.0.0")).to eql(generated_find_cmdlet_with_version)
221
225
  end
222
226
 
223
- it "build install commands correctly" do
227
+ it "builds install commands correctly" do
224
228
  expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet)
225
229
  end
226
230
 
227
- it "build install commands correctly when a version is passed" do
231
+ it "builds install commands correctly when a version is passed" do
228
232
  expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_version)
229
233
  end
230
234
 
231
- it "build install commands correctly" do
235
+ it "builds install commands correctly when options are passed" do
236
+ new_resource.options("-AcceptLicense -Verbose")
237
+ expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_options)
238
+ end
239
+
240
+ it "builds install commands correctly when duplicate options are passed" do
241
+ new_resource.options("-WarningAction SilentlyContinue")
242
+ expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet)
243
+ end
244
+
245
+ it "builds install commands correctly when a version and options are passed" do
246
+ new_resource.options("-AcceptLicense -Verbose")
247
+ expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_version_and_options)
248
+ end
249
+
250
+ it "builds install commands correctly" do
232
251
  expect(provider.build_powershell_package_command("Uninstall-Package xNetworking")).to eql(generated_uninstall_cmdlet)
233
252
  end
234
253
 
235
- it "build install commands correctly when a version is passed" do
254
+ it "builds install commands correctly when a version is passed" do
236
255
  expect(provider.build_powershell_package_command("Uninstall-Package xNetworking", "1.0.0.0")).to eql(generated_uninstall_cmdlet_with_version)
237
256
  end
238
257
  end
239
258
 
240
259
  context "when source is set" do
241
- it "build get commands correctly" do
260
+ it "builds get commands correctly" do
242
261
  new_resource.source("MyGallery")
243
262
  expect(provider.build_powershell_package_command("Get-Package xNetworking")).to eql(generated_get_cmdlet)
244
263
  end
245
264
 
246
- it "build get commands correctly when a version is passed" do
265
+ it "builds get commands correctly when a version is passed" do
247
266
  new_resource.source("MyGallery")
248
267
  expect(provider.build_powershell_package_command("Get-Package xNetworking", "1.0.0.0")).to eql(generated_get_cmdlet_with_version)
249
268
  end
@@ -258,22 +277,40 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
258
277
  expect(provider.build_powershell_package_command("Find-Package xNetworking", "1.0.0.0")).to eql(generated_find_cmdlet_with_source_and_version)
259
278
  end
260
279
 
261
- it "build install commands correctly" do
280
+ it "builds install commands correctly" do
262
281
  new_resource.source("MyGallery")
263
282
  expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_source)
264
283
  end
265
284
 
266
- it "build install commands correctly when a version is passed" do
285
+ it "builds install commands correctly when a version is passed" do
267
286
  new_resource.source("MyGallery")
268
287
  expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_source_and_version)
269
288
  end
270
289
 
271
- it "build install commands correctly" do
290
+ it "builds install commands correctly when options are passed" do
291
+ new_resource.source("MyGallery")
292
+ new_resource.options("-AcceptLicense -Verbose")
293
+ expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_source_and_options)
294
+ end
295
+
296
+ it "builds install commands correctly when duplicate options are passed" do
297
+ new_resource.source("MyGallery")
298
+ new_resource.options("-Force -ForceBootstrap")
299
+ expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_source)
300
+ end
301
+
302
+ it "builds install commands correctly when a version and options are passed" do
303
+ new_resource.source("MyGallery")
304
+ new_resource.options("-AcceptLicense -Verbose")
305
+ expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_source_and_version_and_options)
306
+ end
307
+
308
+ it "builds install commands correctly" do
272
309
  new_resource.source("MyGallery")
273
310
  expect(provider.build_powershell_package_command("Uninstall-Package xNetworking")).to eql(generated_uninstall_cmdlet)
274
311
  end
275
312
 
276
- it "build install commands correctly when a version is passed" do
313
+ it "builds install commands correctly when a version is passed" do
277
314
  new_resource.source("MyGallery")
278
315
  expect(provider.build_powershell_package_command("Uninstall-Package xNetworking", "1.0.0.0")).to eql(generated_uninstall_cmdlet_with_version)
279
316
  end
@@ -434,6 +471,19 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
434
471
  provider.run_action(:install)
435
472
  expect(new_resource).to be_updated_by_last_action
436
473
  end
474
+
475
+ it "should install a package using provided options" do
476
+ provider.load_current_resource
477
+ new_resource.package_name(["xCertificate"])
478
+ new_resource.version(nil)
479
+ new_resource.options(%w{-AcceptLicense -Verbose})
480
+ allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Find-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_available)
481
+ allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Get-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_not_available)
482
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
483
+ expect(provider).to receive(:powershell_out).with("#{tls_set_command} ( Install-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 2.1.0.0 -AcceptLicense -Verbose ).Version", { timeout: new_resource.timeout })
484
+ provider.run_action(:install)
485
+ expect(new_resource).to be_updated_by_last_action
486
+ end
437
487
  end
438
488
 
439
489
  describe "#action_remove" do
@@ -499,5 +549,17 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
499
549
  provider.run_action(:remove)
500
550
  expect(new_resource).to be_updated_by_last_action
501
551
  end
552
+
553
+ it "should remove a package using provided options" do
554
+ new_resource.package_name(["xCertificate"])
555
+ new_resource.options(%w{-AllVersions})
556
+ allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Find-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_available)
557
+ allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Get-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_available)
558
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
559
+ provider.load_current_resource
560
+ expect(provider).to receive(:powershell_out).with("#{tls_set_command} ( Uninstall-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue -AllVersions ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_not_available)
561
+ provider.run_action(:remove)
562
+ expect(new_resource).to be_updated_by_last_action
563
+ end
502
564
  end
503
565
  end
@@ -51,4 +51,18 @@ describe Chef::Resource::ChefClientTrustedCertificate do
51
51
  expect(provider.cert_path).to match(%r{trusted_certs/something.pem$})
52
52
  end
53
53
  end
54
+
55
+ describe "sensitive attribute" do
56
+ context "should be insensitive by default" do
57
+ it { expect(resource.sensitive).to(be_falsey) }
58
+ end
59
+
60
+ context "when set" do
61
+ before { resource.sensitive(true) }
62
+
63
+ it "should be set on the resource" do
64
+ expect(resource.sensitive).to(be_truthy)
65
+ end
66
+ end
67
+ end
54
68
  end
@@ -19,22 +19,40 @@ require "spec_helper"
19
19
 
20
20
  describe Chef::Resource::HomebrewCask do
21
21
 
22
- let(:resource) { Chef::Resource::HomebrewCask.new("fakey_fakerton") }
22
+ context "name with under bar" do
23
+ let(:resource) { Chef::Resource::HomebrewCask.new("fakey_fakerton") }
23
24
 
24
- it "has a resource name of :homebrew_cask" do
25
- expect(resource.resource_name).to eql(:homebrew_cask)
26
- end
25
+ it "has a resource name of :homebrew_cask" do
26
+ expect(resource.resource_name).to eql(:homebrew_cask)
27
+ end
28
+
29
+ it "the cask_name property is the name_property" do
30
+ expect(resource.cask_name).to eql("fakey_fakerton")
31
+ end
32
+
33
+ it "sets the default action as :install" do
34
+ expect(resource.action).to eql([:install])
35
+ end
27
36
 
28
- it "the cask_name property is the name_property" do
29
- expect(resource.cask_name).to eql("fakey_fakerton")
37
+ it "supports :install, :remove actions" do
38
+ expect { resource.action :install }.not_to raise_error
39
+ expect { resource.action :remove }.not_to raise_error
40
+ end
30
41
  end
31
42
 
32
- it "sets the default action as :install" do
33
- expect(resource.action).to eql([:install])
43
+ context "name with high fun" do
44
+ let(:resource) { Chef::Resource::HomebrewCask.new("fakey-fakerton") }
45
+
46
+ it "the cask_name property is the name_property" do
47
+ expect(resource.cask_name).to eql("fakey-fakerton")
48
+ end
34
49
  end
35
50
 
36
- it "supports :install, :remove actions" do
37
- expect { resource.action :install }.not_to raise_error
38
- expect { resource.action :remove }.not_to raise_error
51
+ context "name with at mark" do
52
+ let(:resource) { Chef::Resource::HomebrewCask.new("fakey-fakerton@10") }
53
+
54
+ it "the cask_name property is the name_property" do
55
+ expect(resource.cask_name).to eql("fakey-fakerton@10")
56
+ end
39
57
  end
40
58
  end
@@ -59,6 +59,16 @@ describe Chef::Resource::Mount do
59
59
  expect(resource.mount_point).to eql("//192.168.11.102/Share/backup")
60
60
  end
61
61
 
62
+ it "does not strip slash when mount_point is root directory" do
63
+ resource.mount_point "/"
64
+ expect(resource.mount_point).to eql("/")
65
+ end
66
+
67
+ it "does not strip slash when mount_point is root of network mount" do
68
+ resource.mount_point "127.0.0.1:/"
69
+ expect(resource.mount_point).to eql("127.0.0.1:/")
70
+ end
71
+
62
72
  it "raises error when mount_point property is not set" do
63
73
  expect { resource.mount_point nil }.to raise_error(Chef::Exceptions::ValidationFailed, "Property mount_point must be one of: String! You passed nil.")
64
74
  end