chef 17.6.18 → 17.9.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/chef.gemspec +1 -0
  4. data/lib/chef/application/base.rb +1 -1
  5. data/lib/chef/chef_fs/file_pattern.rb +1 -1
  6. data/lib/chef/chef_fs/path_utils.rb +1 -1
  7. data/lib/chef/compliance/default_attributes.rb +12 -2
  8. data/lib/chef/compliance/runner.rb +51 -5
  9. data/lib/chef/data_collector/run_end_message.rb +1 -1
  10. data/lib/chef/dsl/reboot_pending.rb +1 -1
  11. data/lib/chef/exceptions.rb +10 -0
  12. data/lib/chef/mixin/powershell_exec.rb +6 -5
  13. data/lib/chef/mixin/why_run.rb +8 -2
  14. data/lib/chef/powershell.rb +8 -6
  15. data/lib/chef/provider/cron.rb +6 -3
  16. data/lib/chef/provider/directory.rb +2 -2
  17. data/lib/chef/provider/git.rb +1 -1
  18. data/lib/chef/provider/ifconfig/debian.rb +1 -1
  19. data/lib/chef/provider/ifconfig.rb +4 -4
  20. data/lib/chef/provider/mount/linux.rb +16 -2
  21. data/lib/chef/provider/mount/mount.rb +1 -1
  22. data/lib/chef/provider/package/dnf.rb +1 -1
  23. data/lib/chef/provider/package/habitat.rb +1 -1
  24. data/lib/chef/provider/package/powershell.rb +13 -10
  25. data/lib/chef/provider/package/yum/python_helper.rb +81 -25
  26. data/lib/chef/provider/package/yum.rb +39 -12
  27. data/lib/chef/provider/package/zypper.rb +2 -0
  28. data/lib/chef/provider/package.rb +62 -27
  29. data/lib/chef/provider/subversion.rb +5 -5
  30. data/lib/chef/provider.rb +5 -2
  31. data/lib/chef/providers.rb +0 -1
  32. data/lib/chef/pwsh.rb +3 -2
  33. data/lib/chef/resource/apt_package.rb +2 -2
  34. data/lib/chef/resource/chef_client_config.rb +21 -1
  35. data/lib/chef/resource/chef_client_launchd.rb +1 -1
  36. data/lib/chef/resource/chef_client_trusted_certificate.rb +1 -0
  37. data/lib/chef/resource/chocolatey_config.rb +1 -1
  38. data/lib/chef/resource/chocolatey_feature.rb +1 -1
  39. data/lib/chef/resource/chocolatey_package.rb +3 -3
  40. data/lib/chef/resource/chocolatey_source.rb +24 -2
  41. data/lib/chef/resource/cron/cron.rb +75 -1
  42. data/lib/chef/resource/cron/cron_d.rb +2 -1
  43. data/lib/chef/resource/directory.rb +1 -1
  44. data/lib/chef/resource/dnf_package.rb +4 -6
  45. data/lib/chef/resource/dpkg_package.rb +5 -0
  46. data/lib/chef/resource/execute.rb +1 -4
  47. data/lib/chef/resource/habitat_install.rb +5 -5
  48. data/lib/chef/resource/homebrew_tap.rb +0 -4
  49. data/lib/chef/resource/inspec_waiver.rb +1 -1
  50. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  51. data/lib/chef/resource/kernel_module.rb +27 -2
  52. data/lib/chef/resource/launchd.rb +0 -3
  53. data/lib/chef/resource/macos_userdefaults.rb +41 -131
  54. data/lib/chef/resource/powershell_package_source.rb +8 -8
  55. data/lib/chef/resource/rhsm_register.rb +31 -0
  56. data/lib/chef/resource/support/client.erb +7 -0
  57. data/lib/chef/resource/windows_auto_run.rb +1 -1
  58. data/lib/chef/resource/windows_dfs_namespace.rb +2 -2
  59. data/lib/chef/resource/windows_feature_powershell.rb +8 -9
  60. data/lib/chef/resource/windows_task.rb +25 -10
  61. data/lib/chef/resource/windows_update_settings.rb +3 -3
  62. data/lib/chef/resource.rb +2 -2
  63. data/lib/chef/resource_reporter.rb +1 -1
  64. data/lib/chef/secret_fetcher/azure_key_vault.rb +64 -8
  65. data/lib/chef/secret_fetcher/hashi_vault.rb +37 -3
  66. data/lib/chef/secret_fetcher.rb +0 -1
  67. data/lib/chef/version.rb +1 -1
  68. data/spec/functional/dsl/reboot_pending_spec.rb +3 -3
  69. data/spec/functional/dsl/registry_helper_spec.rb +1 -1
  70. data/spec/functional/resource/dnf_package_spec.rb +138 -124
  71. data/spec/functional/resource/dpkg_package_spec.rb +16 -0
  72. data/spec/functional/resource/dsc_script_spec.rb +2 -2
  73. data/spec/functional/resource/macos_userdefaults_spec.rb +139 -0
  74. data/spec/functional/resource/registry_spec.rb +81 -81
  75. data/spec/functional/resource/yum_package_spec.rb +789 -129
  76. data/spec/functional/resource/zypper_package_spec.rb +7 -0
  77. data/spec/functional/win32/registry_spec.rb +8 -8
  78. data/spec/integration/client/client_spec.rb +31 -0
  79. data/spec/unit/application/base_spec.rb +40 -0
  80. data/spec/unit/compliance/runner_spec.rb +62 -1
  81. data/spec/unit/data_collector_spec.rb +24 -1
  82. data/spec/unit/dsl/reboot_pending_spec.rb +1 -1
  83. data/spec/unit/file_access_control_spec.rb +1 -1
  84. data/spec/unit/mixin/default_paths_spec.rb +1 -1
  85. data/spec/unit/mixin/securable_spec.rb +3 -3
  86. data/spec/unit/mixin/why_run_spec.rb +53 -0
  87. data/spec/unit/provider/cron_spec.rb +45 -0
  88. data/spec/unit/provider/group/groupadd_spec.rb +1 -0
  89. data/spec/unit/provider/group/usermod_spec.rb +2 -2
  90. data/spec/unit/provider/ifconfig_spec.rb +2 -0
  91. data/spec/unit/provider/mount/linux_spec.rb +16 -3
  92. data/spec/unit/provider/package/bff_spec.rb +1 -0
  93. data/spec/unit/provider/package/powershell_spec.rb +114 -114
  94. data/spec/unit/provider/package/rubygems_spec.rb +8 -5
  95. data/spec/unit/provider/package/solaris_spec.rb +1 -0
  96. data/spec/unit/provider/package/windows_spec.rb +1 -1
  97. data/spec/unit/provider/registry_key_spec.rb +4 -4
  98. data/spec/unit/provider/service/arch_service_spec.rb +2 -2
  99. data/spec/unit/provider/service/debian_service_spec.rb +1 -0
  100. data/spec/unit/provider/service/gentoo_service_spec.rb +1 -0
  101. data/spec/unit/provider/service/macosx_spec.rb +1 -0
  102. data/spec/unit/provider/service/redhat_spec.rb +4 -1
  103. data/spec/unit/provider/service/simple_service_spec.rb +6 -4
  104. data/spec/unit/provider/service/windows_spec.rb +5 -5
  105. data/spec/unit/provider/subversion_spec.rb +4 -4
  106. data/spec/unit/provider/user_spec.rb +2 -0
  107. data/spec/unit/provider/windows_env_spec.rb +1 -1
  108. data/spec/unit/provider/zypper_repository_spec.rb +1 -1
  109. data/spec/unit/resource/chef_client_trusted_certificate_spec.rb +14 -0
  110. data/spec/unit/resource/chocolatey_config_spec.rb +1 -1
  111. data/spec/unit/resource/chocolatey_feature_spec.rb +1 -1
  112. data/spec/unit/resource/chocolatey_source_spec.rb +1 -1
  113. data/spec/unit/resource/dpkg_package_spec.rb +12 -0
  114. data/spec/unit/resource/kernel_module_spec.rb +2 -1
  115. data/spec/unit/resource/macos_user_defaults_spec.rb +36 -96
  116. data/spec/unit/resource/registry_key_spec.rb +10 -10
  117. data/spec/unit/resource/rhsm_register_spec.rb +42 -0
  118. data/spec/unit/resource/windows_auto_run_spec.rb +1 -1
  119. data/spec/unit/resource/windows_feature_powershell_spec.rb +1 -1
  120. data/spec/unit/resource/windows_firewall_rule_spec.rb +2 -2
  121. data/spec/unit/resource/windows_task_spec.rb +3 -3
  122. data/spec/unit/resource_reporter_spec.rb +2 -2
  123. data/spec/unit/resource_spec.rb +5 -0
  124. data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +99 -20
  125. data/spec/unit/secret_fetcher/hashi_vault_spec.rb +46 -0
  126. data/spec/unit/util/backup_spec.rb +1 -1
  127. data/spec/unit/win32/registry_spec.rb +3 -3
  128. metadata +24 -9
  129. data/lib/chef/provider/group/suse.rb +0 -82
  130. data/spec/unit/provider/group/suse_spec.rb +0 -90
