chef 17.7.22 → 17.9.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/lib/chef/application/base.rb +1 -1
  4. data/lib/chef/application/exit_code.rb +7 -21
  5. data/lib/chef/compliance/default_attributes.rb +12 -2
  6. data/lib/chef/compliance/runner.rb +51 -5
  7. data/lib/chef/cookbook/syntax_check.rb +1 -1
  8. data/lib/chef/cookbook_version.rb +1 -1
  9. data/lib/chef/mixin/powershell_exec.rb +6 -5
  10. data/lib/chef/mixin/why_run.rb +8 -2
  11. data/lib/chef/powershell.rb +8 -6
  12. data/lib/chef/provider/cron.rb +2 -2
  13. data/lib/chef/provider/directory.rb +2 -2
  14. data/lib/chef/provider/ifconfig.rb +5 -5
  15. data/lib/chef/provider/mount/linux.rb +16 -2
  16. data/lib/chef/provider/mount/mount.rb +1 -1
  17. data/lib/chef/provider/package/dnf.rb +1 -1
  18. data/lib/chef/provider/package/habitat.rb +1 -1
  19. data/lib/chef/provider/package/powershell.rb +13 -10
  20. data/lib/chef/provider/package/yum/python_helper.rb +81 -25
  21. data/lib/chef/provider/package/yum.rb +39 -12
  22. data/lib/chef/provider/package/zypper.rb +2 -0
  23. data/lib/chef/provider/package.rb +63 -28
  24. data/lib/chef/provider/user/mac.rb +3 -3
  25. data/lib/chef/provider.rb +5 -2
  26. data/lib/chef/providers.rb +0 -1
  27. data/lib/chef/pwsh.rb +3 -2
  28. data/lib/chef/resource/apt_package.rb +2 -2
  29. data/lib/chef/resource/chef_client_config.rb +21 -1
  30. data/lib/chef/resource/chef_client_launchd.rb +1 -1
  31. data/lib/chef/resource/chef_client_trusted_certificate.rb +1 -0
  32. data/lib/chef/resource/chocolatey_package.rb +3 -3
  33. data/lib/chef/resource/cron/cron.rb +75 -1
  34. data/lib/chef/resource/cron/cron_d.rb +2 -1
  35. data/lib/chef/resource/dnf_package.rb +4 -6
  36. data/lib/chef/resource/dpkg_package.rb +5 -0
  37. data/lib/chef/resource/execute.rb +1 -4
  38. data/lib/chef/resource/habitat/habitat_sup.rb +1 -1
  39. data/lib/chef/resource/habitat/habitat_sup_windows.rb +1 -1
  40. data/lib/chef/resource/habitat_install.rb +2 -2
  41. data/lib/chef/resource/homebrew_tap.rb +1 -5
  42. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  43. data/lib/chef/resource/launchd.rb +2 -5
  44. data/lib/chef/resource/macos_userdefaults.rb +25 -30
  45. data/lib/chef/resource/powershell_package_source.rb +8 -8
  46. data/lib/chef/resource/remote_file.rb +1 -1
  47. data/lib/chef/resource/rhsm_register.rb +31 -0
  48. data/lib/chef/resource/support/client.erb +7 -0
  49. data/lib/chef/resource/windows_feature_powershell.rb +8 -9
  50. data/lib/chef/resource/windows_task.rb +25 -10
  51. data/lib/chef/resource.rb +3 -3
  52. data/lib/chef/resource_reporter.rb +1 -1
  53. data/lib/chef/run_lock.rb +1 -1
  54. data/lib/chef/secret_fetcher/azure_key_vault.rb +4 -2
  55. data/lib/chef/secret_fetcher/hashi_vault.rb +37 -3
  56. data/lib/chef/version.rb +1 -1
  57. data/spec/functional/resource/dnf_package_spec.rb +138 -124
  58. data/spec/functional/resource/dpkg_package_spec.rb +16 -0
  59. data/spec/functional/resource/macos_userdefaults_spec.rb +21 -1
  60. data/spec/functional/resource/yum_package_spec.rb +789 -129
  61. data/spec/functional/resource/zypper_package_spec.rb +7 -0
  62. data/spec/integration/client/client_spec.rb +31 -0
  63. data/spec/spec_helper.rb +3 -3
  64. data/spec/support/platform_helpers.rb +1 -1
  65. data/spec/support/ruby_installer.rb +1 -1
  66. data/spec/support/shared/functional/file_resource.rb +1 -1
  67. data/spec/support/shared/unit/provider/useradd_based_user_provider.rb +1 -1
  68. data/spec/unit/application/base_spec.rb +40 -0
  69. data/spec/unit/compliance/runner_spec.rb +62 -1
  70. data/spec/unit/dsl/registry_helper_spec.rb +6 -6
  71. data/spec/unit/file_access_control_spec.rb +1 -1
  72. data/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb +1 -1
  73. data/spec/unit/lwrp_spec.rb +2 -2
  74. data/spec/unit/mixin/why_run_spec.rb +53 -0
  75. data/spec/unit/provider/dsc_script_spec.rb +8 -8
  76. data/spec/unit/provider/group/groupadd_spec.rb +1 -0
  77. data/spec/unit/provider/group/usermod_spec.rb +4 -4
  78. data/spec/unit/provider/ifconfig/aix_spec.rb +14 -14
  79. data/spec/unit/provider/ifconfig/debian_spec.rb +1 -1
  80. data/spec/unit/provider/ifconfig/redhat_spec.rb +1 -1
  81. data/spec/unit/provider/ifconfig_spec.rb +5 -3
  82. data/spec/unit/provider/mount/linux_spec.rb +16 -3
  83. data/spec/unit/provider/package/bff_spec.rb +1 -0
  84. data/spec/unit/provider/package/powershell_spec.rb +114 -114
  85. data/spec/unit/provider/package/rubygems_spec.rb +3 -0
  86. data/spec/unit/provider/package/solaris_spec.rb +1 -0
  87. data/spec/unit/provider/remote_file/cache_control_data_spec.rb +3 -3
  88. data/spec/unit/provider/service/arch_service_spec.rb +2 -2
  89. data/spec/unit/provider/service/debian_service_spec.rb +1 -0
  90. data/spec/unit/provider/service/gentoo_service_spec.rb +3 -2
  91. data/spec/unit/provider/service/macosx_spec.rb +1 -0
  92. data/spec/unit/provider/service/redhat_spec.rb +4 -1
  93. data/spec/unit/provider/service/simple_service_spec.rb +6 -4
  94. data/spec/unit/provider/service/upstart_service_spec.rb +3 -3
  95. data/spec/unit/provider/user_spec.rb +2 -0
  96. data/spec/unit/resource/chef_client_trusted_certificate_spec.rb +14 -0
  97. data/spec/unit/resource/conditional_spec.rb +4 -4
  98. data/spec/unit/resource/dpkg_package_spec.rb +12 -0
  99. data/spec/unit/resource/macos_user_defaults_spec.rb +1 -1
  100. data/spec/unit/resource/rhsm_register_spec.rb +42 -0
  101. data/spec/unit/resource_spec.rb +2 -2
  102. data/spec/unit/secret_fetcher/hashi_vault_spec.rb +46 -0
  103. metadata +9 -9
  104. data/lib/chef/provider/group/suse.rb +0 -82
  105. data/spec/unit/provider/group/suse_spec.rb +0 -90
