chef 17.10.95 → 18.0.169

Sign up to get free protection for your applications and to get access to all the features.
Files changed (313) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +16 -8
  3. data/README.md +7 -7
  4. data/Rakefile +3 -22
  5. data/{chef-universal-mingw32.gemspec → chef-universal-mingw-ucrt.gemspec} +8 -7
  6. data/chef.gemspec +14 -7
  7. data/lib/chef/api_client_v1.rb +9 -1
  8. data/lib/chef/application/exit_code.rb +3 -3
  9. data/lib/chef/client.rb +169 -17
  10. data/lib/chef/compliance/input.rb +1 -1
  11. data/lib/chef/compliance/profile.rb +1 -1
  12. data/lib/chef/compliance/profile_collection.rb +0 -1
  13. data/lib/chef/compliance/waiver.rb +1 -1
  14. data/lib/chef/cookbook/syntax_check.rb +2 -2
  15. data/lib/chef/dsl/reader_helpers.rb +1 -1
  16. data/lib/chef/dsl/rest_resource.rb +77 -0
  17. data/lib/chef/event_dispatch/base.rb +3 -0
  18. data/lib/chef/exceptions.rb +8 -0
  19. data/lib/chef/http/authenticator.rb +170 -3
  20. data/lib/chef/http/ssl_policies.rb +3 -3
  21. data/lib/chef/mixin/checksum.rb +0 -6
  22. data/lib/chef/mixin/powershell_exec.rb +5 -28
  23. data/lib/chef/node/mixin/immutablize_array.rb +1 -0
  24. data/lib/chef/property.rb +5 -3
  25. data/lib/chef/provider/file.rb +2 -2
  26. data/lib/chef/provider/group/windows.rb +1 -1
  27. data/lib/chef/provider/http_request.rb +11 -9
  28. data/lib/chef/provider/mount/linux.rb +5 -0
  29. data/lib/chef/provider/mount/mount.rb +8 -0
  30. data/lib/chef/provider/mount/windows.rb +1 -1
  31. data/lib/chef/provider/package/chocolatey.rb +1 -18
  32. data/lib/chef/provider/package/rubygems.rb +1 -1
  33. data/lib/chef/provider/package/windows/msi.rb +2 -2
  34. data/lib/chef/provider/package/windows/registry_uninstall_entry.rb +1 -1
  35. data/lib/chef/provider/package/windows.rb +1 -1
  36. data/lib/chef/provider/package/zypper/version.rb +60 -0
  37. data/lib/chef/provider/package/zypper.rb +47 -3
  38. data/lib/chef/provider/service/windows.rb +1 -1
  39. data/lib/chef/provider/user/aix.rb +5 -0
  40. data/lib/chef/provider/user/linux.rb +29 -0
  41. data/lib/chef/provider/user/mac.rb +1 -1
  42. data/lib/chef/provider/user.rb +46 -14
  43. data/lib/chef/provider.rb +1 -1
  44. data/lib/chef/recipe.rb +1 -1
  45. data/lib/chef/resource/_rest_resource.rb +389 -0
  46. data/lib/chef/resource/alternatives.rb +0 -1
  47. data/lib/chef/resource/apt_package.rb +0 -1
  48. data/lib/chef/resource/apt_preference.rb +0 -1
  49. data/lib/chef/resource/apt_repository.rb +0 -1
  50. data/lib/chef/resource/apt_update.rb +0 -1
  51. data/lib/chef/resource/archive_file.rb +0 -1
  52. data/lib/chef/resource/bash.rb +0 -1
  53. data/lib/chef/resource/batch.rb +0 -1
  54. data/lib/chef/resource/bff_package.rb +0 -1
  55. data/lib/chef/resource/breakpoint.rb +0 -1
  56. data/lib/chef/resource/build_essential.rb +0 -1
  57. data/lib/chef/resource/cab_package.rb +0 -1
  58. data/lib/chef/resource/chef_client_config.rb +12 -14
  59. data/lib/chef/resource/chef_client_cron.rb +1 -2
  60. data/lib/chef/resource/chef_client_launchd.rb +2 -2
  61. data/lib/chef/resource/chef_client_scheduled_task.rb +3 -3
  62. data/lib/chef/resource/chef_client_systemd_timer.rb +0 -1
  63. data/lib/chef/resource/chef_client_trusted_certificate.rb +0 -1
  64. data/lib/chef/resource/chef_gem.rb +0 -1
  65. data/lib/chef/resource/chef_handler.rb +0 -1
  66. data/lib/chef/resource/chef_sleep.rb +1 -3
  67. data/lib/chef/resource/chef_vault_secret.rb +0 -1
  68. data/lib/chef/resource/chocolatey_config.rb +0 -1
  69. data/lib/chef/resource/chocolatey_feature.rb +0 -1
  70. data/lib/chef/resource/chocolatey_package.rb +0 -1
  71. data/lib/chef/resource/chocolatey_source.rb +0 -1
  72. data/lib/chef/resource/cookbook_file.rb +0 -1
  73. data/lib/chef/resource/cron/_cron_shared.rb +0 -1
  74. data/lib/chef/resource/cron/cron.rb +0 -1
  75. data/lib/chef/resource/cron/cron_d.rb +15 -1
  76. data/lib/chef/resource/cron_access.rb +0 -1
  77. data/lib/chef/resource/csh.rb +0 -1
  78. data/lib/chef/resource/directory.rb +0 -1
  79. data/lib/chef/resource/dmg_package.rb +0 -1
  80. data/lib/chef/resource/dnf_package.rb +0 -1
  81. data/lib/chef/resource/dpkg_package.rb +0 -1
  82. data/lib/chef/resource/dsc_resource.rb +0 -1
  83. data/lib/chef/resource/dsc_script.rb +0 -1
  84. data/lib/chef/resource/execute.rb +0 -1
  85. data/lib/chef/resource/file.rb +0 -1
  86. data/lib/chef/resource/freebsd_package.rb +0 -1
  87. data/lib/chef/resource/gem_package.rb +0 -1
  88. data/lib/chef/resource/group.rb +25 -2
  89. data/lib/chef/resource/habitat/habitat_package.rb +0 -1
  90. data/lib/chef/resource/habitat/habitat_sup.rb +6 -7
  91. data/lib/chef/resource/habitat/habitat_sup_windows.rb +1 -1
  92. data/lib/chef/resource/habitat_config.rb +0 -1
  93. data/lib/chef/resource/habitat_install.rb +0 -1
  94. data/lib/chef/resource/habitat_service.rb +0 -1
  95. data/lib/chef/resource/habitat_user_toml.rb +0 -1
  96. data/lib/chef/resource/homebrew_cask.rb +0 -1
  97. data/lib/chef/resource/homebrew_package.rb +0 -1
  98. data/lib/chef/resource/homebrew_tap.rb +0 -1
  99. data/lib/chef/resource/homebrew_update.rb +0 -2
  100. data/lib/chef/resource/hostname.rb +0 -1
  101. data/lib/chef/resource/http_request.rb +0 -1
  102. data/lib/chef/resource/ifconfig.rb +0 -1
  103. data/lib/chef/resource/inspec_input.rb +0 -1
  104. data/lib/chef/resource/inspec_waiver.rb +0 -1
  105. data/lib/chef/resource/inspec_waiver_file_entry.rb +2 -3
  106. data/lib/chef/resource/ips_package.rb +0 -1
  107. data/lib/chef/resource/kernel_module.rb +0 -1
  108. data/lib/chef/resource/ksh.rb +0 -1
  109. data/lib/chef/resource/launchd.rb +0 -1
  110. data/lib/chef/resource/link.rb +0 -1
  111. data/lib/chef/resource/locale.rb +2 -6
  112. data/lib/chef/resource/log.rb +0 -1
  113. data/lib/chef/resource/lwrp_base.rb +0 -4
  114. data/lib/chef/resource/macos_userdefaults.rb +5 -10
  115. data/lib/chef/resource/macosx_service.rb +0 -1
  116. data/lib/chef/resource/macports_package.rb +0 -1
  117. data/lib/chef/resource/mdadm.rb +0 -1
  118. data/lib/chef/resource/mount.rb +0 -1
  119. data/lib/chef/resource/msu_package.rb +0 -1
  120. data/lib/chef/resource/notify_group.rb +0 -2
  121. data/lib/chef/resource/ohai.rb +0 -1
  122. data/lib/chef/resource/ohai_hint.rb +0 -1
  123. data/lib/chef/resource/openbsd_package.rb +0 -1
  124. data/lib/chef/resource/openssl_dhparam.rb +0 -2
  125. data/lib/chef/resource/openssl_ec_private_key.rb +0 -2
  126. data/lib/chef/resource/openssl_ec_public_key.rb +0 -2
  127. data/lib/chef/resource/openssl_rsa_private_key.rb +0 -2
  128. data/lib/chef/resource/openssl_rsa_public_key.rb +0 -2
  129. data/lib/chef/resource/openssl_x509_certificate.rb +0 -2
  130. data/lib/chef/resource/openssl_x509_crl.rb +0 -2
  131. data/lib/chef/resource/openssl_x509_request.rb +0 -2
  132. data/lib/chef/resource/osx_profile.rb +0 -1
  133. data/lib/chef/resource/package.rb +0 -1
  134. data/lib/chef/resource/pacman_package.rb +0 -1
  135. data/lib/chef/resource/paludis_package.rb +0 -1
  136. data/lib/chef/resource/perl.rb +0 -1
  137. data/lib/chef/resource/plist.rb +7 -3
  138. data/lib/chef/resource/portage_package.rb +0 -1
  139. data/lib/chef/resource/powershell_package.rb +0 -1
  140. data/lib/chef/resource/powershell_package_source.rb +0 -1
  141. data/lib/chef/resource/powershell_script.rb +0 -1
  142. data/lib/chef/resource/python.rb +0 -1
  143. data/lib/chef/resource/reboot.rb +0 -1
  144. data/lib/chef/resource/registry_key.rb +0 -1
  145. data/lib/chef/resource/remote_directory.rb +0 -1
  146. data/lib/chef/resource/remote_file.rb +0 -1
  147. data/lib/chef/resource/rhsm_errata.rb +0 -1
  148. data/lib/chef/resource/rhsm_errata_level.rb +0 -1
  149. data/lib/chef/resource/rhsm_register.rb +0 -3
  150. data/lib/chef/resource/rhsm_repo.rb +0 -1
  151. data/lib/chef/resource/rhsm_subscription.rb +0 -1
  152. data/lib/chef/resource/route.rb +0 -1
  153. data/lib/chef/resource/rpm_package.rb +0 -1
  154. data/lib/chef/resource/ruby.rb +0 -1
  155. data/lib/chef/resource/ruby_block.rb +0 -1
  156. data/lib/chef/resource/scm/_scm.rb +0 -2
  157. data/lib/chef/resource/scm/git.rb +0 -2
  158. data/lib/chef/resource/scm/subversion.rb +0 -2
  159. data/lib/chef/resource/script.rb +0 -1
  160. data/lib/chef/resource/selinux/common_helpers.rb +47 -0
  161. data/lib/chef/resource/selinux/selinux_debian.erb +18 -0
  162. data/lib/chef/resource/selinux/selinux_default.erb +15 -0
  163. data/lib/chef/resource/selinux_boolean.rb +101 -0
  164. data/lib/chef/resource/selinux_fcontext.rb +160 -0
  165. data/lib/chef/resource/selinux_install.rb +107 -0
  166. data/lib/chef/resource/selinux_module.rb +143 -0
  167. data/lib/chef/resource/selinux_permissive.rb +64 -0
  168. data/lib/chef/resource/selinux_port.rb +118 -0
  169. data/lib/chef/resource/selinux_state.rb +166 -0
  170. data/lib/chef/resource/service.rb +0 -1
  171. data/lib/chef/resource/smartos_package.rb +0 -1
  172. data/lib/chef/resource/snap_package.rb +0 -1
  173. data/lib/chef/resource/solaris_package.rb +0 -1
  174. data/lib/chef/resource/ssh_known_hosts_entry.rb +0 -1
  175. data/lib/chef/resource/sudo.rb +0 -1
  176. data/lib/chef/resource/support/client.erb +2 -2
  177. data/lib/chef/resource/swap_file.rb +0 -1
  178. data/lib/chef/resource/sysctl.rb +1 -2
  179. data/lib/chef/resource/systemd_unit.rb +0 -1
  180. data/lib/chef/resource/template.rb +0 -1
  181. data/lib/chef/resource/timezone.rb +0 -1
  182. data/lib/chef/resource/user/aix_user.rb +0 -1
  183. data/lib/chef/resource/user/linux_user.rb +0 -1
  184. data/lib/chef/resource/user/mac_user.rb +0 -1
  185. data/lib/chef/resource/user/pw_user.rb +0 -1
  186. data/lib/chef/resource/user/solaris_user.rb +0 -1
  187. data/lib/chef/resource/user/windows_user.rb +0 -1
  188. data/lib/chef/resource/user.rb +10 -1
  189. data/lib/chef/resource/user_ulimit.rb +0 -1
  190. data/lib/chef/resource/whyrun_safe_ruby_block.rb +0 -1
  191. data/lib/chef/resource/windows_ad_join.rb +0 -2
  192. data/lib/chef/resource/windows_audit_policy.rb +0 -2
  193. data/lib/chef/resource/windows_auto_run.rb +0 -1
  194. data/lib/chef/resource/windows_defender.rb +0 -1
  195. data/lib/chef/resource/windows_defender_exclusion.rb +0 -1
  196. data/lib/chef/resource/windows_dfs_folder.rb +0 -1
  197. data/lib/chef/resource/windows_dfs_namespace.rb +0 -1
  198. data/lib/chef/resource/windows_dfs_server.rb +0 -1
  199. data/lib/chef/resource/windows_dns_record.rb +0 -1
  200. data/lib/chef/resource/windows_dns_zone.rb +0 -1
  201. data/lib/chef/resource/windows_env.rb +0 -1
  202. data/lib/chef/resource/windows_feature.rb +0 -1
  203. data/lib/chef/resource/windows_feature_dism.rb +0 -1
  204. data/lib/chef/resource/windows_feature_powershell.rb +0 -1
  205. data/lib/chef/resource/windows_firewall_profile.rb +0 -2
  206. data/lib/chef/resource/windows_firewall_rule.rb +0 -1
  207. data/lib/chef/resource/windows_font.rb +2 -3
  208. data/lib/chef/resource/windows_package.rb +0 -1
  209. data/lib/chef/resource/windows_pagefile.rb +0 -2
  210. data/lib/chef/resource/windows_path.rb +0 -1
  211. data/lib/chef/resource/windows_printer.rb +0 -1
  212. data/lib/chef/resource/windows_printer_port.rb +0 -1
  213. data/lib/chef/resource/windows_script.rb +0 -2
  214. data/lib/chef/resource/windows_security_policy.rb +0 -1
  215. data/lib/chef/resource/windows_service.rb +0 -1
  216. data/lib/chef/resource/windows_share.rb +0 -1
  217. data/lib/chef/resource/windows_shortcut.rb +1 -2
  218. data/lib/chef/resource/windows_task.rb +0 -1
  219. data/lib/chef/resource/windows_uac.rb +0 -1
  220. data/lib/chef/resource/windows_update_settings.rb +0 -1
  221. data/lib/chef/resource/windows_user_privilege.rb +0 -1
  222. data/lib/chef/resource/windows_workgroup.rb +0 -1
  223. data/lib/chef/resource/yum_package.rb +0 -1
  224. data/lib/chef/resource/yum_repository.rb +0 -1
  225. data/lib/chef/resource/zypper_package.rb +0 -1
  226. data/lib/chef/resource/zypper_repository.rb +0 -1
  227. data/lib/chef/resource.rb +12 -5
  228. data/lib/chef/resources.rb +7 -0
  229. data/lib/chef/run_context.rb +3 -3
  230. data/lib/chef/secret_fetcher/azure_key_vault.rb +3 -3
  231. data/lib/chef/version.rb +1 -1
  232. data/lib/chef/win32/handle.rb +6 -7
  233. data/lib/chef/win32/registry.rb +7 -3
  234. data/spec/data/rubygems.org/sexp_processor-info +2 -1
  235. data/spec/data/trusted_certs/example.crt +20 -29
  236. data/spec/data/trusted_certs/example_no_cn.crt +34 -30
  237. data/spec/data/trusted_certs/opscode.pem +54 -33
  238. data/spec/functional/resource/chocolatey_package_spec.rb +20 -32
  239. data/spec/functional/resource/dsc_script_spec.rb +1 -1
  240. data/spec/functional/resource/group_spec.rb +10 -6
  241. data/spec/functional/resource/link_spec.rb +8 -8
  242. data/spec/functional/resource/macos_userdefaults_spec.rb +4 -4
  243. data/spec/functional/resource/plist_spec.rb +25 -0
  244. data/spec/functional/resource/user/linux_user_spec.rb +127 -0
  245. data/spec/functional/resource/windows_certificate_spec.rb +1 -26
  246. data/spec/functional/resource/windows_font_spec.rb +12 -9
  247. data/spec/functional/resource/yum_package_spec.rb +1 -1
  248. data/spec/functional/resource/zypper_package_spec.rb +12 -0
  249. data/spec/functional/shell_spec.rb +1 -2
  250. data/spec/functional/version_spec.rb +1 -1
  251. data/spec/integration/client/client_spec.rb +82 -3
  252. data/spec/integration/client/exit_code_spec.rb +1 -1
  253. data/spec/integration/client/ipv6_spec.rb +1 -1
  254. data/spec/integration/compliance/compliance_spec.rb +1 -1
  255. data/spec/integration/recipes/accumulator_spec.rb +1 -1
  256. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +1 -1
  257. data/spec/integration/recipes/lwrp_spec.rb +1 -1
  258. data/spec/integration/recipes/notifies_spec.rb +1 -1
  259. data/spec/integration/recipes/notifying_block_spec.rb +1 -1
  260. data/spec/integration/recipes/remote_directory.rb +1 -1
  261. data/spec/integration/recipes/unified_mode_spec.rb +1 -1
  262. data/spec/integration/recipes/use_partial_spec.rb +2 -1
  263. data/spec/integration/solo/solo_spec.rb +2 -2
  264. data/spec/spec_helper.rb +1 -0
  265. data/spec/support/platform_helpers.rb +4 -0
  266. data/spec/support/ruby_installer.rb +1 -1
  267. data/spec/support/shared/functional/windows_script.rb +2 -2
  268. data/spec/unit/application/client_spec.rb +0 -10
  269. data/spec/unit/client_spec.rb +57 -8
  270. data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +1 -1
  271. data/spec/unit/cookbook/syntax_check_spec.rb +3 -0
  272. data/spec/unit/http/authenticator_spec.rb +68 -0
  273. data/spec/unit/mixin/checksum_spec.rb +0 -28
  274. data/spec/unit/mixin/powershell_exec_spec.rb +5 -5
  275. data/spec/unit/platform/query_helpers_spec.rb +2 -17
  276. data/spec/unit/provider/http_request_spec.rb +60 -72
  277. data/spec/unit/provider/mount/linux_spec.rb +10 -0
  278. data/spec/unit/provider/package/chocolatey_spec.rb +3 -19
  279. data/spec/unit/provider/package/rubygems_spec.rb +1 -1
  280. data/spec/unit/provider/package/zypper_spec.rb +32 -0
  281. data/spec/unit/provider/user/linux_spec.rb +51 -11
  282. data/spec/unit/provider/user_spec.rb +24 -6
  283. data/spec/unit/resource/archive_file_spec.rb +1 -1
  284. data/spec/unit/resource/chef_client_cron_spec.rb +5 -0
  285. data/spec/unit/resource/chef_client_launchd_spec.rb +5 -0
  286. data/spec/unit/resource/chef_client_scheduled_task_spec.rb +5 -0
  287. data/spec/unit/resource/chef_client_systemd_timer_spec.rb +1 -1
  288. data/spec/unit/resource/cron_d_spec.rb +37 -1
  289. data/spec/unit/resource/macos_user_defaults_spec.rb +4 -4
  290. data/spec/unit/resource/rest_resource_spec.rb +381 -0
  291. data/spec/unit/resource/selinux_boolean_spec.rb +92 -0
  292. data/spec/unit/resource/selinux_fcontext_spec.rb +65 -0
  293. data/spec/unit/resource/selinux_install_spec.rb +60 -0
  294. data/spec/unit/resource/selinux_module_spec.rb +55 -0
  295. data/spec/unit/resource/selinux_permissive_spec.rb +39 -0
  296. data/spec/unit/resource/selinux_port_spec.rb +42 -0
  297. data/spec/unit/resource/selinux_state_spec.rb +46 -0
  298. data/spec/unit/resource/sysctl_spec.rb +2 -2
  299. data/spec/unit/resource/user/linux_user_spec.rb +42 -0
  300. data/spec/unit/resource_spec.rb +0 -1
  301. data/spec/unit/util/dsc/local_configuration_manager_spec.rb +1 -1
  302. data/tasks/rspec.rb +1 -1
  303. metadata +102 -30
  304. /data/spec/functional/assets/chocolatey_feed/{test-A.1.0.0.nupkg → test-A.1.0.nupkg} +0 -0
  305. /data/spec/functional/assets/chocolatey_feed/{test-A.1.5.0.nupkg → test-A.1.5.nupkg} +0 -0
  306. /data/spec/functional/assets/chocolatey_feed/{test-A.2.0.0.nupkg → test-A.2.0.nupkg} +0 -0
  307. /data/spec/functional/assets/chocolatey_feed/{test-B.1.0.0.nupkg → test-B.1.0.nupkg} +0 -0
  308. /data/spec/functional/assets/yumrepo/repodata/{01a3b-filelists.sqlite.bz2 → 4632d67cb92636e7575d911c24f0e04d3505a944e97c483abe0c3e73a7c62d33-filelists.sqlite.bz2} +0 -0
  309. /data/spec/functional/assets/yumrepo/repodata/{6bf96-other.xml.gz → 74599b793e54d877323837d2d81a1c3c594c44e4335f9528234bb490f7b9b439-other.xml.gz} +0 -0
  310. /data/spec/functional/assets/yumrepo/repodata/{5dc1e-primary.sqlite.bz2 → a845d418f919d2115ab95a56b2c76f6825ad0d0bede49181a55c04f58995d057-primary.sqlite.bz2} +0 -0
  311. /data/spec/functional/assets/yumrepo/repodata/{7c365-other.sqlite.bz2 → af9b7cf9ef23bd7b43068d74a460f3b5d06753d638e58e4a0c9edc35bfb9cdc4-other.sqlite.bz2} +0 -0
  312. /data/spec/functional/assets/yumrepo/repodata/{401dc-filelists.xml.gz → bdb4f5f1492a3b9532f22c43110a81500dd744f23da0aec5c33b2a41317c737d-filelists.xml.gz} +0 -0
  313. /data/spec/functional/assets/yumrepo/repodata/{dabe2-primary.xml.gz → c10d1d34ce99e02f12ec96ef68360543ab1bb7c3cb81a4a2bf78df7d8597e9df-primary.xml.gz} +0 -0