@@ -187,6 +187,13 @@ describe Chef::Resource::ZypperPackage, :requires_root, :suse_only do
187
187
  expect(zypper_package.updated_by_last_action?).to be true
188
188
  expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
189
189
  end
190
+
191
+ it "is idempotent when a package isn't installed" do
192
+ FileUtils.rm_f "/etc/zypp/repos.d/chef-zypp-localtesting.repo"
193
+ zypper_package.run_action(:remove)
194
+ expect(zypper_package.updated_by_last_action?).to be false
195
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
196
+ end
190
197
  end
191
198
  end
192
199
 
@@ -28,14 +28,14 @@ describe "Chef::Win32::Registry", :windows_only do
28
28
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root\\Branch"
29
29
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root\\B®anch"
30
30
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root\\Branch\\Flower"
31
- ::Win32::Registry::HKEY_CURRENT_USER.open('Software\\Root', Win32::Registry::KEY_ALL_ACCESS) do |reg|
31
+ ::Win32::Registry::HKEY_CURRENT_USER.open("Software\\Root", Win32::Registry::KEY_ALL_ACCESS) do |reg|
32
32
  reg["RootType1", Win32::Registry::REG_SZ] = "fibrous"
33
33
  reg.write("Roots", Win32::Registry::REG_MULTI_SZ, ["strong roots", "healthy tree"])