@@ -115,10 +115,90 @@ class Chef
115
115
  end
116
116
  end
117
117
 
118
+ def is_arch?(arch)
119
+ # cspell:disable-next
120
+ arches = %w{aarch64 alpha alphaev4 alphaev45 alphaev5 alphaev56 alphaev6 alphaev67 alphaev68 alphaev7 alphapca56 armv5tejl armv5tel armv5tl armv6l armv7l armv8l armv6hl armv7hl armv7hnl armv8hl i386 athlon geode i386 i486 i586 i686 ia64 mips mipsel mips64 mips64el noarch ppc ppc64 ppc64iseries ppc64p7 ppc64pseries ppc64le riscv32 riscv64 riscv128 s390 s390x sh3 sh4 sh4a sparc sparc64 sparc64v sparcv8 sparcv9 sparcv9v x86_64 amd64 ia32e}
121
+ arches.include?(arch)
122
+ end
123
+
124
+ # We have a provides line with an epoch in it and yum cannot parse that, so we
125
+ # need to deconstruct the args. This doesn't support splats which is why we
126
+ # only do it for this particularly narrow use case.
127
+ #
128
+ # name-epoch:version
129
+ # name-epoch:version.arch
130
+ # name-epoch:version-release
131
+ # name-epoch:version-release.arch
132
+ #
133
+ # @api private
134
+ def deconstruct_args(provides)
135
+ raise "provides must have an epoch in the version to deconstruct" unless provides =~ /^(\S+)-(\d+):(\S+)/
136
+
137
+ name = $1
138
+ epoch = $2
139
+ other = $3
140
+ ret = { "provides" => name, "epoch" => epoch }
141
+ maybe_arch = other.rpartition(".").last
142
+ arch = if is_arch?(maybe_arch)
143
+ other.delete_suffix!(".#{maybe_arch}")
144
+ maybe_arch
145
+ end
146
+ ret.merge!({ "arch" => arch }) if arch
147
+ (version, _, release) = other.rpartition("-")
148
+ if version.empty?
149
+ ret.merge!({ "version" => release }) # yeah, rpartition is just weird
150
+ else
151
+ ret.merge!({ "version" => version, "release" => release })
152
+ end
153
+ end
154
+
155
+ # In the default case for the yum provider we now do terrible things with ruby
156
+ # to concatenate all the properties together to form a single string to feed to
157
+ # the python which favors using returnPackages/searchProvides over the
158
+ # searchNevra API. That means that these two different ways of constructing the
159
+ # resource are now perfectly identical:
160
+ #
161
+ # yum_package "zabbix-agent-4.0.15-1.fc31.x86_64"
162
+ #
163
+ # yum_package "zabbix-agent" do
164
+ # version "4.0.15-1.fc31"
165
+ # arch "x86_64"
166
+ # end
167
+ #
168
+ # This function handles turning the second form into the first form.
169
+ #
170
+ # In the case where the epoch is given in the version and we do not have any glob
171
+ # patterns that is handled by going the other way and calling deconstruct_args due
172
+ # to the yum libraries not supporting that calling pattern other than by searchNevra.
173
+ #
174
+ # NOTE: This is an ugly hack and should NOT be considered an endorsement of this approach
175
+ # towards any kind of features or bugfixes in the DNF provider. I'm doing this
176
+ # because YUM is sunsetting at this point and its very difficult to fight with the
177
+ # libraries on the python side of things.
178
+ #
179
+ # @api private
180
+ def combine_args(provides, version, arch)
181
+ provides = provides.dup
182
+ maybe_arch = provides.rpartition(".").last
183
+ if is_arch?(maybe_arch)
184
+ arch = maybe_arch
185
+ provides.delete_suffix!(".#{arch}")
186
+ end
187
+ provides = "#{provides}-#{version}" if version
188
+ provides = "#{provides}.#{arch}" if arch
189
+ # yum (on rhel7) can't handle an epoch in provides, but
190
+ # deconstructing the args can't handle dealing with globs
191
+ if provides =~ /-\d+:/ && provides !~ /[\*\?]/
192
+ deconstruct_args(provides)
193
+ else
194
+ { "provides" => provides }
195
+ end
196
+ end
197
+
118
198
  # @return Array<Version>