@@ -20,17 +20,28 @@
20
20
 
21
21
  require_relative "../package"
22
22
  require_relative "../../resource/zypper_package"
23
+ require_relative "zypper/version"
23
24
 
24
25
  class Chef
25
26
  class Provider
26
27
  class Package
27
28
  class Zypper < Chef::Provider::Package
28
29
  use_multipackage_api
30
+ use_package_name_for_source
29
31
  allow_nils
30
32
 
31
33
  provides :package, platform_family: "suse"
32
34
  provides :zypper_package
33
35
 
36
+ def define_resource_requirements
37
+ super
38
+ requirements.assert(:install, :upgrade) do |a|
39
+ a.assertion { source_files_exist? }
40
+ a.failure_message Chef::Exceptions::Package, "#{new_resource} source file(s) do not exist: #{missing_sources}"
41
+ a.whyrun "Assuming they would have been previously created."
42
+ end
43
+ end
44
+
34
45
  def load_current_resource
35
46
  @current_resource = Chef::Resource::ZypperPackage.new(new_resource.name)
36
47
  current_resource.package_name(new_resource.package_name)
@@ -70,7 +81,35 @@ class Chef
70
81
  end
71
82
 
72
83
  def candidate_version
73
- @candidate_version ||= package_name_array.each_with_index.map { |pkg, i| available_version(i) }
84
+ package_name_array.each_with_index.map do |pkg, i|
85
+ available_version(i)
86
+ end
87
+ end
88
+
89
+ # returns true if all sources exist. Returns false if any do not, or if no
90
+ # sources were specified.
91
+ # @return [Boolean] True if all sources exist
92
+ def source_files_exist?
93
+ if !new_resource.source.nil?
94
+ resolved_source_array.all? { |s| s && ::File.exist?(s) }
95
+ else
96
+ true
97
+ end
98
+ end
99
+
100
+ # Helper to return all the names of the missing sources for error messages.
101
+ # @return [Array<String>] Array of missing sources
102
+ def missing_sources
103
+ resolved_source_array.select { |s| s.nil? || !::File.exist?(s) }
104
+ end
105
+
106
+ def resolve_source_to_version
107
+ shell_out!("rpm -qp --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n' #{new_resource.source}").stdout.each_line do |line|
108
+ case line
109
+ when /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/
110
+ return Version.new($1, "#{$2 == "(none)" ? "0" : $2}:#{$3}-#{$4}", $5)
111
+ end
112
+ end
74
113
  end