34
34
  end
35
- ::Win32::Registry::HKEY_CURRENT_USER.open('Software\\Root\\Branch', Win32::Registry::KEY_ALL_ACCESS) do |reg|
35
+ ::Win32::Registry::HKEY_CURRENT_USER.open("Software\\Root\\Branch", Win32::Registry::KEY_ALL_ACCESS) do |reg|
36
36
  reg["Strong", Win32::Registry::REG_SZ] = "bird nest"
37
37
  end
38
- ::Win32::Registry::HKEY_CURRENT_USER.open('Software\\Root\\Branch\\Flower', Win32::Registry::KEY_ALL_ACCESS) do |reg|
38
+ ::Win32::Registry::HKEY_CURRENT_USER.open("Software\\Root\\Branch\\Flower", Win32::Registry::KEY_ALL_ACCESS) do |reg|
39
39
  reg["Petals", Win32::Registry::REG_MULTI_SZ] = %w{Pink Delicate}
40
40
  end
41
41
 
@@ -297,7 +297,7 @@ describe "Chef::Win32::Registry", :windows_only do
297
297
  describe "delete_value" do
298
298
  before(:all) do
299
299
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root\\Trunk\\Peck\\Woodpecker"
300
- ::Win32::Registry::HKEY_CURRENT_USER.open('Software\\Root\\Trunk\\Peck\\Woodpecker', Win32::Registry::KEY_ALL_ACCESS) do |reg|
300
+ ::Win32::Registry::HKEY_CURRENT_USER.open("Software\\Root\\Trunk\\Peck\\Woodpecker", Win32::Registry::KEY_ALL_ACCESS) do |reg|
301
301
  reg["Peter", Win32::Registry::REG_SZ] = "Tiny"
302
302
  end
303
303
  end
@@ -324,11 +324,11 @@ describe "Chef::Win32::Registry", :windows_only do
324
324
  describe "delete_key" do
325
325
  before(:all) do
326
326
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root\\Branch\\Fruit"
327
- ::Win32::Registry::HKEY_CURRENT_USER.open('Software\\Root\\Branch\\Fruit', Win32::Registry::KEY_ALL_ACCESS) do |reg|
327
+ ::Win32::Registry::HKEY_CURRENT_USER.open("Software\\Root\\Branch\\Fruit", Win32::Registry::KEY_ALL_ACCESS) do |reg|
328
328
  reg["Apple", Win32::Registry::REG_MULTI_SZ] = %w{Red Juicy}