119
199
  # NB: "options" here is the yum_package options hash and is deliberately not **opts
120
200
  def package_query(action, provides, version: nil, arch: nil, options: {})
121
- parameters = { "provides" => provides, "version" => version, "arch" => arch }
201
+ parameters = combine_args(provides, version, arch)
122
202
  repo_opts = options_params(options || {})
123
203
  parameters.merge!(repo_opts)
124
204
  # XXX: for now we close the rpmdb before and after every query with an enablerepo/disablerepo to clean the helpers internal state
@@ -137,25 +217,6 @@ class Chef
137
217
 
138
218
  private
139
219
 
140
- # i couldn't figure out how to decompose an evr on the python side, it seems reasonably
141
- # painless to do it in ruby (generally massaging nevras in the ruby side is HIGHLY
142
- # discouraged -- this is an "every rule has an exception" exception -- any additional
143
- # functionality should probably trigger moving this regexp logic into python)
144
- def add_version(hash, version)
145
- epoch = nil
146
- if version =~ /(\S+):(\S+)/
147
- epoch = $1
148
- version = $2
149
- end
150
- if version =~ /(\S+)-(\S+)/
151
- version = $1
152
- release = $2
153
- end
154
- hash["epoch"] = epoch unless epoch.nil?
155
- hash["release"] = release unless release.nil?
156
- hash["version"] = version
157
- end
158
-
159
220
  def query(action, parameters)
160
221
  with_helper do
161
222
  json = build_query(action, parameters)
@@ -174,11 +235,6 @@ class Chef
174
235
  hash[param_name] = param_value unless param_value.nil?
175
236
  end
176
237
 
177
- # Special handling for certain action / param combos
178
- if %i{whatinstalled whatavailable}.include?(action)
179
- add_version(hash, parameters["version"]) unless parameters["version"].nil?
180
- end
181
-
182
238
  FFI_Yajl::Encoder.encode(hash)
183
239
  end
184
240
 
@@ -36,6 +36,7 @@ class Chef
36
36
  allow_nils
37
37
  use_multipackage_api
38
38
  use_package_name_for_source
39
+ use_magic_version
39
40
 
40
41
  provides :package, platform_family: "fedora_derived"
41
42
 
@@ -64,6 +65,16 @@ class Chef
64
65
  current_resource
65
66
  end
66
67
 
68
+ def load_after_resource
69
+ # force the installed version array to repopulate
70
+ @current_version = []
71
+ @after_resource = Chef::Resource::YumPackage.new(new_resource.name)
72
+ after_resource.package_name(new_resource.package_name)
73
+ after_resource.version(get_current_versions)
74
+
75
+ after_resource
76
+ end
77
+
67
78
  def define_resource_requirements
