chef 17.7.29 → 17.9.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -3
  3. data/README.md +1 -1
  4. data/lib/chef/application/base.rb +1 -1
  5. data/lib/chef/application/exit_code.rb +7 -21
  6. data/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb +1 -1
  7. data/lib/chef/chef_fs/file_system/repository/base_file.rb +1 -1
  8. data/lib/chef/chef_fs/file_system/repository/file_system_entry.rb +1 -1
  9. data/lib/chef/compliance/default_attributes.rb +12 -2
  10. data/lib/chef/compliance/input_collection.rb +1 -1
  11. data/lib/chef/compliance/runner.rb +51 -5
  12. data/lib/chef/compliance/waiver_collection.rb +1 -1
  13. data/lib/chef/cookbook/syntax_check.rb +1 -1
  14. data/lib/chef/cookbook_uploader.rb +1 -1
  15. data/lib/chef/cookbook_version.rb +1 -1
  16. data/lib/chef/mixin/powershell_exec.rb +6 -5
  17. data/lib/chef/mixin/why_run.rb +8 -2
  18. data/lib/chef/powershell.rb +8 -6
  19. data/lib/chef/provider/cron.rb +2 -2
  20. data/lib/chef/provider/directory.rb +2 -2
  21. data/lib/chef/provider/ifconfig.rb +5 -5
  22. data/lib/chef/provider/mount/linux.rb +16 -2
  23. data/lib/chef/provider/mount/mount.rb +1 -1
  24. data/lib/chef/provider/package/dnf.rb +1 -1
  25. data/lib/chef/provider/package/powershell.rb +13 -10
  26. data/lib/chef/provider/package/yum/python_helper.rb +81 -25
  27. data/lib/chef/provider/package/yum.rb +39 -12
  28. data/lib/chef/provider/package/zypper.rb +2 -0
  29. data/lib/chef/provider/package.rb +63 -28
  30. data/lib/chef/provider/user/mac.rb +3 -3
  31. data/lib/chef/provider.rb +5 -2
  32. data/lib/chef/providers.rb +0 -1
  33. data/lib/chef/pwsh.rb +3 -2
  34. data/lib/chef/resource/apt_package.rb +2 -2
  35. data/lib/chef/resource/chef_client_config.rb +21 -1
  36. data/lib/chef/resource/chef_client_launchd.rb +1 -1
  37. data/lib/chef/resource/chocolatey_package.rb +3 -3
  38. data/lib/chef/resource/cron/cron.rb +75 -1
  39. data/lib/chef/resource/cron/cron_d.rb +2 -1
  40. data/lib/chef/resource/dnf_package.rb +4 -6
  41. data/lib/chef/resource/dpkg_package.rb +5 -0
  42. data/lib/chef/resource/execute.rb +1 -4
  43. data/lib/chef/resource/habitat/habitat_sup.rb +1 -1
  44. data/lib/chef/resource/habitat/habitat_sup_windows.rb +1 -1
  45. data/lib/chef/resource/homebrew_tap.rb +1 -5
  46. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  47. data/lib/chef/resource/launchd.rb +2 -5
  48. data/lib/chef/resource/lwrp_base.rb +1 -1
  49. data/lib/chef/resource/macos_userdefaults.rb +5 -7
  50. data/lib/chef/resource/powershell_package_source.rb +8 -8
  51. data/lib/chef/resource/remote_file.rb +1 -1
  52. data/lib/chef/resource/rhsm_register.rb +31 -0
  53. data/lib/chef/resource/support/client.erb +7 -0
  54. data/lib/chef/resource/windows_feature_powershell.rb +8 -9
  55. data/lib/chef/resource/windows_task.rb +25 -10
  56. data/lib/chef/resource.rb +3 -3
  57. data/lib/chef/resource_reporter.rb +1 -1
  58. data/lib/chef/run_lock.rb +1 -1
  59. data/lib/chef/secret_fetcher/azure_key_vault.rb +4 -2
  60. data/lib/chef/secret_fetcher/hashi_vault.rb +37 -3
  61. data/lib/chef/util/dsc/configuration_generator.rb +1 -1
  62. data/lib/chef/version.rb +1 -1
  63. data/spec/functional/resource/cookbook_file_spec.rb +1 -1
  64. data/spec/functional/resource/dnf_package_spec.rb +138 -124
  65. data/spec/functional/resource/dpkg_package_spec.rb +16 -0
  66. data/spec/functional/resource/dsc_script_spec.rb +2 -2
  67. data/spec/functional/resource/macos_userdefaults_spec.rb +20 -0
  68. data/spec/functional/resource/template_spec.rb +1 -1
  69. data/spec/functional/resource/yum_package_spec.rb +789 -129
  70. data/spec/functional/resource/zypper_package_spec.rb +7 -0
  71. data/spec/integration/client/client_spec.rb +32 -1
  72. data/spec/spec_helper.rb +3 -3
  73. data/spec/support/platform_helpers.rb +1 -1
  74. data/spec/support/ruby_installer.rb +1 -1
  75. data/spec/support/shared/functional/file_resource.rb +2 -2
  76. data/spec/support/shared/functional/http.rb +9 -9
  77. data/spec/support/shared/unit/provider/useradd_based_user_provider.rb +1 -1
  78. data/spec/unit/application/base_spec.rb +40 -0
  79. data/spec/unit/compliance/runner_spec.rb +62 -1
  80. data/spec/unit/dsl/registry_helper_spec.rb +6 -6
  81. data/spec/unit/file_access_control_spec.rb +1 -1
  82. data/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb +1 -1
  83. data/spec/unit/lwrp_spec.rb +2 -2
  84. data/spec/unit/mixin/why_run_spec.rb +53 -0
  85. data/spec/unit/provider/dsc_script_spec.rb +8 -8
  86. data/spec/unit/provider/group/groupadd_spec.rb +1 -0
  87. data/spec/unit/provider/group/usermod_spec.rb +4 -4
  88. data/spec/unit/provider/ifconfig/aix_spec.rb +14 -14
  89. data/spec/unit/provider/ifconfig/debian_spec.rb +1 -1
  90. data/spec/unit/provider/ifconfig/redhat_spec.rb +1 -1
  91. data/spec/unit/provider/ifconfig_spec.rb +5 -3
  92. data/spec/unit/provider/mount/linux_spec.rb +16 -3
  93. data/spec/unit/provider/package/bff_spec.rb +1 -0
  94. data/spec/unit/provider/package/powershell_spec.rb +114 -114
  95. data/spec/unit/provider/package/rubygems_spec.rb +3 -0
  96. data/spec/unit/provider/package/solaris_spec.rb +1 -0
  97. data/spec/unit/provider/remote_file/cache_control_data_spec.rb +3 -3
  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 +3 -2
  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/upstart_service_spec.rb +3 -3
  105. data/spec/unit/provider/user/solaris_spec.rb +1 -1
  106. data/spec/unit/provider/user_spec.rb +2 -0
  107. data/spec/unit/resource/conditional_spec.rb +4 -4
  108. data/spec/unit/resource/dpkg_package_spec.rb +12 -0
  109. data/spec/unit/resource/rhsm_register_spec.rb +42 -0
  110. data/spec/unit/resource_spec.rb +2 -2
  111. data/spec/unit/secret_fetcher/hashi_vault_spec.rb +46 -0
  112. metadata +9 -9
  113. data/lib/chef/provider/group/suse.rb +0 -82
  114. data/spec/unit/provider/group/suse_spec.rb +0 -90
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c14c01fc55c7847b27979c41e01be0dd845b69840fc048e7abeb8787156bae23
4
- data.tar.gz: 44676d2fe03cc4306efaa4c33f48a9eb3e2d6d736962bcd441ffc4bd0c371621
3
+ metadata.gz: 81905931cf4ca87528c65bb2be19f6656fcbf6754612da872f3c74e9c0e8753f
4
+ data.tar.gz: 75e630d0ac718daabb1854788c2428b765ea05229a25a21974812b5e4063a30a
5
5
  SHA512:
6
- metadata.gz: 768707842ce349798c256c91d2202c5c7b7f931d63ca53eb9454ed6b424f3a11b38b2c9b94c4c4177959ff179029831a9cca3d3233afa5d2ba7dcd90afba3c23
7
- data.tar.gz: 9a3a715294581c43a663387a3462c745d6bab3a44736ab9bf87e607cfa5cfa7a920de90a918225e05b08a8962b52103c792d97b586d69ef32023afb1e45dc11c
6
+ metadata.gz: db10283eb9a37f5b8dfd7223583eba74dc536277de8c5d424872c66b36102b505b07de211e9cd6022aa03d371339ebbc97846f5d3e534bbdf10896bde43fcb7a
7
+ data.tar.gz: 5bcaf6a2182e345138d53e67967a5b956c4bcdfd700f8c8b35994a15d71a0e5ed87a8327ccc6a7cb690b52c8c4043db1df65f16509b6268d7bc2a8169ef76875
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem "chef", path: "."
4
4
 
5
- gem "ohai", git: "https://github.com/chef/ohai.git", branch: "main"
5
+ gem "ohai", git: "https://github.com/chef/ohai.git", branch: "17-stable"
6
6
 
7
7
  gem "chef-utils", path: File.expand_path("chef-utils", __dir__) if File.exist?(File.expand_path("chef-utils", __dir__))