329
329
  end
330
330
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root\\Trunk\\Peck\\Woodpecker"
331
- ::Win32::Registry::HKEY_CURRENT_USER.open('Software\\Root\\Trunk\\Peck\\Woodpecker', Win32::Registry::KEY_ALL_ACCESS) do |reg|
331
+ ::Win32::Registry::HKEY_CURRENT_USER.open("Software\\Root\\Trunk\\Peck\\Woodpecker", Win32::Registry::KEY_ALL_ACCESS) do |reg|
332
332
  reg["Peter", Win32::Registry::REG_SZ] = "Tiny"
333
333
  end
334
334
  end
@@ -519,12 +519,12 @@ describe "Chef::Win32::Registry", :windows_only do
519
519
  end
520
520
  # 64-bit
521
521
  ::Win32::Registry::HKEY_LOCAL_MACHINE.create("Software\\Root\\Mauve", ::Win32::Registry::KEY_ALL_ACCESS | 0x0100)
522
- ::Win32::Registry::HKEY_LOCAL_MACHINE.open('Software\\Root\\Mauve', Win32::Registry::KEY_ALL_ACCESS | 0x0100) do |reg|
522
+ ::Win32::Registry::HKEY_LOCAL_MACHINE.open("Software\\Root\\Mauve", Win32::Registry::KEY_ALL_ACCESS | 0x0100) do |reg|
523
523
  reg["Alert", Win32::Registry::REG_SZ] = "Universal"
524
524
  end
525
525
  # 32-bit
526
526
  ::Win32::Registry::HKEY_LOCAL_MACHINE.create("Software\\Root\\Poosh", ::Win32::Registry::KEY_ALL_ACCESS | 0x0200)
527
- ::Win32::Registry::HKEY_LOCAL_MACHINE.open('Software\\Root\\Poosh', Win32::Registry::KEY_ALL_ACCESS | 0x0200) do |reg|
527
+ ::Win32::Registry::HKEY_LOCAL_MACHINE.open("Software\\Root\\Poosh", Win32::Registry::KEY_ALL_ACCESS | 0x0200) do |reg|
528
528
  reg["Status", Win32::Registry::REG_SZ] = "Lost"
529
529
  end
530
530
  end
@@ -48,6 +48,37 @@ describe "chef-client" do
48
48
  let(:chef_client) { "bundle exec #{ChefUtils::Dist::Infra::CLIENT} --minimal-ohai" }
49
49
  let(:chef_solo) { "bundle exec #{ChefUtils::Dist::Solo::EXEC} --legacy-mode --minimal-ohai" }
50
50
 
51
+ context "when validation.pem in current Directory" do
52
+ let(:validation_path) { "" }
53
+
54
+ before do
55
+ tempfile = Tempfile.new(validation_path)
56
+ tempfile.write "string"
57
+ tempfile.close
58
+ @path = tempfile.path
59
+ Chef::Config.validation_key = @path
60
+
61
+ file "config/client.rb", <<~EOM
62
+ local_mode true
63
+ cookbook_path "#{path_to("cookbooks")}"
64
+ EOM
65
+ end
66
+
67
+ it "should find validation.pem successfully in current dir" do
68
+ validation_path = "validation.pem"
69
+ shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -K #{@path} ", cwd: chef_dir)
70
+ end
71
+
72
+ it "should find validation.pem successfully in current dir" do
73
+ validation_path = "/tmp/validation.pem"
74
+ shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -K #{@path} ", cwd: chef_dir)
75
+ end
76
+
77
+ it "should find validation.pem successfully in default directory" do
78
+ shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" ", cwd: chef_dir)
79
+ end
80
+ end
81
+
51
82
  when_the_repository "has a cookbook with a no-op recipe" do
52
83
  before { file "cookbooks/x/recipes/default.rb", "" }