68
79
  requirements.assert(:install, :upgrade, :remove, :purge) do |a|
69
80
  a.assertion { !new_resource.source || ::File.exist?(new_resource.source) }
@@ -80,9 +91,15 @@ class Chef
80
91
  end
81
92
  end
82
93
 
94
+ def magic_version_array
95
+ package_name_array.each_with_index.map do |pkg, i|
96
+ magical_version(i).version_with_arch
97
+ end
98
+ end
99
+
83
100
  def get_current_versions
84
101
  package_name_array.each_with_index.map do |pkg, i|
85
- installed_version(i).version_with_arch
102
+ current_version(i).version_with_arch
86
103
  end
87
104
  end
88
105
 
@@ -127,7 +144,7 @@ class Chef
127
144
  alias upgrade_package install_package
128
145
 
129
146
  def remove_package(names, versions)
130
- resolved_names = names.each_with_index.map { |name, i| installed_version(i).to_s unless name.nil? }
147
+ resolved_names = names.each_with_index.map { |name, i| magical_version(i).to_s unless name.nil? }
131
148
  yum(options, "-y", "remove", resolved_names)
132
149
  flushcache
133
150
  end
@@ -157,10 +174,10 @@ class Chef
157
174
  def resolved_package_lock_names(names)
158
175
  names.each_with_index.map do |name, i|
159
176
  unless name.nil?
160
- if installed_version(i).version.nil?
177
+ if magical_version(i).version.nil?
161
178
  available_version(i).name
162
179
  else
163
- installed_version(i).name
180
+ magical_version(i).name
164
181
  end
165
182
  end
166
183
  end
@@ -226,15 +243,25 @@ class Chef
226
243
  @available_version[index]
227
244
  end
228
245
 
246
+ def magical_version(index)
247
+ @magical_version ||= []
248
+ @magical_version[index] ||= if new_resource.source
249
+ python_helper.package_query(:whatinstalled, available_version(index).name, version: safe_version_array[index], arch: safe_arch_array[index], options: options)
250
+ else
251
+ python_helper.package_query(:whatinstalled, package_name_array[index], version: safe_version_array[index], arch: safe_arch_array[index], options: options)
252
+ end
253
+ @magical_version[index]
254
+ end
255
+
229
256
  # @return Array<Version>
230
- def installed_version(index)
231
- @installed_version ||= []
232
- @installed_version[index] ||= if new_resource.source
233
- python_helper.package_query(:whatinstalled, available_version(index).name, arch: safe_arch_array[index], options: options)
234
- else
235
- python_helper.package_query(:whatinstalled, package_name_array[index], arch: safe_arch_array[index], options: options)
236
- end
237
- @installed_version[index]
257
+ def current_version(index)
258
+ @current_version ||= []
259
+ @current_version[index] ||= if new_resource.source
260
+ python_helper.package_query(:whatinstalled, available_version(index).name, arch: safe_arch_array[index], options: options)
261
+ else
262
+ python_helper.package_query(:whatinstalled, package_name_array[index], arch: safe_arch_array[index], options: options)
263
+ end
264
+ @current_version[index]
238
265
  end
239
266
 
240
267
  def flushcache
@@ -113,6 +113,8 @@ class Chef
113
113
  end
114
114
  end
115
115
  nil
116
+ rescue
117
+ nil
116
118
  end
117
119
 
118
120
  def available_version(index)
@@ -107,7 +107,7 @@ class Chef
107
107
  end
108
108
  end
109
109
 
110
- action :install do
110
+ action :install, description: "Install a package. If a version is specified, install the specified version of the package." do
111
111
  unless target_version_array.any?
112
112
  logger.debug("#{new_resource} is already installed - nothing to do")
113
113
  return
@@ -136,7 +136,7 @@ class Chef
136
136
 
137
137
  private :install_description
138
138
 
139
- action :upgrade do
139
+ action :upgrade, description: "Install a package and ensure that a package is the latest version." do
140
140
  unless target_version_array.any?
141
141
  logger.debug("#{new_resource} no versions to upgrade - nothing to do")
142
142
  return
@@ -167,7 +167,7 @@ class Chef
167
167
 
168
168
  private :upgrade_description
169
169
 
170
- action :remove do
170
+ action :remove, description: "Remove a package." do
171
171
  if removing_package?
172
172
  description = new_resource.version ? "version #{new_resource.version} of " : ""
173
173
  converge_by("remove #{description}package #{current_resource.package_name}") do
@@ -202,7 +202,7 @@ class Chef
202
202
  end
203
203
  end