8
8
  gem "chef-config", path: File.expand_path("chef-config", __dir__) if File.exist?(File.expand_path("chef-config", __dir__))
@@ -15,7 +15,7 @@ else
15
15
  gem "chef-bin" # rubocop:disable Bundler/DuplicatedGem
16
16
  end
17
17
 
18
- gem "cheffish", ">= 17"
18
+ gem "cheffish", "~> 17.0"
19
19
 
20
20
  group(:omnibus_package) do
21
21
  gem "appbundler"
@@ -29,7 +29,7 @@ group(:omnibus_package, :pry) do
29
29
  # some work is ongoing? https://github.com/deivid-rodriguez/pry-byebug/issues/343
30
30
  gem "pry", "= 0.13.0"
31
31
  # byebug does not install on freebsd on ruby 3.0
32
- gem "pry-byebug" unless RUBY_PLATFORM =~ /freebsd/i
32
+ gem "pry-byebug" unless RUBY_PLATFORM.match?(/freebsd/i)
33
33
  gem "pry-stack_explorer"
34
34
  end
35
35
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Chef Infra
2
2
  [![Code Climate](https://codeclimate.com/github/chef/chef.svg)](https://codeclimate.com/github/chef/chef)
3
- [![Build Status](https://badge.buildkite.com/c82093430ceec7d27af05febb9dcafe3aa331fff9d74c0ab9d.svg?branch=master)](https://buildkite.com/chef-oss/chef-chef-master-verify)
3
+ [![Build Status](https://badge.buildkite.com/c82093430ceec7d27af05febb9dcafe3aa331fff9d74c0ab9d.svg?branch=chef-17)](https://buildkite.com/chef-oss/chef-chef-chef-17-verify)
4
4
  [![Gem Version](https://badge.fury.io/rb/chef.svg)](https://badge.fury.io/rb/chef)
5
5
  [![](https://img.shields.io/badge/Release%20Policy-Cadence%20Release-brightgreen.svg)](https://github.com/chef/chef/blob/master/docs/dev/design_documents/client_release_cadence.md)
6
6
 
@@ -254,7 +254,7 @@ class Chef::Application::Base < Chef::Application
254
254
  short: "-K KEY_FILE",
255
255
  long: "--validation_key KEY_FILE",
256
256
  description: "Set the validation key file location, used for registering new clients.",
257
- proc: nil
257
+ proc: lambda { |argument| File.expand_path(argument) }
258
258
 
259
259
  option :client_key,
260
260
  short: "-k KEY_FILE",
@@ -90,45 +90,31 @@ class Chef
90
90
  end
91
91
 
92
92
  def reboot_scheduled?(exception)
93
- resolve_exception_array(exception).any? do |e|
94
- e.is_a? Chef::Exceptions::Reboot
95
- end
93
+ resolve_exception_array(exception).any?(Chef::Exceptions::Reboot)
96
94
  end
97
95
 
98
96
  def reboot_needed?(exception)
99
- resolve_exception_array(exception).any? do |e|
100
- e.is_a? Chef::Exceptions::RebootPending
101
- end
97
+ resolve_exception_array(exception).any?(Chef::Exceptions::RebootPending)
102
98
  end
103
99
 
104
100
  def reboot_failed?(exception)
105
- resolve_exception_array(exception).any? do |e|
106
- e.is_a? Chef::Exceptions::RebootFailed
107
- end
101
+ resolve_exception_array(exception).any?(Chef::Exceptions::RebootFailed)
108
102
  end
109
103
 
110
104
  def configuration_failure?(exception)
111
- resolve_exception_array(exception).any? do |e|
112
- e.is_a? Chef::Exceptions::ConfigurationError
113
- end
105
+ resolve_exception_array(exception).any?(Chef::Exceptions::ConfigurationError)
114
106
  end
115
107
 
116
108
  def client_upgraded?(exception)
117
- resolve_exception_array(exception).any? do |e|
118
- e.is_a? Chef::Exceptions::ClientUpgraded
119
- end
109
+ resolve_exception_array(exception).any?(Chef::Exceptions::ClientUpgraded)
120
110
  end
121
111
 
122
112
  def sigint_received?(exception)
123
- resolve_exception_array(exception).any? do |e|
124
- e.is_a? Chef::Exceptions::SigInt
125
- end
113
+ resolve_exception_array(exception).any?(Chef::Exceptions::SigInt)
126
114
  end
127
115
 
128
116
  def sigterm_received?(exception)
129
- resolve_exception_array(exception).any? do |e|
130
- e.is_a? Chef::Exceptions::SigTerm
131
- end
117
+ resolve_exception_array(exception).any?(Chef::Exceptions::SigTerm)
132
118
  end
133
119
 
134
120
  def resolve_exception_array(exception)
@@ -38,7 +38,7 @@ class Chef
38
38
 
39
39
  def read
40
40
  tmpfile = rest.streaming_request(file[:url])
41
- File.open(tmpfile, "rb", &:read)
41
+ File.binread(tmpfile)
42
42
  rescue Timeout::Error => e
43
43
  raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "Timeout reading #{file[:url]}: #{e}")
44
44
  rescue Net::HTTPClientException => e
@@ -123,7 +123,7 @@ class Chef
123
123
  if is_ruby_file?
124
124
  data_handler.from_ruby(file_path).to_json
125
125
  else
126
- File.open(file_path, "rb", &:read)
126
+ File.binread(file_path)
127
127
  end
128
128
  rescue Errno::ENOENT
129
129
  raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
@@ -126,7 +126,7 @@ class Chef
126
126
  end
127
127
 
128
128
  def read
129
- File.open(file_path, "rb", &:read)
129
+ File.binread(file_path)
130
130
  rescue Errno::ENOENT
131
131
  raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
132
132
  end
@@ -28,7 +28,7 @@ class Chef
28
28
  # Controls what is done with the resulting report after the Chef InSpec run.
29
29
  # Accepts a single string value or an array of multiple values.
30
30
  # Accepted values: 'chef-server-automate', 'chef-automate', 'json-file', 'audit-enforcer', 'cli'
31
- "reporter" => "cli",
31
+ "reporter" => nil,
32
32
 
33
33
  # Controls if Chef InSpec profiles should be fetched from Chef Automate or Chef Infra Server
34
34
  # in addition to the default fetch locations provided by Chef Inspec.
@@ -94,7 +94,17 @@ class Chef
94
94
 
95
95
  # Should the built-in compliance phase run. True and false force the behavior. Nil does magic based on if you have
96
96
  # profiles defined but do not have the audit cookbook enabled.
97
- "compliance_phase" => false
97
+ "compliance_phase" => false,
98
+
99
+ "interval" => {
100
+ # control how often inspec scans are run, if not on every node converge
101
+ # notes: false value will result in running inspec scan every converge
102
+ "enabled" => false,
103
+
104
+ # controls how often inspec scans are run (in minutes)
105
+ # notes: only used if interval is enabled above
106
+ "time" => 1440,
107
+ }
98
108
  )
99
109
  end
100
110
  end
@@ -57,7 +57,7 @@ class Chef
57
57
  # @return [Array<Input>] inspec inputs which are enabled in a form suitable to pass to inspec
58
58
  #
59
59
  def inspec_data
60
- select(&:enabled?).each_with_object({}) { |input, hash| hash.merge(input.inspec_data) }
60
+ select(&:enabled?).each_with_object({}) { |input, hash| hash.merge!(input.inspec_data) }
61
61
  end
62
62
 
63
63
  # DSL method to enable input files. This matches on the filename of the input file.
@@ -71,7 +71,7 @@ class Chef
71
71
 
72
72
  logger.debug("#{self.class}##{__method__}: enabling Compliance Phase")
73
73
 
74
- report
74
+ report_with_interval
75
75
  end
76
76
 
77
77
  def run_failed(_exception, _run_status)
@@ -82,7 +82,7 @@ class Chef
82
82
 
83
83
  logger.debug("#{self.class}##{__method__}: enabling Compliance Phase")
84
84
 
85
- report
85
+ report_with_interval
86
86
  end
87
87
 
88
88
  ### Below code adapted from audit cookbook's files/default/handler/audit_report.rb
@@ -92,7 +92,6 @@ class Chef
92
92
  fail_if_not_present
93
93
  inspec_gem_source
94
94
  inspec_version
95
- interval
96
95
  owner
97
96
  raise_if_unreachable
98
97
  }.freeze
@@ -106,6 +105,15 @@ class Chef
106
105
  end
107
106
  end
108
107
 
108
+ def report_with_interval
109
+ if interval_seconds_left <= 0
110
+ create_timestamp_file if interval_enabled
111
+ report
112
+ else
113
+ logger.info "Skipping Chef Infra Compliance Phase due to interval settings (next run in #{interval_seconds_left / 60.0} mins)"
114
+ end
115
+ end
116
+
109
117
  def report(report = nil)
110
118
  logger.info "Starting Chef Infra Compliance Phase"
111
119
  report ||= generate_report
@@ -118,7 +126,7 @@ class Chef
118
126
  return
119
127
  end
120
128
 
121
- Array(node["audit"]["reporter"]).each do |reporter_type|
129
+ requested_reporters.each do |reporter_type|
122
130
  logger.info "Reporting to #{reporter_type}"
123
131
  @reporters[reporter_type].send_report(report)
124
132
  end
@@ -325,7 +333,7 @@ class Chef
325
333
  @reporters = {}
326
334
  # Note that the docs don't say you can use an array, but our implementation
327
335
  # supports it.
328
- Array(node["audit"]["reporter"]).each do |type|
336
+ requested_reporters.each do |type|
329
337
  unless SUPPORTED_REPORTERS.include? type
330
338
  raise "CMPL003: '#{type}' found in node['audit']['reporter'] is not a supported reporter for Compliance Phase. Supported reporters are: #{SUPPORTED_REPORTERS.join(", ")}. For more information, see the documentation at https://docs.chef.io/chef_compliance_phase#reporters"
331
339
  end
@@ -358,6 +366,44 @@ class Chef
358
366
  def safe_input_collection
359
367
  run_context&.input_collection
360
368
  end
369
+
370
+ def requested_reporters
371
+ (Array(node["audit"]["reporter"]) + ["cli"]).uniq
372
+ end
373
+
374
+ def create_timestamp_file
375
+ FileUtils.touch report_timing_file
376
+ end
377
+
378
+ def report_timing_file
379
+ ::File.join(Chef::FileCache.create_cache_path("compliance"), "report_timing.json")
380
+ end
381
+
382
+ def interval_time
383
+ @interval_time ||= node.read("audit", "interval", "time")
384
+ end
385
+
386
+ def interval_enabled
387
+ @interval_enabled ||= node.read("audit", "interval", "enabled")
388
+ end
389
+
390
+ def interval_seconds
391
+ @interval_seconds ||=
392
+ if interval_enabled
393
+ logger.debug "Running Chef Infra Compliance Phase every #{interval_time} minutes"
394
+ interval_time * 60
395
+ else
396
+ logger.debug "Running Chef Infra Compliance Phase on every run"
397
+ 0
398
+ end
399
+ end
400
+
401
+ def interval_seconds_left
402
+ return 0 unless ::File.exist?(report_timing_file)
403
+
404
+ seconds_since_last_run = Time.now - ::File.mtime(report_timing_file)
405
+ interval_seconds - seconds_since_last_run
406
+ end
361
407
  end
362
408
  end
363
409
  end
@@ -57,7 +57,7 @@ class Chef
57
57
  # @return [Array<Waiver>] inspec waivers which are enabled in a form suitable to pass to inspec
58
58
  #
59
59
  def inspec_data
60
- select(&:enabled?).each_with_object({}) { |waiver, hash| hash.merge(waiver.inspec_data) }
60
+ select(&:enabled?).each_with_object({}) { |waiver, hash| hash.merge!(waiver.inspec_data) }
61
61
  end
62
62
 
63
63
  # DSL method to enable waiver files. This matches on the filename of the waiver file.
@@ -113,7 +113,7 @@ class Chef
113
113
  end
114
114
 
115
115
  def remove_uninteresting_ruby_files(file_list)
116
- file_list.reject { |f| f =~ %r{#{Regexp.quote(cookbook_path)}/(files|templates)/} }
116
+ file_list.grep_v(%r{#{Regexp.quote(cookbook_path)}/(files|templates)/})
117
117
  end
118
118
 
119
119
  def ruby_files
@@ -119,7 +119,7 @@ class Chef
119
119
  # but we need the base64 encoding for the content-md5
120
120
  # header
121
121
  checksum64 = Base64.encode64([checksum].pack("H*")).strip
122
- file_contents = File.open(file, "rb", &:read)
122
+ file_contents = File.binread(file)
123
123
 
124
124
  # Custom headers. 'content-type' disables JSON serialization of the request body.
125
125
  headers = { "content-type" => "application/x-binary", "content-md5" => checksum64, "accept" => "application/json" }
@@ -598,7 +598,7 @@ class Chef
598
598
  filename = record[:name]
599
599
  base_dup_name = File.join(File.dirname(filename), File.basename(filename, File.extname(filename)))
600
600
  yml_files.each do |other|
601
- if other[:name] =~ /#{(File.extname(filename) == ".yml") ? "#{base_dup_name}.yaml" : "#{base_dup_name}.yml"}$/
601
+ if /#{(File.extname(filename) == ".yml") ? "#{base_dup_name}.yaml" : "#{base_dup_name}.yml"}$/.match?(other[:name])
602
602
  raise Chef::Exceptions::AmbiguousYAMLFile.new("Cookbook #{name}@#{version} contains ambiguous files: #{filename} and #{other[:name]}. Please update the cookbook to remove the incorrect file.")
603
603
  end
604
604
  end
@@ -104,13 +104,14 @@ class Chef
104
104
  #
105
105
  # @param script [String] script to run
106
106
  # @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
107
+ # @param timeout [Integer, nil] timeout in seconds.
107
108
  # @return [Chef::PowerShell] output
108
- def powershell_exec(script, interpreter = :powershell)
109
+ def powershell_exec(script, interpreter = :powershell, timeout: -1)
109
110
  case interpreter
110
111
  when :powershell
111
- Chef::PowerShell.new(script)
112
+ Chef::PowerShell.new(script, timeout: timeout)
112
113
  when :pwsh
113
- Chef::Pwsh.new(script)
114
+ Chef::Pwsh.new(script, timeout: timeout)
114
115
  else
115
116
  raise ArgumentError, "Expected interpreter of :powershell or :pwsh"
116
117
  end
@@ -118,8 +119,8 @@ class Chef
118
119
 
119
120
  # The same as the #powershell_exec method except this will raise
120
121
  # Chef::PowerShell::CommandFailed if the command fails
121
- def powershell_exec!(script, interpreter = :powershell)
122
- cmd = powershell_exec(script, interpreter)
122
+ def powershell_exec!(script, interpreter = :powershell, **options)
123
+ cmd = powershell_exec(script, interpreter, **options)
123
124
  cmd.error!
124
125
  cmd
125
126
  end
@@ -242,8 +242,12 @@ class Chef
242
242
  end
243
243
  end
244
244
 
245
- def initialize(resource, run_context)
246
- @resource, @run_context = resource, run_context
245
+ attr_accessor :action
246
+
247
+ def initialize(resource, run_context, action)
248
+ @resource = resource
249
+ @run_context = run_context
250
+ @action = action
247
251
  @assertions = Hash.new { |h, k| h[k] = [] }
248
252
  @blocked_actions = []
249
253
  end
@@ -305,6 +309,8 @@ class Chef
305
309
  # "You don't have sufficient privileges to delete #{@new_resource.path}")
306
310
  # end
307
311
  def assert(*actions)
312
+ return unless actions.include?(action.to_sym) || actions.include?(:all_actions)
313
+
308
314
  assertion = Assertion.new
309
315
  yield assertion
310
316
  actions.each { |action| @assertions[action] << assertion }
@@ -33,15 +33,16 @@ class Chef
33
33
  # Requires: .NET Framework 4.0 or higher on the target machine.
34
34
  #
35
35
  # @param script [String] script to run
36
+ # @param timeout [Integer, nil] timeout in seconds.
36
37
  # @return [Object] output
37
- def initialize(script)
38
+ def initialize(script, timeout: -1)
38
39
  # This Powershell DLL source lives here: https://github.com/chef/chef-powershell-shim
39
40
  # Every merge into that repo triggers a Habitat build and promotion. Running
40
41
  # the rake :update_chef_exec_dll task in this (chef/chef) repo will pull down
41
42
  # the built packages and copy the binaries to distro/ruby_bin_folder. Bundle install
42
43
  # ensures that the correct architecture binaries are installed into the path.
43
44
  @dll ||= "Chef.PowerShell.Wrapper.dll"
44
- exec(script)
45
+ exec(script, timeout: timeout)
45
46
  end
46
47
 
47
48
  #
@@ -64,12 +65,13 @@ class Chef
64
65
  raise Chef::PowerShell::CommandFailed, "Unexpected exit in PowerShell command: #{@errors}" if error?
65
66
  end
66
67
 
67
- protected
68
+ private
68
69
 
69
- def exec(script)
70
+ def exec(script, timeout: -1)
70
71
  FFI.ffi_lib @dll
71
- FFI.attach_function :execute_powershell, :ExecuteScript, [:string], :pointer
72
- execution = FFI.execute_powershell(script).read_utf16string
72
+ FFI.attach_function :execute_powershell, :ExecuteScript, %i{string int}, :pointer
73
+ timeout = -1 if timeout == 0 || timeout.nil?
74
+ execution = FFI.execute_powershell(script, timeout).read_utf16string
73
75
  hashed_outcome = Chef::JSONCompat.parse(execution)
74
76
  @result = Chef::JSONCompat.parse(hashed_outcome["result"])
75
77
  @errors = hashed_outcome["errors"]
@@ -92,7 +92,7 @@ class Chef
92
92
  end
93
93
  end
94
94
 
95
- action :create do
95
+ action :create, description: "Create an entry in a cron table file (crontab). If an entry already exists (but does not match), update that entry to match." do
96
96
  crontab = ""
97
97
  newcron = ""
98
98
  cron_found = false
@@ -149,7 +149,7 @@ class Chef
149
149
  end
150
150
  end
151
151
 
152
- action :delete do
152
+ action :delete, description: "Delete an entry from a cron table file (crontab)." do
153
153
  if @cron_exists
154
154
  crontab = ""
155
155
  cron_found = false
@@ -121,7 +121,7 @@ class Chef
121
121
  end
122
122
  end
123
123
 
124
- action :create do
124
+ action :create, description: "Create a directory. If a directory already exists (but does not match), update that directory to match." do
125
125
  unless ::File.exist?(new_resource.path)
126
126
  converge_by("create new directory #{new_resource.path}") do
127
127
  if new_resource.recursive == true
@@ -137,7 +137,7 @@ class Chef
137
137
  load_resource_attributes_from_file(new_resource) unless Chef::Config[:why_run]
138
138
  end
139
139
 
140
- action :delete do
140
+ action :delete, description: "Delete a directory." do
141
141
  if ::File.exist?(new_resource.path)
142
142
  converge_by("delete existing directory #{new_resource.path}") do
143
143
  if new_resource.recursive == true
@@ -120,7 +120,7 @@ class Chef
120
120
  @status = shell_out("ifconfig")
121
121
  @status.stdout.each_line do |line|
122
122
  addr_regex = /^((\w|-)+):?(\d*):?\ .+$/
123
- if line =~ addr_regex
123
+ if line&.match?(addr_regex)
124
124
  if line.match(addr_regex).nil?
125
125
  @int_name = "nil"
126
126
  elsif line.match(addr_regex)[3] == ""
@@ -168,7 +168,7 @@ class Chef
168
168
  end
169
169
  end
170
170
 
171
- action :add do
171
+ action :add, description: "Run ifconfig to configure a network interface and (on some platforms) write a configuration file for that network interface." do
172
172
  # check to see if load_current_resource found interface in ifconfig
173
173
  unless current_resource.inet_addr
174
174
  unless new_resource.device == loopback_device
@@ -183,7 +183,7 @@ class Chef
183
183
  generate_config
184
184
  end
185
185
 
186
- action :enable do
186
+ action :enable, description: "Run ifconfig to enable a network interface." do
187
187
  # check to see if load_current_resource found ifconfig
188
188
  # enables, but does not manage config files
189
189
  return if current_resource.inet_addr
@@ -196,7 +196,7 @@ class Chef
196
196
  end
197
197
  end
198
198
 
199
- action :delete do
199
+ action :delete, description: "Run ifconfig to disable a network interface and (on some platforms) delete that network interface’s configuration file." do
200
200
  # check to see if load_current_resource found the interface
201
201
  if current_resource.device
202
202
  command = delete_command
@@ -210,7 +210,7 @@ class Chef
210
210
  delete_config
211
211
  end
212
212
 
213
- action :disable do
213
+ action :disable, description: "Run ifconfig to disable a network interface." do
214
214
  # check to see if load_current_resource found the interface
215
215
  # disables, but leaves config files in place.
216
216
  if current_resource.device
@@ -29,10 +29,16 @@ class Chef
29
29
  # "findmnt" outputs the mount points with volume.
30
30
  # Convert the mount_point of the resource to a real path in case it
31
31
  # contains symlinks in its parents dirs.
32
+ def loop_mount_points
33
+ # get loop_mount_points only if not initialized earlier
34
+ @loop_mount_points ||= shell_out!("losetup -a").stdout
35
+
36
+ rescue Errno::ENOENT
37
+ @loop_mount_points = ""
38
+ end
32
39
 
33
40
  def mounted?
34
41
  mounted = false
35
-
36
42
  real_mount_point = if ::File.exists? @new_resource.mount_point
37
43
  ::File.realpath(@new_resource.mount_point)
38
44
  else
@@ -45,6 +51,14 @@ class Chef
45
51
  when /\A#{Regexp.escape(real_mount_point)}\s+#{device_mount_regex}\s/
46
52
  mounted = true
47
53
  logger.trace("Special device #{device_logstring} mounted as #{real_mount_point}")
54
+ # Permalink for loop type devices mount points https://rubular.com/r/a0bS4p2RvXsGxx
55
+ when %r{\A#{Regexp.escape(real_mount_point)}\s+\/dev\/loop+[0-9]+\s}
56
+ loop_mount_points.each_line do |mount_point|
57
+ if mount_point.include? device_real
58
+ mounted = true
59
+ break
60
+ end
61
+ end
48
62
  # Permalink for multiple devices mounted to the same mount point(i.e. '/proc') https://rubular.com/r/a356yzspU7N9TY
49
63
  when %r{\A#{Regexp.escape(real_mount_point)}\s+([/\w])+\s}
50
64
  mounted = false
@@ -64,4 +78,4 @@ class Chef
64
78
  end
65
79
  end
66
80
  end
67
- end
81
+ end
@@ -279,4 +279,4 @@ class Chef
279
279
  end
280
280
  end
281
281
  end
282
- end
282
+ end
@@ -98,7 +98,7 @@ class Chef
98
98
  end
99
99
  end
100
100
 
101
- def magic_version
101
+ def magic_version_array
102
102
  package_name_array.each_with_index.map do |pkg, i|
103
103
  magical_version(i).version_with_arch
104
104
  end
@@ -17,13 +17,13 @@
17
17
 
18
18
  require_relative "../package"
19
19
  require_relative "../../resource/powershell_package"
20
- require_relative "../../mixin/powershell_out"
20
+ require_relative "../../mixin/powershell_exec"
21
21
 
22
22
  class Chef
23
23
  class Provider
24
24
  class Package
25
25
  class Powershell < Chef::Provider::Package
26
- include Chef::Mixin::PowershellOut
26
+ include Chef::Mixin::PowershellExec
27
27
 
28
28
  provides :powershell_package
29
29
 
@@ -54,9 +54,9 @@ class Chef
54
54
  # Installs the package specified with the version passed else latest version will be installed
55
55
  def install_package(names, versions)
56
56
  names.each_with_index do |name, index|
57
- cmd = powershell_out(build_powershell_package_command("Install-Package '#{name}'", versions[index]), timeout: new_resource.timeout)
57
+ cmd = powershell_exec(build_powershell_package_command("Install-Package '#{name}'", versions[index]), timeout: new_resource.timeout)
58
58
  next if cmd.nil?
59
- raise Chef::Exceptions::PowershellCmdletException, "Failed to install package due to catalog signing error, use skip_publisher_check to force install" if /SkipPublisherCheck/.match?(cmd.stderr)
59
+ raise Chef::Exceptions::PowershellCmdletException, "Failed to install package due to catalog signing error, use skip_publisher_check to force install" if /SkipPublisherCheck/.match?(cmd.error)
60
60
  end
61
61
  end
62
62
 
@@ -64,11 +64,12 @@ class Chef
64
64
  def remove_package(names, versions)
65
65
  names.each_with_index do |name, index|
66
66
  if versions && !versions[index].nil?
67
- powershell_out(build_powershell_package_command("Uninstall-Package '#{name}'", versions[index]), timeout: new_resource.timeout)
67
+ powershell_exec(build_powershell_package_command("Uninstall-Package '#{name}'", versions[index]), timeout: new_resource.timeout)
68
68
  else
69
69
  version = "0"
70
70
  until version.empty?
71
- version = powershell_out(build_powershell_package_command("Uninstall-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip
71
+ version = powershell_exec(build_powershell_package_command("Uninstall-Package '#{name}'"), timeout: new_resource.timeout).result
72
+ version = version.strip if version.respond_to?(:strip)
72
73
  unless version.empty?
73
74
  logger.info("Removed package '#{name}' with version #{version}")
74
75
  end
@@ -82,13 +83,14 @@ class Chef
82
83
  versions = []
83
84
  new_resource.package_name.each_with_index do |name, index|
84
85
  version = if new_resource.version && !new_resource.version[index].nil?
85
- powershell_out(build_powershell_package_command("Find-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).stdout.strip
86
+ powershell_exec(build_powershell_package_command("Find-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).result
86
87
  else
87
- powershell_out(build_powershell_package_command("Find-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip
88
+ powershell_exec(build_powershell_package_command("Find-Package '#{name}'"), timeout: new_resource.timeout).result
88
89
  end
89
90
  if version.empty?
90
91
  version = nil
91
92
  end
93
+ version = version.strip if version.respond_to?(:strip)
92
94
  versions.push(version)
93
95
  end
94
96
  versions
@@ -99,13 +101,14 @@ class Chef
99
101
  version_list = []
100
102
  new_resource.package_name.each_with_index do |name, index|
101
103
  version = if new_resource.version && !new_resource.version[index].nil?
102
- powershell_out(build_powershell_package_command("Get-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).stdout.strip
104
+ powershell_exec(build_powershell_package_command("Get-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).result
103
105
  else
104
- powershell_out(build_powershell_package_command("Get-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip
106
+ powershell_exec(build_powershell_package_command("Get-Package '#{name}'"), timeout: new_resource.timeout).result
105
107
  end
106
108
  if version.empty?
107
109
  version = nil
108
110
  end
111
+ version = version.strip if version.respond_to?(:strip)
109
112
  version_list.push(version)
110
113
  end
111
114
  version_list