53
84
 
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Chef::Application::Base, "setup_application" do
4
+ let(:validation_path) { "" }
5
+
6
+ context "when validation key is supplied" do
7
+ before do
8
+ @app = Chef::Application::Base.new
9
+ tempfile = Tempfile.new(validation_path)
10
+ tempfile.write "string"
11
+ tempfile.close
12
+ @path = tempfile.path
13
+ Chef::Config.validation_key = @path
14
+ end
15
+
16
+ context "when key is in current directory" do
17
+ it "should find with full path of validation_key" do
18
+ validation_path = "validation.pem"
19
+ expect(Chef::Config.validation_key).to eql(@path)
20
+ end
21
+ end
22
+
23
+ context "when path is given" do
24
+ validation_path = "/tmp/validation.pem"
25
+ it "should find validation_key" do
26
+ expect(Chef::Config.validation_key).to eql(@path)
27
+ end
28
+ end
29
+ end
30
+
31
+ context "when validation key is not supplied" do
32
+ it "should return default path for validation_key" do
33
+ if windows?
34
+ expect(Chef::Config.validation_key).to eql("C:\\chef\\validation.pem")
35
+ else
36
+ expect(Chef::Config.validation_key).to eql("/etc/chef/validation.pem")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require "tmpdir"
2
3
 
3
4
  describe Chef::Compliance::Runner do
4
5
  let(:logger) { double(:logger).as_null_object }
@@ -216,6 +217,7 @@ describe Chef::Compliance::Runner do
216
217
  node.normal["audit"]["reporter"] = [ "chef-automate" ]
217
218
  reporter_double = double("reporter", validate_config!: nil)
218
219
  expect(runner).to receive(:reporter).with("chef-automate").and_return(reporter_double)
220
+ expect(runner).to receive(:reporter).with("cli").and_return(reporter_double)
219
221
  runner.load_and_validate!
220
222
  end
221
223
 
@@ -278,8 +280,67 @@ describe Chef::Compliance::Runner do
278
280
  inputs = runner.inspec_opts[:inputs]
279
281
 
280
282
  expect(inputs["tacos"]).to eq("lunch")
281
- expect(inputs["chef_node"]["audit"]["reporter"]).to eq("cli")
283
+ expect(inputs["chef_node"]["audit"]["reporter"]).to eq(nil)
282
284
  expect(inputs["chef_node"]["chef_environment"]).to eq("_default")
283
285
  end
284
286
  end
287
+
288
+ describe "interval running" do
289
+ let(:tempdir) { Dir.mktmpdir("chef-compliance-tests") }
290
+
291
+ before do
292
+ allow(runner).to receive(:report_timing_file).and_return("#{tempdir}/report_timing.json")
293
+ end
294
+
295
+ it "is disabled by default" do
296
+ expect(runner.node["audit"]["interval"]["enabled"]).to be false
297
+ end
298
+
299
+ it "defaults to 24 hours / 1440 minutes" do
300
+ expect(runner.node["audit"]["interval"]["time"]).to be 1440
301
+ end
302
+
303
+ it "runs when the timing file does not exist" do
304
+ expect(runner).to receive(:report)
305
+ runner.report_with_interval
306
+ end
307
+
308
+ it "runs when the timing file does not exist and intervals are enabled" do
309
+ node.normal["audit"]["interval"]["enabled"] = true
310
+ expect(runner).to receive(:report)
311
+ runner.report_with_interval
312
+ end
313
+
314
+ it "runs when the timing file exists and has a recent timestamp" do
315
+ FileUtils.touch runner.report_timing_file
316
+ expect(runner).to receive(:report)
317
+ runner.report_with_interval
318
+ end
319
+
320
+ it "does not runs when the timing file exists and has a recent timestamp and intervals are enabled" do
321
+ node.normal["audit"]["interval"]["enabled"] = true
322
+ FileUtils.touch runner.report_timing_file
323
+ expect(runner).not_to receive(:report)
324
+ runner.report_with_interval
325
+ end
326
+
327
+ it "does not runs when the timing file exists and has a recent timestamp and intervals are enabled" do
328
+ node.normal["audit"]["interval"]["enabled"] = true
329
+ FileUtils.touch runner.report_timing_file
330
+ ten_minutes_ago = Time.now - 600
331
+ File.utime ten_minutes_ago, ten_minutes_ago, runner.report_timing_file
332
+ expect(runner).not_to receive(:report)
333
+ runner.report_with_interval
334
+ end
335
+
336
+ it "runs when the timing file exists and has a recent timestamp and intervals are enabled and the time is short" do
337
+ node.normal["audit"]["interval"]["enabled"] = true
338
+ node.normal["audit"]["interval"]["time"] = 9
339
+ FileUtils.touch runner.report_timing_file
340
+ ten_minutes_ago = Time.now - 600
341
+ File.utime ten_minutes_ago, ten_minutes_ago, runner.report_timing_file
342
+ expect(runner).to receive(:report)
343
+ runner.report_with_interval
344
+ end
345
+ end
285
346
  end