75
114
 
76
115
  def resolve_current_version(package_name)
@@ -119,7 +158,12 @@ class Chef
119
158
 
120
159
  def available_version(index)
121
160
  @available_version ||= []
122
- @available_version[index] ||= resolve_available_version(package_name_array[index], safe_version_array[index])
161
+
162
+ @available_version[index] ||= if new_resource.source
163
+ resolve_source_to_version
164
+ else
165
+ resolve_available_version(package_name_array[index], safe_version_array[index])
166
+ end
123
167
  @available_version[index]
124
168
  end
125
169
 
@@ -141,7 +185,7 @@ class Chef
141
185
  end
142
186
 
143
187
  def zypper_package(command, global_options, *options, names, versions)
144
- zipped_names = zip(names, versions)
188
+ zipped_names = new_resource.source || zip(names, versions)
145
189
  if zypper_version < 1.0
146
190
  shell_out!("zypper", global_options, gpg_checks, command, *options, "-y", names)
147
191
  else
@@ -20,7 +20,7 @@
20
20
 
21
21
  require_relative "simple"
22
22
  require_relative "../../win32_service_constants"
23
- if RUBY_PLATFORM.match?(/mswin|mingw32|windows/)
23
+ if RUBY_PLATFORM.match?(/mswin|mingw|windows/)
24
24
  require_relative "../../win32/error"