204
204
 
205
- action :purge do
205
+ action :purge, description: "Purge a package. This action typically removes the configuration files as well as the package." do
206
206
  if removing_package?
207
207
  description = new_resource.version ? "version #{new_resource.version} of" : ""
208
208
  converge_by("purge #{description} package #{current_resource.package_name}") do
@@ -438,47 +438,81 @@ class Chef
438
438
  @target_version_array ||=
439
439
  begin
440
440
  target_version_array = []
441
- each_package do |package_name, new_version, current_version, candidate_version|
441
+ each_package do |package_name, new_version, current_version, candidate_version, magic_version|
442
442
  case action
443
443
  when :upgrade
444
- if current_version.nil?
445
- # with use_magic_version there may be a package installed, but it fails the user's
446
- # requested new_resource.version constraints
444
+ if version_equals?(current_version, new_version)
445
+ # This is a short-circuit (mostly for the rubygems provider) to avoid needing to
446
+ # expensively query the candidate_version which must come later. This only checks
447
+ # exact matching, the check for fuzzy matching is later.
448
+ logger.trace("#{new_resource} #{package_name} #{new_version} is already installed")
449
+ target_version_array.push(nil)
450
+ elsif current_version.nil?
451
+ # This is a simple check to see if we have any currently installed version at all, this is
452
+ # safe to do before the allow_downgrade check so we check this before.
447
453
  logger.trace("#{new_resource} has no existing installed version. Installing install #{candidate_version}")
448
454
  target_version_array.push(candidate_version)
449
- elsif !use_magic_version? && version_equals?(current_version, new_version)
450
- # this is a short-circuit (mostly for the rubygems provider) to avoid needing to expensively query the candidate_version which must come later
451
- logger.trace("#{new_resource} #{package_name} #{new_version} is already installed")
455
+ elsif !allow_downgrade && version_compare(current_version, candidate_version) == 1
456
+ # This check for downgrading when allow_downgrade is false uses the current_version rather
457
+ # than the magic_version since we never want to downgrade even if the constraints are not met
458
+ # if the version is higher. This check does use the candidate_version and unlazies this so
459
+ # there will a perf hit on idempotent use when allow_downgrade is false which is unavoidable.
460
+ logger.trace("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{candidate_version}. Skipping...)")
452
461
  target_version_array.push(nil)
462
+ elsif magic_version.nil?
463
+ # This is the check for fuzzy matching of the installed_version, where if the installed version
464
+ # does not match the desired version constraints (but is not an exact match) then we need to
465
+ # install the candidate_version (this must come after the allow_downgrade check)
466
+ logger.trace("#{new_resource} has an installed version that does not match the version constraint. Installing install #{candidate_version}")
467
+ target_version_array.push(candidate_version)
453
468
  elsif candidate_version.nil?
469
+ # This check necessarily unlazies the candidate_version and may be expensive (connecting to
470
+ # rubygems.org or whatever). It comes as late as possible.
454
471
  logger.trace("#{new_resource} #{package_name} has no candidate_version to upgrade to")
455
472
  target_version_array.push(nil)
456
473
  elsif version_equals?(current_version, candidate_version)
474
+ # This check sees if the candidate_version is already installed or if we should upgrade/update the
475
+ # package. This is the normal idempotent behavior of :upgrade and is inherently expensive due to
476
+ # unlazying the candidate_version. To prevent the perf hit the version may be specified with a full
477
+ # version constraint. Then the cookbook can roll the version forward and use :upgrade to force version
478
+ # pinning.
457
479
  logger.trace("#{new_resource} #{package_name} #{candidate_version} is already installed")
458
480
  target_version_array.push(nil)
459
- elsif !allow_downgrade && version_compare(current_version, candidate_version) == 1
460
- logger.trace("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{candidate_version}. Skipping...)")
461
- target_version_array.push(nil)
462
481
  else
463
- logger.trace("#{new_resource} #{package_name} is out of date, will upgrade to #{candidate_version}")
482
+ logger.trace("#{new_resource} #{package_name} is out of date, will update to #{candidate_version}")
464
483
  target_version_array.push(candidate_version)
465
484
  end
466
485
 
467
486
  when :install
468
- if new_version && !use_magic_version?
487
+ if current_version && new_version && !allow_downgrade && version_compare(current_version, new_version) == 1
488
+ # This is the idempotency guard for downgrades when downgrades are not allowed. This should perhaps raise
489
+ # an exception since we were told to install an exact package version but we are silently refusing to do so
490
+ # because a higher version is already installed. Maybe we need a flag for users to apply their preferred
491
+ # declarative philosophy? This has to come early and outside of the two code paths below.
492
+ logger.warn("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{new_version}. Skipping...)")
493
+ target_version_array.push(nil)
494
+ elsif new_version && !use_magic_version?
495
+ # This is for "non magic version using" subclasses to do comparisons between the current_version and the
496
+ # desired new_version. XXX: If we converted this to current_version_requirement_satisfied? and made it specific
497
+ # to the current version check and then eliminated the magic_version, we might be able to eliminate separate codepaths
498
+ # here, and eliminate the semantic confusion around the magic_version?
469
499
  if version_requirement_satisfied?(current_version, new_version)