@@ -164,7 +164,7 @@ describe Chef::DataCollector do
164
164
  "after" => after_resource&.state_for_resource_reporter || {},
165
165
  "before" => before_resource&.state_for_resource_reporter || {},
166
166
  "cookbook_name" => cookbook_name,
167
- "cookbook_version" => cookbook_version.version,
167
+ "cookbook_version" => cookbook_version&.version,
168
168
  "delta" => resource_has_diff(new_resource, status) ? new_resource.diff : "",
169
169
  "duration" => duration,
170
170
  "id" => new_resource.identity,
@@ -567,6 +567,29 @@ describe Chef::DataCollector do
567
567
  it_behaves_like "sends a converge message"
568
568
  end
569
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
+
570
593
  context "when the run contains a file resource that is updated" do
571
594
  let(:total_resource_count) { 1 }
572
595
  let(:updated_resource_count) { 1 }
@@ -36,7 +36,7 @@ describe Chef::DSL::RebootPending do
36
36
  end
37
37
 
38
38
  it 'should return true if "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations" exists' do
39
- allow(recipe).to receive(:registry_value_exists?).with('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager', { name: "PendingFileRenameOperations" }).and_return(true)
39
+ allow(recipe).to receive(:registry_value_exists?).with("HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager", { name: "PendingFileRenameOperations" }).and_return(true)
40
40
  expect(recipe.reboot_pending?).to be_truthy
41
41
  end
42
42
 
@@ -35,7 +35,7 @@ describe Chef::FileAccessControl do
35
35
  @events = Chef::EventDispatch::Dispatcher.new
36
36
  @run_context = Chef::RunContext.new(@node, {}, @events)
37
37
  @current_resource = Chef::Resource::File.new("/tmp/different_file.txt")
38
- @provider_requirements = Chef::Provider::ResourceRequirements.new(@resource, @run_context)
38
+ @provider_requirements = Chef::Provider::ResourceRequirements.new(@resource, @run_context, :create)
39
39
  @provider = double("File provider", requirements: @provider_requirements, manage_symlink_access?: false)
40
40
 
41
41
  @fac = Chef::FileAccessControl.new(@current_resource, @resource, @provider)
@@ -84,7 +84,7 @@ describe Chef::Mixin::DefaultPaths do
84
84
  allow(Gem).to receive(:bindir).and_return(gem_bindir)
85
85
  allow(RbConfig::CONFIG).to receive(:[]).with("bindir").and_return(ruby_bindir)
86
86
  allow(ChefUtils).to receive(:windows?).and_return(true)
87
- env = { "PATH" => 'C:\Windows\system32;C:\mr\softie' }
87
+ env = { "PATH" => "C:\\Windows\\system32;C:\\mr\\softie" }
88
88
  @default_paths.enforce_default_paths(env)
89
89
  expect(env["PATH"]).to eq("#{gem_bindir};#{ruby_bindir};C:\\Windows\\system32;C:\\mr\\softie")
90
90
  end
@@ -53,8 +53,8 @@ describe Chef::Mixin::Securable do
53
53
  end
54
54
 
55
55
  it "should accept group/owner names with spaces and backslashes" do
56
- expect { @securable.group 'test\ group' }.not_to raise_error
57
- expect { @securable.owner 'test\ group' }.not_to raise_error
56
+ expect { @securable.group "test\\ group" }.not_to raise_error
57
+ expect { @securable.owner "test\\ group" }.not_to raise_error
58
58
  end
59
59
 
60
60
  it "should accept group/owner names that are a single character or digit" do
@@ -186,7 +186,7 @@ describe Chef::Mixin::Securable do
186
186
  end
187
187
 
188
188
  it "should not accept a group name or id for group with spaces and multiple backslashes" do