25
25
  require "win32/service"
26
26
  end
@@ -23,6 +23,11 @@ class Chef
23
23
  provides :user, os: "aix"
24
24
  provides :aix_user
25
25
 
26
+ # The ruby-shadow gem is not supported on aix.
27
+ def supports_ruby_shadow?
28
+ false
29
+ end
30
+
26
31
  def create_user
27
32
  shell_out!("useradd", universal_options, useradd_options, new_resource.username)
28
33
  add_password
@@ -23,6 +23,27 @@ class Chef
23
23
  provides :linux_user
24
24
  provides :user, os: "linux"
25
25
 
26
+ def load_current_resource
27
+ super
28
+ load_shadow_options
29
+ end
30
+
31
+ def compare_user
32
+ user_changed = super
33
+
34
+ @change_desc ||= []
35
+
36
+ %i{expire_date inactive}.each do |user_attrib|
37
+ new_val = new_resource.send(user_attrib)
38
+ cur_val = current_resource.send(user_attrib)
39
+ if !new_val.nil? && new_val.to_s != cur_val.to_s
40
+ @change_desc << "change #{user_attrib} from #{cur_val} to #{new_val}"
41
+ end
42
+ end
43
+
44
+ user_changed || !@change_desc.empty?
45
+ end
46
+
26
47
  def create_user