470
500
  logger.trace("#{new_resource} #{package_name} #{current_version} satisfies #{new_version} requirement")
471
501
  target_version_array.push(nil)
472
- elsif current_version && !allow_downgrade && version_compare(current_version, new_version) == 1
473
- logger.warn("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{new_version}. Skipping...)")
474
- target_version_array.push(nil)
475
502
  else
503
+ # XXX: some subclasses seem to depend on this behavior where the new_version can be different from the
504
+ # candidate_version and we install the new_version, it seems like the candidate_version should be fixed to
505
+ # be resolved correctly to the new_version for those providers. although it may just be unit test bugs.
506
+ # it would be more correct to use the candidate_version here, but then it needs to be the correctly resolved
507
+ # candidate_version against the new_version constraint.
476
508
  logger.trace("#{new_resource} #{package_name} #{current_version} needs updating to #{new_version}")
477
509
  target_version_array.push(new_version)
478
510
  end
479
- elsif current_version.nil?
480
- # with use_magic_version there may be a package installed, but it fails the user's
481
- # requested new_resource.version constraints
511
+ elsif magic_version.nil?
512
+ # This is for when we have a "magic version using" subclass and where the installed version does not match the
513
+ # constraint specified in the new_version, so we need to upgrade to the candidate_version. This is the only
514
+ # codepath in the :install branch which references the candidate_version so it is slow, but it is the path where
515
+ # we need to do work anyway. XXX: should we check for candidate_version.nil? somewhere around here?
482
516
  logger.trace("#{new_resource} #{package_name} not installed, installing #{candidate_version}")
483
517
  target_version_array.push(candidate_version)
484
518
  else
@@ -512,8 +546,8 @@ class Chef
512
546
  @packages_missing_candidates ||=
513
547
  begin
514
548
  missing = []
515
- each_package do |package_name, new_version, current_version, candidate_version|
516
- missing.push(package_name) if current_version.nil? && candidate_version.nil?
549
+ each_package do |package_name, new_version, current_version, candidate_version, magic_version|
550
+ missing.push(package_name) if magic_version.nil? && candidate_version.nil?
517
551
  end
518
552
  missing
519
553
  end
@@ -536,7 +570,7 @@ class Chef
536
570
  @forced_packages_missing_candidates ||=
537
571
  begin
538
572
  missing = []
539
- each_package do |package_name, new_version, current_version, candidate_version|
573
+ each_package do |package_name, new_version, current_version, candidate_version, magic_version|
540
574
  next if new_version.nil? || current_version.nil?
541
575
 
542
576
  if use_magic_version?
@@ -559,9 +593,10 @@ class Chef
559
593
  def each_package
560
594
  package_name_array.each_with_index do |package_name, i|
561
595
  candidate_version = candidate_version_array[i]
562
- current_version = use_magic_version? ? magic_version[i] : current_version_array[i]
596
+ current_version = current_version_array[i]
597
+ magic_version = use_magic_version? ? magic_version_array[i] : current_version_array[i]
563
598
  new_version = new_version_array[i]
564
- yield package_name, new_version, current_version, candidate_version
599
+ yield package_name, new_version, current_version, candidate_version, magic_version
565
600
  end
566
601
  end
567
602
 
@@ -623,7 +658,7 @@ class Chef
623
658
  end
624
659
 
625
660
  def allow_downgrade
626
- if new_resource.respond_to?("allow_downgrade")
661
+ if new_resource.respond_to?(:allow_downgrade)
627
662
  new_resource.allow_downgrade
628
663
  else
629
664
  true
@@ -339,7 +339,7 @@ class Chef
339
339
  end
340
340
 
341
341
  def locked?
342
- user_plist[:auth_authority].any? { |tag| tag == ";DisabledUser;" }
342
+ user_plist[:auth_authority].any?(";DisabledUser;")
343
343
  rescue
344
344
  false
345
345
  end
@@ -411,7 +411,7 @@ class Chef
411
411
  end
412
412
 
413
413
  def secure_token_enabled?
414
- user_plist[:auth_authority].any? { |tag| tag == ";SecureToken;" }
414
+ user_plist[:auth_authority].any?(";SecureToken;")
415
415
  rescue
416
416
  false
417
417
  end
@@ -505,7 +505,7 @@ class Chef
505
505
  end