189
- expect { @securable.group 'test\ \group' }.to raise_error(ArgumentError)
189
+ expect { @securable.group "test\\ \\group" }.to raise_error(ArgumentError)
190
190
  end
191
191
 
192
192
  it "should accept a unix file mode in string form as an octal number" do
@@ -0,0 +1,53 @@
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::Mixin::WhyRun::ResourceRequirements do
21
+ class TestResource < Chef::Resource
22
+ action_class do
23
+ def define_resource_requirements
24
+ requirements.assert(:boom) do |a|
25
+ a.assertion { raise "boom1" }
26
+ a.failure_message("#{raise "boom2"}")
27
+ a.whyrun("#{raise "boom3"}")
28
+ end
29
+ end
30
+ end
31
+
32
+ action :boom do
33
+ # nothing
34
+ end
35
+
36
+ action :noboom do
37
+ # nothing
38
+ end
39
+ end
40
+
41
+ let(:node) { Chef::Node.new }
42
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
43
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
44
+ let(:resource) { TestResource.new("name", run_context) }
45
+
46
+ it "raises an exception for an action where the assertions raise exceptions" do
47
+ expect { resource.run_action(:boom) }.to raise_error(StandardError, /boom2/)
48
+ end
49
+
50
+ it "does not raise an exception for an action which has no assertions" do
51
+ resource.run_action(:noboom)
52
+ end
53
+ end
@@ -392,6 +392,27 @@ describe Chef::Provider::Cron do
392
392
  expect(cron.command).to eq("/bin/true")
393
393
  end
394
394
  end
395
+
396
+ context "with a matching entry with a commented crontab line" do
397
+ it "should set cron_exists" do
398
+ allow(@provider).to receive(:read_crontab).and_return(<<~CRONTAB)
399
+ 0 2 * * * /some/other/command
400
+
401
+ # Chef Name: cronhole some stuff
402
+ #* * * * * /bin/true
403
+ CRONTAB
404
+ cron = @provider.load_current_resource
405
+ expect(@provider.cron_exists).to eq(true)
406
+ expect(@provider.cron_empty).to eq(false)
407
+ expect(cron.minute).to eq("*")
408
+ expect(cron.hour).to eq("*")
409
+ expect(cron.day).to eq("*")
410
+ expect(cron.month).to eq("*")
411
+ expect(cron.weekday).to eq("*")
412
+ expect(cron.time).to eq(nil)
413
+ expect(cron.property_is_set?(:command)).to eq(false)
414
+ end
415
+ end
395
416
  end
396
417
 
397
418
  describe "cron_different?" do
@@ -691,6 +712,30 @@ describe Chef::Provider::Cron do
691
712
  end
692
713
  end
693
714
 
715
+ context "when there is a crontab with a matching section with a commented crontab line in it" do
716
+ before :each do
717
+ @provider.cron_exists = true
718
+ end
719
+
720
+ it "should add the crontab to the entry" do
721
+ allow(@provider).to receive(:read_crontab).and_return(<<~CRONTAB)
722
+ 0 2 * * * /some/other/command
723
+
724
+ # Chef Name: cronhole some stuff
725
+ # * * * * * /bin/true
726
+ CRONTAB
727
+ expect(@provider).to receive(:write_crontab).with(<<~ENDCRON)
728
+ 0 2 * * * /some/other/command
729
+
730
+ # Chef Name: cronhole some stuff
731
+ * * * * * /bin/true
732
+ # * * * * * /bin/true
733
+ ENDCRON
734
+ @new_resource.minute "*"
735
+ @provider.run_action(:create)
736
+ end
737
+ end
738
+
694
739
  context "when there is a crontab with a matching and identical section" do
695
740
  context "when environment variable is not used" do
696
741
  before :each do
@@ -169,6 +169,7 @@ describe Chef::Provider::Group::Groupadd do
169
169
 
170
170
  before do
171
171
  allow(File).to receive(:exist?).and_return(false)
172
+ provider.action = :modify
172
173
  provider.define_resource_requirements
173
174
  end
174
175
 
@@ -58,18 +58,18 @@ describe Chef::Provider::Group::Usermod do
58
58
  end
59
59
 
60
60
  it "should raise an error when setting the entire group directly" do
61
+ @provider.action = :modify
61
62
  @provider.define_resource_requirements