27
48
  shell_out!("useradd", universal_options, useradd_options, new_resource.username)
28
49
  end
@@ -52,7 +73,9 @@ class Chef
52
73
  def universal_options
53
74
  opts = []
54
75
  opts << "-c" << new_resource.comment if should_set?(:comment)
76
+ opts << "-e" << new_resource.expire_date if prop_is_set?(:expire_date)
55
77
  opts << "-g" << new_resource.gid if should_set?(:gid)
78
+ opts << "-f" << new_resource.inactive if prop_is_set?(:inactive)
56
79
  opts << "-p" << new_resource.password if should_set?(:password)
57
80
  opts << "-s" << new_resource.shell if should_set?(:shell)
58
81
  opts << "-u" << new_resource.uid if should_set?(:uid)
@@ -116,6 +139,12 @@ class Chef
116
139
  # FIXME: should probably go on the current_resource
117
140
  @locked
118
141
  end
142
+
143
+ def prop_is_set?(prop)
144
+ v = new_resource.send(prop.to_sym)
145
+
146
+ !v.nil? && v != ""
147
+ end
119
148
  end
120
149
  end
121
150
  end
@@ -48,7 +48,7 @@ class Chef
48
48
  if user_plist
49
49
  current_resource.uid(user_plist[:uid][0])
50
50
  current_resource.gid(user_plist[:gid][0])
51
- current_resource.home(user_plist[:home][0])
51
+ current_resource.home(user_plist[:home]&.first) # use &.first since home can be nil
52
52
  current_resource.shell(user_plist[:shell]&.first) # use &.first since shell can be nil
53
53
  current_resource.comment(user_plist[:comment][0])
54
54
 
@@ -66,14 +66,23 @@ class Chef
66
66
  end
67
67
  current_resource.comment(user_info.gecos)
68
68
 