506
506
 
507
507
  def admin_user?
508
- admin_group_plist[:group_members].any? { |mem| mem == user_plist[:guid][0] }
508
+ admin_group_plist[:group_members].any?(user_plist[:guid][0])
509
509
  rescue
510
510
  false
511
511
  end
data/lib/chef/provider.rb CHANGED
@@ -35,7 +35,6 @@ class Chef
35
35
  attr_accessor :after_resource
36
36
  attr_accessor :run_context
37
37
 
38
- attr_reader :recipe_name
39
38
  attr_reader :logger
40
39
 
41
40
  include Chef::Mixin::WhyRun
@@ -174,6 +173,10 @@ class Chef
174
173
  new_resource.cookbook_name
175
174
  end
176
175
 
176
+ def recipe_name
177
+ new_resource.recipe_name
178
+ end
179
+
177
180
  # hook that subclasses can use to do lazy validation for where properties aren't flexible enough
178
181
  def check_resource_semantics!; end
179
182
 
@@ -269,7 +272,7 @@ class Chef
269
272
  end
270
273
 
271
274
  def requirements
272
- @requirements ||= ResourceRequirements.new(@new_resource, run_context)
275
+ @requirements ||= ResourceRequirements.new(@new_resource, run_context, action || new_resource.action)
273
276
  end
274
277
 
275
278
  def description(description = "NOT_PASSED")
@@ -108,7 +108,6 @@ require_relative "provider/group/groupadd"
108
108
  require_relative "provider/group/groupmod"
109
109
  require_relative "provider/group/pw"
110
110
  require_relative "provider/group/solaris"
111
- require_relative "provider/group/suse"
112
111
  require_relative "provider/group/usermod"
113
112
  require_relative "provider/group/windows"
114
113
 
data/lib/chef/pwsh.rb CHANGED
@@ -24,15 +24,16 @@ class Chef
24
24
  # bindir directory.
25
25
  #
26
26
  # @param script [String] script to run
27
+ # @param timeout [Integer, nil] timeout in seconds.
27
28
  # @return [Object] output
28
- def initialize(script)
29
+ def initialize(script, timeout: -1)
29
30
  @dll = Pwsh.dll
30
31
  super
31
32
  end
32
33
 
33
34
  protected
34
35
 
35
- def exec(script)
36
+ def exec(script, timeout: -1)
36
37
  # Note that we need to override the location of the shared dotnet core library
37
38
  # location. With most .net core applications, you can simply publish them as a
38
39
  # "self-contained" application allowing consumers of the application to run them
@@ -43,7 +43,7 @@ class Chef
43
43
  **Install multiple packages at once**:
44
44
 
45
45
  ```ruby
46
- apt_package %(package1 package2 package3)
46
+ apt_package %w(package1 package2 package3)
47
47
  ```
48
48
 
49
49
  **Install without using recommend packages as a dependency**:
@@ -55,7 +55,7 @@ class Chef
55
55
  ```
56
56
  DOC
57
57
 
58
- description "Use the **apt_package** resource to manage packages on Debian and Ubuntu platforms."
58
+ description "Use the **apt_package** resource to manage packages on Debian, Ubuntu, and other platforms that use the APT package system."
59
59
 
60
60
  property :default_release, String,
61
61
  description: "The default release. For example: `stable`.",
@@ -87,6 +87,16 @@ class Chef
87
87
  ]
88
88
  end
89
89
  ```
90
+
91
+ **Report directly to the [Chef Automate data collector endpoint](/automate/data_collection/#configure-chef-infra-client-to-use-the-data-collector-endpoint-in-chef-automate).**
92
+
93
+ ```ruby
94
+ chef_client_config 'Create client.rb' do
95
+ chef_server_url 'https://chef.example.dmz'
96
+ data_collector_server_url 'https://automate.example.dmz'
97
+ data_collector_token 'TEST_TOKEN_TEST'
98
+ end
99
+ ```
90
100
  DOC
91
101
 
92
102
  # @todo policy_file or policy_group being set requires the other to be set so enforce that.
@@ -231,6 +241,14 @@ class Chef
231
241
  property :additional_config, String,
232
242
  description: "Additional text to add at the bottom of the client.rb config. This can be used to run custom Ruby or to add less common config options"
233
243
 
244
+ property :data_collector_server_url, String,
245
+ description: "The data collector URL (typically automate) to send node, converge, and compliance data. Note: If possible, use Chef Infra Server to do all data collection reporting, as this removes the need to distribute tokens to individual nodes.",
246
+ introduced: "17.8"
247
+
248
+ property :data_collector_token, String,
249
+ description: "The data collector token to interact with the data collector server URL (Automate). Note: If possible, use Chef Infra Server to do all data collection reporting, as this removes the need to distribute tokens to individual nodes.",
250
+ introduced: "17.8"
251
+
234
252
  action :create, description: "Create a client.rb config file for configuring #{ChefUtils::Dist::Infra::PRODUCT}." do
235
253
  unless ::Dir.exist?(new_resource.config_directory)
236
254
  directory new_resource.config_directory do
@@ -282,7 +300,9 @@ class Chef
282
300
  ssl_verify_mode: new_resource.ssl_verify_mode,
283
301
  start_handlers: format_handler(new_resource.start_handlers),
284
302
  additional_config: new_resource.additional_config,
285
- policy_persist_run_list: new_resource.policy_persist_run_list
303
+ policy_persist_run_list: new_resource.policy_persist_run_list,
304
+ data_collector_server_url: new_resource.data_collector_server_url,
305
+ data_collector_token: new_resource.data_collector_token
286
306
  )