62
63
  @provider.load_current_resource
63
64
  @provider.instance_variable_set("@group_exists", true)
64
- @provider.action = :modify
65
65
  expect { @provider.run_action(@provider.process_resource_requirements) }.to raise_error(Chef::Exceptions::Group, "setting group members directly is not supported by #{@provider}, must set append true in group")
66
66
  end
67
67
 
68
68
  it "should raise an error when excluded_members are set" do
69
+ @provider.action = :modify
69
70
  @provider.define_resource_requirements
70
71
  @provider.load_current_resource
71
72
  @provider.instance_variable_set("@group_exists", true)
72
- @provider.action = :modify
73
73
  @new_resource.append(true)
74
74
  @new_resource.excluded_members(["someone"])
75
75
  expect { @provider.run_action(@provider.process_resource_requirements) }.to raise_error(Chef::Exceptions::Group, "excluded_members is not supported by #{@provider}")
@@ -61,6 +61,7 @@ describe Chef::Provider::Ifconfig do
61
61
  expect(@provider.instance_variable_get("@status").exitstatus).not_to eq(0)
62
62
  end
63
63
  it "should thrown an exception when ifconfig fails" do
64
+ @provider.action = :add
64
65
  @provider.define_resource_requirements
65
66
  expect { @provider.process_resource_requirements }.to raise_error Chef::Exceptions::Ifconfig
66
67
  end
@@ -81,6 +82,7 @@ describe Chef::Provider::Ifconfig do
81
82
  expect(@provider.instance_variable_get("@status").exitstatus).not_to eq(0)
82
83
  end
83
84
  it "should thrown an exception when ifconfig fails" do
85
+ @provider.action = :add
84
86
  @provider.define_resource_requirements
85
87
  expect { @provider.process_resource_requirements }.to raise_error Chef::Exceptions::Ifconfig
86
88
  end
@@ -10,9 +10,9 @@ describe Chef::Provider::Mount::Linux do
10
10
 
11
11
  let(:new_resource) do
12
12
  new_resource = Chef::Resource::Mount.new("/tmp/foo")
13
- new_resource.device "/dev/sdz1"
13
+ new_resource.device "/dev/sdz1"
14
14
  new_resource.device_type :device
15
- new_resource.fstype "ext3"
15
+ new_resource.fstype "ext3"
16
16
  new_resource.supports remount: false
17
17
  new_resource
18
18
  end
@@ -32,6 +32,7 @@ describe Chef::Provider::Mount::Linux do
32
32
  context "to see if the volume is mounted" do
33
33
 
34
34
  it "should set mounted true if the mount point is found in the mounts list" do
35
+ allow(provider).to receive(:shell_out!).with("losetup --list").and_return(double(stdout: "/tmp/foo"))
35
36
  allow(provider).to receive(:shell_out!).and_return(double(stdout: "/tmp/foo /dev/sdz1 type ext3 (rw)\n"))
36
37
  provider.load_current_resource
37
38
  expect(provider.current_resource.mounted).to be_truthy
@@ -104,4 +105,16 @@ describe Chef::Provider::Mount::Linux do
104
105
  end
105
106
  end
106
107
 
107
- end
108
+ context "to check if loop resource is mounted" do
109
+ it "should set mounted true in case of loop resource" do
110
+ new_resource.options "loop"
111
+ mount = "/tmp/foo /dev/loop16 iso660 cifs ro\n"
112
+ losetup = "/dev/loop16 0 0 1 1 /dev/sdz1 \n"
113
+ allow(provider).to receive(:shell_out!).with("findmnt -rn").and_return(double(stdout: mount))
114
+ allow(provider).to receive(:shell_out!).with("losetup -a").and_return(double(stdout: losetup))
115
+ provider.load_current_resource
116
+ expect(provider.current_resource.mounted).to be_truthy
117
+ end
118
+ end
119
+
120
+ end
@@ -61,6 +61,7 @@ describe Chef::Provider::Package::Bff do
61
61
  allow(@provider).to receive(:shell_out_compacted).and_return(@empty_status)
62
62
  allow(::File).to receive(:exist?).with(@new_resource.source).and_return(false)
63
63
  @provider.load_current_resource
64
+ @provider.action = :install
64
65
  @provider.define_resource_requirements
65
66
  expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Package)
66
67
  end