69
- if new_resource.password && current_resource.password == "x"
70
- begin
71
- require "shadow"
72
- rescue LoadError
73
- @shadow_lib_ok = false
74
- else
75
- shadow_info = Shadow::Passwd.getspnam(new_resource.username)
76
- current_resource.password(shadow_info.sp_pwdp)
69
+ begin
70
+ require "shadow"
71
+ rescue LoadError
72
+ @shadow_lib_ok = false
73
+ else
74
+ @shadow_info = Shadow::Passwd.getspnam(new_resource.username)
75
+ # This conditional remains in place until we can sort out whether we need it.
76
+ # Currently removing it causes tests to fail, but that /seems/ to be mocking/setup issues.
77
+ # Some notes for context:
78
+ # 1. Ruby's ETC.getpwnam makes use of /etc/passwd file (https://github.com/ruby/etc/blob/master/ext/etc/etc.c),
79
+ # which returns "x" for a nil password. on AIX it returns a "*"
80
+ # (https://www.ibm.com/docs/bg/aix/7.2?topic=passwords-using-etcpasswd-file)
81
+ # 2. On AIX platforms ruby_shadow does not work as it does not
82
+ # store encrypted passwords in the /etc/passwd file but in /etc/security/passwd file.
83
+ # The AIX provider for user currently declares it does not support ruby-shadow.
84
+ if new_resource.password && current_resource.password == "x"
85
+ current_resource.password(@shadow_info.sp_pwdp)
77
86
  end
78
87
  end
79
88
 
@@ -83,6 +92,27 @@ class Chef
83
92
  current_resource
84
93
  end
85
94
 
95
+ # An overridable for platforms that do not support ruby shadow. This way we
96
+ # can verify that the platform supports ruby shadow before requiring that
97
+ # it be available.
98
+ def supports_ruby_shadow?
99
+ true
100
+ end
101
+
102
+ def load_shadow_options
103
+ unless @shadow_info.nil?
104
+ current_resource.inactive(@shadow_info.sp_inact&.to_i)
105
+ # sp_expire gives time since epoch in days till expiration. Need to convert that
106
+ # to time in seconds since epoch and output date format for comparison
107
+ expire_date = if @shadow_info.sp_expire.nil?
108
+ @shadow_info.sp_expire
109
+ else
110
+ Time.at(@shadow_info.sp_expire * 60 * 60 * 24).strftime("%Y-%m-%d")
111
+ end
112
+ current_resource.expire_date(expire_date)
113
+ end
114
+ end
115
+
86
116
  def define_resource_requirements
87
117
  requirements.assert(:create, :modify, :manage, :lock, :unlock) do |a|
88
118
  a.assertion { @group_name_resolved }
@@ -90,11 +120,17 @@ class Chef
90
120
  a.whyrun "group name #{new_resource.gid} does not exist. This will cause group assignment to fail. Assuming this group will have been created previously."
91
121
  end
92
122
  requirements.assert(:all_actions) do |a|
93
- a.assertion { @shadow_lib_ok }
123
+ a.assertion { !supports_ruby_shadow? || @shadow_lib_ok }
94
124
  a.failure_message Chef::Exceptions::MissingLibrary, "You must have ruby-shadow installed for password support!"
95
125
  a.whyrun "ruby-shadow is not installed. Attempts to set user password will cause failure. Assuming that this gem will have been previously installed." \
96
126
  "Note that user update converge may report false-positive on the basis of mismatched password. "
97
127
  end
128
+ requirements.assert(:all_actions) do |a|
129
+ # either neither linux-only value is set, or we need to be on Linux.
130
+ a.assertion { (!new_resource.expire_date && !new_resource.inactive) || linux? }
131
+ a.failure_message Chef::Exceptions::User, "Properties expire_date and inactive are not supported by this OS or have not been implemented for this OS yet."
132
+ a.whyrun "Properties expire_date and inactive are ignored as they are not supported by this OS or have not been implemented yet for this OS"
133
+ end
98
134
  requirements.assert(:modify, :lock, :unlock) do |a|
99
135
  a.assertion { @user_exists }
100
136
  a.failure_message(Chef::Exceptions::User, "Cannot modify user #{new_resource.username} - does not exist!")
@@ -117,11 +153,7 @@ class Chef
117
153
  new_val = new_resource.send(user_attrib)
118
154
  cur_val = current_resource.send(user_attrib)
119
155
  if !new_val.nil? && new_val.to_s != cur_val.to_s
120
- if user_attrib.to_s == "password" && new_resource.sensitive
121
- @change_desc << "change #{user_attrib} from ******** to ********"
122
- else
123
- @change_desc << "change #{user_attrib} from #{cur_val} to #{new_val}"
124
- end
156
+ @change_desc << "change #{user_attrib} from #{cur_val} to #{new_val}"
125
157
  end
126
158
  end
127
159
 
data/lib/chef/provider.rb CHANGED
@@ -113,7 +113,7 @@ class Chef
113
113
  dirname = ::File.dirname(partial)
114
114
  basename = ::File.basename(partial, ".rb")
115
115
  basename = basename[1..] if basename.start_with?("_")
116
- class_eval IO.read(::File.expand_path("#{dirname}/_#{basename}.rb", ::File.dirname(caller_locations.first.absolute_path)))
116
+ class_eval IO.read(::File.expand_path("#{dirname}/_#{basename}.rb", ::File.dirname(caller_locations.first.path)))
117
117
  end
118
118
 
119
119
  # delegate to the resource
data/lib/chef/recipe.rb CHANGED
@@ -101,7 +101,7 @@ class Chef
101
101
  end
102
102
 
103
103
  def from_yaml(string)
104
- res = ::YAML.safe_load(string)
104
+ res = ::YAML.safe_load(string, permitted_classes: [Date])
105
105
  unless res.is_a?(Hash) && res.key?("resources")
106
106
  raise ArgumentError, "YAML recipe '#{source_file}' must contain a top-level 'resources' hash (YAML sequence), i.e. 'resources:'"
107
107
  end