287
307
  mode "0640"
288
308
  action :create
@@ -134,7 +134,7 @@ class Chef
134
134
  standard_error_path ::File.join(new_resource.log_directory, new_resource.log_file_name)
135
135
  program_arguments ["/bin/bash",
136
136
  "-c",
137
- "echo; echo #{ChefUtils::Dist::Infra::PRODUCT} launchd daemon config has been updated. Manually unloading and reloading the daemon; echo Now unloading the daemon; /bin/launchctl unload /Library/LaunchDaemons/com.#{ChefUtils::Dist::Infra::SHORT}.#{ChefUtils::Dist::Infra::CLIENT}.plist; sleep 2; echo Now loading the daemon; /bin/launchctl load /Library/LaunchDaemons/com.#{ChefUtils::Dist::Infra::SHORT}.#{ChefUtils::Dist::Infra::CLIENT}.plist"]
137
+ "echo; echo #{ChefUtils::Dist::Infra::PRODUCT} launchd daemon config has been updated. Manually unloading and reloading the daemon; echo Now unloading the daemon; sudo /bin/launchctl unload /Library/LaunchDaemons/com.#{ChefUtils::Dist::Infra::SHORT}.#{ChefUtils::Dist::Infra::CLIENT}.plist; sleep 2; echo Now loading the daemon; sudo /bin/launchctl load /Library/LaunchDaemons/com.#{ChefUtils::Dist::Infra::SHORT}.#{ChefUtils::Dist::Infra::CLIENT}.plist"]
138
138
  action :enable # enable creates the plist & triggers service restarts on change
139
139
  end
140
140
 
@@ -75,6 +75,7 @@ class Chef
75
75
  file cert_path do
76
76
  content new_resource.certificate
77
77
  mode "0640"
78
+ sensitive new_resource.sensitive
78
79
  end
79
80
  end
80
81
 
@@ -25,7 +25,7 @@ class Chef
25
25
 
26
26
  provides :chocolatey_package
27
27
 
28
- description "Use the **chocolatey_package** resource to manage packages using Chocolatey on the Microsoft Windows platform. Note: The Chocolatey package manager is not installed on Windows by default. You will need to install it prior to using this resource by adding the [Chocolatey cookbook](https://supermarket.chef.io/cookbooks/chocolatey/) to your node's run list."
28
+ description "Use the **chocolatey_package** resource to manage packages using the Chocolatey package manager on the Microsoft Windows platform. Note: The Chocolatey package manager is not installed on Windows by default. You will need to install it prior to using this resource by adding the [chocolatey cookbook](https://supermarket.chef.io/cookbooks/chocolatey/) to your node's run list. Warning: The **chocolatey_package** resource must be specified as `chocolatey_package` and cannot be shortened to `package` in a recipe."
29
29
  introduced "12.7"
30
30
  examples <<~DOC
31
31
  **Install a Chocolatey package**:
@@ -73,9 +73,9 @@ class Chef
73
73
  coerce: proc { |x| [x].flatten }
74
74
 
75
75
  # In the choco if we have the feature useEnhancedExitCodes turned on, then choco will provide enhanced exit codes(2: no results).
76
- # Choco exit codes https://chocolatey.org/docs/commandsinfo#exit-codes
76
+ # Choco exit codes https://docs.chocolatey.org/en-us/choco/commands/info#exit-codes
77
77
  property :returns, [Integer, Array],
78
- description: "The exit code(s) returned a chocolatey package that indicate success.",
78
+ description: "The exit code(s) returned by the `choco` command that indicate a successful action. See [Chocolatey Exit Codes](https://docs.chocolatey.org/en-us/choco/commands/info#exit-codes) for a complete list of exit codes used by Chocolatey.",
79
79
  default: [ 0, 2 ], desired_state: false,
80
80
  introduced: "12.18"
81
81
  end