@@ -0,0 +1,389 @@
1
+ #
2
+ # Copyright:: Copyright 2008-2016, Chef, 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 "addressable/template" unless defined?(Addressable::Template)
19
+ require "rest-client" unless defined?(RestClient)
20
+ require "jmespath" unless defined?(JMESPath)
21
+ require "chef/dsl/rest_resource" unless defined?(Chef::DSL::RestResource)
22
+
23
+ extend Chef::DSL::RestResource
24
+
25
+ action_class do
26
+ def load_current_resource
27
+ @current_resource = new_resource.class.new(new_resource.name)
28
+
29
+ required_properties.each do |name|
30
+ requested = new_resource.send(name)
31
+ current_resource.send(name, requested)
32
+ end
33
+
34
+ return @current_resource if rest_get_all.data.empty?
35
+
36
+ resource_data = rest_get.data rescue nil
37
+ return @current_resource if resource_data.nil? || resource_data.empty?
38
+
39
+ @resource_exists = true
40
+
41
+ # Map JSON contents to defined properties
42
+ current_resource.class.rest_property_map.each do |property, match_instruction|
43
+ property_value = json_to_property(match_instruction, property, resource_data)
44
+ current_resource.send(property, property_value) unless property_value.nil?
45
+ end
46
+
47
+ current_resource
48
+ end
49
+ end
50
+
51
+ action :configure do
52
+ if resource_exists?
53
+ converge_if_changed do
54
+ data = {}
55
+
56
+ new_resource.class.rest_property_map.each do |property, match_instruction|
57
+ # Skip "creation-only" properties on modifications
58
+ next if new_resource.class.rest_post_only_properties.include?(property)
59
+
60
+ deep_merge! data, property_to_json(property, match_instruction)
61
+ end
62
+
63
+ deep_compact!(data)
64
+
65
+ rest_patch(data)
66
+ end
67
+ else
68
+ converge_by "creating resource" do
69
+ data = {}
70
+
71
+ new_resource.class.rest_property_map.each do |property, match_instruction|
72
+ deep_merge! data, property_to_json(property, match_instruction)
73
+ end
74
+
75
+ deep_compact!(data)
76
+
77
+ rest_post(data)
78
+ end
79
+ end
80
+ end
81
+
82
+ action :delete do
83
+ if resource_exists?
84
+ converge_by "deleting resource" do
85
+ rest_delete
86
+ end
87
+ else
88
+ logger.debug format("REST resource %<name>s of type %<type>s does not exist. Skipping.",
89
+ type: new_resource.name, name: id_property)
90
+ end
91
+ end
92
+
93
+ action_class do
94
+ # Override this for postprocessing device-specifics (paging, data conversion)
95
+ def rest_postprocess(response)
96
+ response
97
+ end
98
+
99
+ # Override this for error handling of device-specifics (readable error messages)
100
+ def rest_errorhandler(error_obj)
101
+ error_obj
102
+ end
103
+
104
+ private
105
+
106
+ def resource_exists?
107
+ @resource_exists
108
+ end
109
+
110
+ def required_properties
111
+ current_resource.class.properties.select { |_, v| v.required? }.except(:name).keys
112
+ end
113
+
114
+ # Return changed value or nil for delta current->new
115
+ def changed_value(property)
116
+ new_value = new_resource.send(property)
117
+ return new_value if current_resource.nil?
118
+
119
+ current_value = current_resource.send(property)
120
+
121
+ return current_value if required_properties.include? property
122
+
123
+ new_value == current_value ? nil : new_value
124
+ end
125
+
126
+ def id_property
127
+ current_resource.class.identity_attr
128
+ end
129
+
130
+ # Map properties to their current values
131
+ def property_map
132
+ map = {}
133
+
134
+ current_resource.class.state_properties.each do |property|
135
+ name = property.options[:name]
136
+
137
+ map[name] = current_resource.send(name)
138
+ end
139
+
140
+ map[id_property] = current_resource.send(id_property)
141
+
142
+ map
143
+ end
144
+
145
+ # Map part of a JSON (Hash) to resource property via JMESPath or user-supplied function
146
+ def json_to_property(match_instruction, property, resource_data)
147
+ case match_instruction
148
+ when String
149
+ JMESPath.search(match_instruction, resource_data)
150
+ when Symbol
151
+ function = "#{property}_from_json".to_sym
152
+ raise "#{new_resource.name} missing #{function} method" unless self.class.protected_method_defined?(function)
153
+
154
+ send(function, resource_data) || {}
155
+ else
156
+ raise TypeError, "Did not expect match type #{match_instruction.class}"
157
+ end
158
+ end
159
+
160
+ # Map resource contents into a JSON (Hash) via JMESPath-like syntax or user-supplied function
161
+ def property_to_json(property, match_instruction)
162
+ case match_instruction
163
+ when String
164
+ bury(match_instruction, changed_value(property))
165
+ when Symbol
166
+ function = "#{property}_to_json".to_sym
167
+ raise "#{new_resource.name} missing #{function} method" unless self.class.protected_method_defined?(function)
168
+
169
+ value = new_resource.send(property)
170
+ changed_value(property).nil? ? {} : send(function, value)
171
+ else
172
+ raise TypeError, "Did not expect match type #{match_instruction.class}"
173
+ end
174
+ end
175
+
176
+ def rest_url_collection
177
+ current_resource.class.rest_api_collection
178
+ end
179
+
180
+ # Resource document URL after RFC 6570 template evaluation via properties substitution
181
+ def rest_url_document
182
+ template = ::Addressable::Template.new(current_resource.class.rest_api_document)
183
+ template.expand(property_map).to_s
184
+ end
185
+
186
+ # Convenience method for conditional requires
187
+ def conditionally_require_on_setting(property, dependent_properties)
188
+ dependent_properties = Array(dependent_properties)
189
+
190
+ requirements.assert(:configure) do |a|
191
+ a.assertion do
192
+ # Needs to be set and truthy to require dependent properties
193
+ if new_resource.send(property)
194
+ dependent_properties.all? { |dep_prop| new_resource.property_is_set?(dep_prop) }
195
+ else
196
+ true
197
+ end
198
+ end
199
+
200
+ message = format("Setting property :%<property>s requires properties :%<properties>s to be set as well on resource %<resource_name>s",
201
+ property: property,
202
+ properties: dependent_properties.join(", :"),
203
+ resource_name: current_resource.to_s)
204
+
205
+ a.failure_message message
206
+ end
207
+ end
208
+
209
+ # Generic REST helpers
210
+
211
+ def rest_get_all
212
+ response = api_connection.get(rest_url_collection)
213
+
214
+ rest_postprocess(response)
215
+ rescue RestClient::Exception => e
216
+ rest_errorhandler(e)
217
+ end
218
+
219
+ def rest_get
220
+ response = api_connection.get(rest_url_document)
221
+
222
+ response = rest_postprocess(response)
223
+
224
+ first_only = current_resource.class.rest_api_document_first_element_only
225
+ response.data = response.data.first if first_only && response.data.is_a?(Array)
226
+
227
+ response
228
+ rescue RestClient::Exception => e
229
+ rest_errorhandler(e)
230
+ end
231
+
232
+ def rest_post(data)
233
+ data.merge! rest_identity_values
234
+
235
+ response = api_connection.post(rest_url_collection, data: data)
236
+
237
+ rest_postprocess(response)
238
+ rescue RestClient::Exception => e
239
+ rest_errorhandler(e)
240
+ end
241
+
242
+ def rest_put(data)
243
+ data.merge! rest_identity_values
244
+
245
+ response = api_connection.put(rest_url_collection, data: data)
246
+
247
+ rest_postprocess(response)
248
+ rescue RestClient::Exception => e
249
+ rest_errorhandler(e)
250
+ end
251
+
252
+ def rest_patch(data)
253
+ response = api_connection.patch(rest_url_document, data: data)
254
+
255
+ rest_postprocess(response)
256
+ rescue RestClient::Exception => e
257
+ rest_errorhandler(e)
258
+ end
259
+
260
+ def rest_delete
261
+ response = api_connection.delete(rest_url_document)
262
+
263
+ rest_postprocess(response)
264
+ rescue RestClient::Exception => e
265
+ rest_errorhandler(e)
266
+ end
267
+
268
+ # REST parameter mapping
269
+
270
+ # Return number of parameters needed to identify a resource (pre- and post-creation)
271
+ def rest_arity
272
+ rest_identity_map.keys.count
273
+ end
274
+
275
+ # Return mapping of template placeholders to property value of identity parameters
276
+ def rest_identity_values
277
+ data = {}
278
+
279
+ rest_identity_map.each do |rfc_template, property|
280
+ property_value = new_resource.send(property)
281
+ data.merge! bury(rfc_template, property_value)
282
+ end
283
+
284
+ data
285
+ end
286
+
287
+ def rest_identity_map
288
+ rest_identity_explicit || rest_identity_implicit
289
+ end
290
+
291
+ # Accept direct mapping like { "svm.name" => :name } for specifying the x-ary identity of a resource
292
+ def rest_identity_explicit
293
+ current_resource.class.rest_identity_map
294
+ end
295
+
296
+ # Parse document URL for RFC 6570 templates and map them to resource properties.
297
+ #
298
+ # Examples:
299
+ # Query based: "/api/protocols/san/igroups?name={name}&svm.name={svm}": { "name" => :name, "svm.name" => :svm }
300
+ # Path based: "/api/v1/{address}": { "address" => :address }
301
+ #
302
+ def rest_identity_implicit
303
+ template_url = current_resource.class.rest_api_document
304
+
305
+ rfc_template = ::Addressable::Template.new(template_url)
306
+ rfc_template_vars = rfc_template.variables
307
+
308
+ # Shortcut for 0-ary resources
309
+ return {} if rfc_template_vars.empty?
310
+
311
+ if query_based_selection?
312
+ uri_query = URI.parse(template_url).query
313
+
314
+ if CGI.parse(uri_query).values.any?(&:empty?)
315
+ raise "Need explicit identity mapping, as URL does not contain query parameters for all templates"
316
+ end
317
+
318
+ path_variables = CGI.parse(uri_query).keys
319
+ elsif path_based_selection?
320
+ path_variables = rfc_template_vars
321
+ else
322
+ # There is also
323
+ raise "Unknown type of resource selection. Document URL does not seem to be path- or query-based?"
324
+ end
325
+
326
+ identity_map = {}
327
+ path_variables.each_with_index do |v, i|
328
+ next if rfc_template_vars[i].nil? # Not mapped to property, assume metaparameter
329
+
330
+ identity_map[v] = rfc_template_vars[i].to_sym
331
+ end
332
+
333
+ identity_map
334
+ end
335
+
336
+ def query_based_selection?
337
+ template_url = current_resource.class.rest_api_document
338
+
339
+ # Will throw exception on presence of RFC 6570 templates
340
+ URI.parse(template_url)
341
+ true
342
+ rescue URI::InvalidURIError => _e
343
+ false
344
+ end
345
+
346
+ def path_based_selection?
347
+ !query_based_selection?
348
+ end
349
+
350
+ def api_connection
351
+ Chef.run_context.transport.connection
352
+ end
353
+
354
+ # Remove all empty keys (recusively) from Hash.
355
+ # @see https://stackoverflow.com/questions/56457020/#answer-56458673
356
+ def deep_compact!(hsh)
357
+ raise TypeError unless hsh.is_a? Hash
358
+
359
+ hsh.each do |_, v|
360
+ deep_compact!(v) if v.is_a? Hash
361
+ end.reject! { |_, v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }
362
+ end
363
+
364
+ # Deep merge two hashes
365
+ # @see https://stackoverflow.com/questions/41109599#answer-41109737
366
+ def deep_merge!(hsh1, hsh2)
367
+ raise TypeError unless hsh1.is_a?(Hash) && hsh2.is_a?(Hash)
368
+
369
+ hsh1.merge!(hsh2) { |_, v1, v2| deep_merge!(v1, v2) }
370
+ end
371
+
372
+ # Create nested hashes from JMESPath syntax.
373
+ def bury(path, value)
374
+ raise TypeError unless path.is_a?(String)
375
+
376
+ arr = path.split(".")
377
+ ret = {}
378
+
379
+ if arr.count == 1
380
+ ret[arr.first] = value
381
+
382
+ ret
383
+ else
384
+ partial_path = arr[0..-2].join(".")
385
+
386
+ bury(partial_path, bury(arr.last, value))
387
+ end
388
+ end
389
+ end
@@ -22,7 +22,6 @@ require_relative "../resource"
22
22
  class Chef
23
23
  class Resource
24
24
  class Alternatives < Chef::Resource
25
- unified_mode true
26
25
 
27
26
  provides(:alternatives) { true }
28
27
 
@@ -21,7 +21,6 @@ require_relative "package"
21
21
  class Chef
22
22
  class Resource
23
23
  class AptPackage < Chef::Resource::Package
24
- unified_mode true
25
24
 
26
25
  provides :apt_package, target_mode: true
27
26
  provides :package, platform_family: "debian", target_mode: true