chef 18.4.2 → 18.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (223) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -1
  3. data/chef.gemspec +7 -7
  4. data/lib/chef/application/client.rb +12 -0
  5. data/lib/chef/client.rb +10 -16
  6. data/lib/chef/compliance/runner.rb +10 -0
  7. data/lib/chef/cookbook/chefignore.rb +4 -1
  8. data/lib/chef/cookbook/cookbook_version_loader.rb +1 -1
  9. data/lib/chef/cookbook/synchronizer.rb +7 -1
  10. data/lib/chef/cookbook_manifest.rb +2 -2
  11. data/lib/chef/file_access_control/unix.rb +9 -9
  12. data/lib/chef/file_cache.rb +17 -2
  13. data/lib/chef/file_content_management/deploy/target_io.rb +29 -0
  14. data/lib/chef/file_content_management/deploy.rb +4 -1
  15. data/lib/chef/formatters/doc.rb +1 -1
  16. data/lib/chef/mixin/file_class.rb +3 -1
  17. data/lib/chef/mixin/get_source_from_package.rb +1 -1
  18. data/lib/chef/mixin/openssl_helper.rb +1 -1
  19. data/lib/chef/node/attribute.rb +3 -11
  20. data/lib/chef/node/immutable_collections.rb +15 -8
  21. data/lib/chef/node/mixin/state_tracking.rb +6 -3
  22. data/lib/chef/node.rb +1 -1
  23. data/lib/chef/policy_builder/policyfile.rb +8 -0
  24. data/lib/chef/provider/.gitkeep +0 -0
  25. data/lib/chef/provider/cookbook_file.rb +1 -1
  26. data/lib/chef/provider/cron.rb +1 -1
  27. data/lib/chef/provider/directory.rb +15 -15
  28. data/lib/chef/provider/file.rb +42 -29
  29. data/lib/chef/provider/git.rb +8 -8
  30. data/lib/chef/provider/group/aix.rb +1 -1
  31. data/lib/chef/provider/group/dscl.rb +1 -1
  32. data/lib/chef/provider/group/gpasswd.rb +2 -2
  33. data/lib/chef/provider/group/groupadd.rb +1 -1
  34. data/lib/chef/provider/group/groupmod.rb +2 -2
  35. data/lib/chef/provider/group/pw.rb +2 -2
  36. data/lib/chef/provider/group/solaris.rb +2 -2
  37. data/lib/chef/provider/group/usermod.rb +2 -2
  38. data/lib/chef/provider/group.rb +1 -1
  39. data/lib/chef/provider/http_request.rb +2 -3
  40. data/lib/chef/provider/ifconfig/aix.rb +1 -1
  41. data/lib/chef/provider/ifconfig/debian.rb +3 -3
  42. data/lib/chef/provider/ifconfig/redhat.rb +1 -1
  43. data/lib/chef/provider/ifconfig.rb +1 -1
  44. data/lib/chef/provider/link.rb +10 -10
  45. data/lib/chef/provider/mount/aix.rb +4 -4
  46. data/lib/chef/provider/mount/linux.rb +4 -4
  47. data/lib/chef/provider/mount/mount.rb +11 -11
  48. data/lib/chef/provider/package/apt.rb +2 -11
  49. data/lib/chef/provider/package/bff.rb +3 -3
  50. data/lib/chef/provider/package/chocolatey.rb +54 -24
  51. data/lib/chef/provider/package/dpkg.rb +3 -3
  52. data/lib/chef/provider/package/freebsd/base.rb +1 -1
  53. data/lib/chef/provider/package/habitat.rb +5 -3
  54. data/lib/chef/provider/package/ips.rb +2 -2
  55. data/lib/chef/provider/package/openbsd.rb +3 -2
  56. data/lib/chef/provider/package/pacman.rb +4 -4
  57. data/lib/chef/provider/package/paludis.rb +2 -2
  58. data/lib/chef/provider/package/portage.rb +1 -1
  59. data/lib/chef/provider/package/powershell.rb +1 -0
  60. data/lib/chef/provider/package/rpm.rb +2 -2
  61. data/lib/chef/provider/package/smartos.rb +2 -2
  62. data/lib/chef/provider/package/snap.rb +2 -1
  63. data/lib/chef/provider/package/snap_tm.rb +79 -0
  64. data/lib/chef/provider/package/solaris.rb +4 -4
  65. data/lib/chef/provider/package/zypper.rb +4 -5
  66. data/lib/chef/provider/package.rb +1 -1
  67. data/lib/chef/provider/remote_directory.rb +5 -5
  68. data/lib/chef/provider/remote_file/http.rb +2 -3
  69. data/lib/chef/provider/remote_file.rb +1 -1
  70. data/lib/chef/provider/route.rb +9 -9
  71. data/lib/chef/provider/service/aix.rb +1 -1
  72. data/lib/chef/provider/service/aixinit.rb +4 -4
  73. data/lib/chef/provider/service/arch.rb +6 -6
  74. data/lib/chef/provider/service/debian.rb +5 -5
  75. data/lib/chef/provider/service/freebsd.rb +7 -7
  76. data/lib/chef/provider/service/gentoo.rb +5 -5
  77. data/lib/chef/provider/service/init.rb +2 -2
  78. data/lib/chef/provider/service/insserv.rb +2 -2
  79. data/lib/chef/provider/service/invokercd.rb +1 -1
  80. data/lib/chef/provider/service/openbsd.rb +7 -7
  81. data/lib/chef/provider/service/redhat.rb +3 -3
  82. data/lib/chef/provider/service/solaris.rb +2 -2
  83. data/lib/chef/provider/service/systemd.rb +2 -2
  84. data/lib/chef/provider/service/upstart.rb +2 -2
  85. data/lib/chef/provider/service/windows.rb +0 -1
  86. data/lib/chef/provider/subversion.rb +8 -8
  87. data/lib/chef/provider/systemd_unit.rb +3 -3
  88. data/lib/chef/provider/template.rb +1 -1
  89. data/lib/chef/provider/user/aix.rb +3 -3
  90. data/lib/chef/provider/user/linux.rb +7 -2
  91. data/lib/chef/provider/user/pw.rb +3 -3
  92. data/lib/chef/provider/user/solaris.rb +7 -7
  93. data/lib/chef/provider/user.rb +7 -8
  94. data/lib/chef/provider/yum_repository.rb +1 -3
  95. data/lib/chef/provider/zypper_repository.rb +1 -1
  96. data/lib/chef/providers.rb +1 -0
  97. data/lib/chef/resource/.gitkeep +0 -0
  98. data/lib/chef/resource/alternatives.rb +2 -2
  99. data/lib/chef/resource/apt_preference.rb +1 -1
  100. data/lib/chef/resource/apt_repository.rb +7 -9
  101. data/lib/chef/resource/apt_update.rb +3 -3
  102. data/lib/chef/resource/bff_package.rb +1 -1
  103. data/lib/chef/resource/chef_client_config.rb +3 -2
  104. data/lib/chef/resource/chef_client_systemd_timer.rb +5 -0
  105. data/lib/chef/resource/chef_gem.rb +1 -1
  106. data/lib/chef/resource/chef_sleep.rb +1 -1
  107. data/lib/chef/resource/cookbook_file.rb +1 -1
  108. data/lib/chef/resource/cron/cron.rb +1 -1
  109. data/lib/chef/resource/cron/cron_d.rb +1 -1
  110. data/lib/chef/resource/cron_access.rb +1 -1
  111. data/lib/chef/resource/directory.rb +1 -1
  112. data/lib/chef/resource/dpkg_package.rb +1 -1
  113. data/lib/chef/resource/execute.rb +8 -6
  114. data/lib/chef/resource/file/verification/json.rb +1 -1
  115. data/lib/chef/resource/file/verification/systemd_unit.rb +1 -1
  116. data/lib/chef/resource/file/verification/yaml.rb +1 -1
  117. data/lib/chef/resource/file.rb +1 -1
  118. data/lib/chef/resource/freebsd_package.rb +2 -2
  119. data/lib/chef/resource/group.rb +1 -1
  120. data/lib/chef/resource/habitat/habitat_package.rb +1 -1
  121. data/lib/chef/resource/habitat/habitat_sup.rb +9 -9
  122. data/lib/chef/resource/habitat/habitat_sup_systemd.rb +2 -2
  123. data/lib/chef/resource/habitat_install.rb +5 -4
  124. data/lib/chef/resource/hostname.rb +11 -10
  125. data/lib/chef/resource/http_request.rb +1 -1
  126. data/lib/chef/resource/ifconfig.rb +1 -1
  127. data/lib/chef/resource/inspec_input.rb +3 -1
  128. data/lib/chef/resource/inspec_waiver.rb +1 -1
  129. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  130. data/lib/chef/resource/ips_package.rb +2 -2
  131. data/lib/chef/resource/kernel_module.rb +2 -2
  132. data/lib/chef/resource/link.rb +1 -1
  133. data/lib/chef/resource/locale.rb +2 -2
  134. data/lib/chef/resource/mount.rb +1 -1
  135. data/lib/chef/resource/notify_group.rb +1 -1
  136. data/lib/chef/resource/ohai.rb +1 -1
  137. data/lib/chef/resource/ohai_hint.rb +1 -1
  138. data/lib/chef/resource/openbsd_package.rb +2 -2
  139. data/lib/chef/resource/package.rb +1 -1
  140. data/lib/chef/resource/pacman_package.rb +1 -1
  141. data/lib/chef/resource/paludis_package.rb +1 -1
  142. data/lib/chef/resource/portage_package.rb +1 -1
  143. data/lib/chef/resource/powershell_package.rb +4 -0
  144. data/lib/chef/resource/reboot.rb +1 -1
  145. data/lib/chef/resource/remote_directory.rb +1 -1
  146. data/lib/chef/resource/remote_file.rb +1 -1
  147. data/lib/chef/resource/rhsm_errata.rb +1 -1
  148. data/lib/chef/resource/rhsm_errata_level.rb +1 -1
  149. data/lib/chef/resource/rhsm_register.rb +1 -1
  150. data/lib/chef/resource/rhsm_repo.rb +3 -4
  151. data/lib/chef/resource/rhsm_subscription.rb +8 -9
  152. data/lib/chef/resource/route.rb +1 -1
  153. data/lib/chef/resource/rpm_package.rb +1 -1
  154. data/lib/chef/resource/scm/git.rb +1 -1
  155. data/lib/chef/resource/scm/subversion.rb +1 -1
  156. data/lib/chef/resource/selinux/common_helpers.rb +1 -1
  157. data/lib/chef/resource/selinux_boolean.rb +1 -1
  158. data/lib/chef/resource/selinux_fcontext.rb +3 -3
  159. data/lib/chef/resource/selinux_install.rb +1 -1
  160. data/lib/chef/resource/selinux_login.rb +1 -1
  161. data/lib/chef/resource/selinux_module.rb +5 -5
  162. data/lib/chef/resource/selinux_permissive.rb +2 -2
  163. data/lib/chef/resource/selinux_port.rb +2 -2
  164. data/lib/chef/resource/selinux_state.rb +2 -2
  165. data/lib/chef/resource/selinux_user.rb +1 -1
  166. data/lib/chef/resource/smartos_package.rb +2 -2
  167. data/lib/chef/resource/snap_package.rb +24 -1
  168. data/lib/chef/resource/solaris_package.rb +1 -1
  169. data/lib/chef/resource/ssh_known_hosts_entry.rb +1 -1
  170. data/lib/chef/resource/sudo.rb +5 -5
  171. data/lib/chef/resource/support/client.erb +1 -1
  172. data/lib/chef/resource/swap_file.rb +6 -6
  173. data/lib/chef/resource/sysctl.rb +6 -5
  174. data/lib/chef/resource/systemd_unit.rb +1 -1
  175. data/lib/chef/resource/template.rb +1 -1
  176. data/lib/chef/resource/timezone.rb +5 -5
  177. data/lib/chef/resource/user/aix_user.rb +2 -2
  178. data/lib/chef/resource/user/linux_user.rb +2 -2
  179. data/lib/chef/resource/user/pw_user.rb +2 -2
  180. data/lib/chef/resource/user/solaris_user.rb +2 -2
  181. data/lib/chef/resource/user_ulimit.rb +1 -1
  182. data/lib/chef/resource/yum_repository.rb +1 -1
  183. data/lib/chef/resource/zypper_package.rb +2 -2
  184. data/lib/chef/resource/zypper_repository.rb +2 -2
  185. data/lib/chef/run_lock.rb +3 -0
  186. data/lib/chef/scan_access_control.rb +6 -6
  187. data/lib/chef/target_io/dir.rb +12 -0
  188. data/lib/chef/target_io/etc.rb +16 -0
  189. data/lib/chef/target_io/file.rb +12 -0
  190. data/lib/chef/target_io/fileutils.rb +12 -0
  191. data/lib/chef/target_io/http.rb +22 -0
  192. data/lib/chef/target_io/io.rb +12 -0
  193. data/lib/chef/target_io/shadow.rb +44 -0
  194. data/lib/chef/target_io/train/dir.rb +69 -0
  195. data/lib/chef/target_io/train/etc.rb +112 -0
  196. data/lib/chef/target_io/train/file.rb +219 -0
  197. data/lib/chef/target_io/train/fileutils.rb +220 -0
  198. data/lib/chef/target_io/train/http.rb +117 -0
  199. data/lib/chef/target_io/train/io.rb +13 -0
  200. data/lib/chef/target_io/train/shadow.rb +52 -0
  201. data/lib/chef/target_io/train_compat.rb +7 -0
  202. data/lib/chef/target_io.rb +9 -0
  203. data/lib/chef/util/backup.rb +1 -1
  204. data/lib/chef/util/diff.rb +14 -1
  205. data/lib/chef/util/file_edit.rb +4 -4
  206. data/lib/chef/version.rb +1 -1
  207. data/lib/chef.rb +2 -0
  208. data/spec/functional/resource/remote_file_spec.rb +1 -1
  209. data/spec/integration/client/fips_spec.rb +11 -2
  210. data/spec/integration/client/open_ssl_spec.rb +20 -0
  211. data/spec/spec_helper.rb +3 -1
  212. data/spec/support/platform_helpers.rb +20 -7
  213. data/spec/unit/client_spec.rb +0 -16
  214. data/spec/unit/file_cache_spec.rb +64 -0
  215. data/spec/unit/mixin/openssl_helper_spec.rb +6 -1
  216. data/spec/unit/provider/apt_repository_spec.rb +1 -1
  217. data/spec/unit/provider/package/chocolatey_spec.rb +17 -12
  218. data/spec/unit/provider/package/windows_spec.rb +5 -5
  219. data/spec/unit/provider/package/zypper_spec.rb +0 -10
  220. data/spec/unit/provider/route_spec.rb +6 -4
  221. data/spec/unit/resource/rhsm_repo_spec.rb +1 -0
  222. data/spec/unit/resource/rhsm_subscription_spec.rb +2 -0
  223. metadata +31 -10
@@ -21,7 +21,7 @@ class Chef
21
21
  class Provider
22
22
  class Mount
23
23
  class Aix < Chef::Provider::Mount::Mount
24
- provides :mount, platform: "aix"
24
+ provides :mount, platform: "aix", target_mode: true
25
25
 
26
26
  # Override for aix specific handling
27
27
  def initialize(new_resource, run_context)
@@ -163,7 +163,7 @@ class Chef
163
163
  # disable, then enable.
164
164
  disable_fs
165
165
  end
166
- ::File.open("/etc/filesystems", "a") do |fstab|
166
+ ::TargetIO::File.open("/etc/filesystems", "a") do |fstab|
167
167
  fstab.puts("\n\n#{@new_resource.mount_point}:")
168
168
  if network_device?
169
169
  device_details = device_fstab.split(":")
@@ -194,7 +194,7 @@ class Chef
194
194
  contents = []
195
195
  if @current_resource.enabled
196
196
  found_device = false
197
- ::File.open("/etc/filesystems", "r").each_line do |line|
197
+ ::TargetIO::File.open("/etc/filesystems", "r").each_line do |line|
198
198
  case line
199
199
  when %r{^/.+:\s*$}
200
200
  if /#{Regexp.escape(@new_resource.mount_point)}+:/.match?(line)
@@ -207,7 +207,7 @@ class Chef
207
207
  contents << line
208
208
  end
209
209
  end
210
- ::File.open("/etc/filesystems", "w") do |fstab|
210
+ ::TargetIO::File.open("/etc/filesystems", "w") do |fstab|
211
211
  contents.each { |line| fstab.puts line }
212
212
  end
213
213
  else
@@ -23,7 +23,7 @@ class Chef
23
23
  class Mount
24
24
  class Linux < Chef::Provider::Mount::Mount
25
25
 
26
- provides :mount, os: "linux"
26
+ provides :mount, os: "linux", target_mode: true
27
27
 
28
28
  # Check to see if the volume is mounted.
29
29
  # "findmnt" outputs the mount points with volume.
@@ -39,8 +39,8 @@ class Chef
39
39
 
40
40
  def mounted?
41
41
  mounted = false
42
- real_mount_point = if ::File.exist? @new_resource.mount_point
43
- ::File.realpath(@new_resource.mount_point)
42
+ real_mount_point = if ::TargetIO::File.exist? @new_resource.mount_point
43
+ ::TargetIO::File.realpath(@new_resource.mount_point)
44
44
  else
45
45
  @new_resource.mount_point
46
46
  end
@@ -83,4 +83,4 @@ class Chef
83
83
  end
84
84
  end
85
85
  end
86
- end
86
+ end
@@ -42,9 +42,9 @@ class Chef
42
42
 
43
43
  def mountable?
44
44
  # only check for existence of non-remote devices
45
- if device_should_exist? && !::File.exist?(device_real)
45
+ if device_should_exist? && !::TargetIO::File.exist?(device_real)
46
46
  raise Chef::Exceptions::Mount, "Device #{@new_resource.device} does not exist"
47
- elsif @new_resource.mount_point != "none" && !::File.exist?(@new_resource.mount_point)
47
+ elsif @new_resource.mount_point != "none" && !::TargetIO::File.exist?(@new_resource.mount_point)
48
48
  raise Chef::Exceptions::Mount, "Mount point #{@new_resource.mount_point} does not exist"
49
49
  end
50
50
 
@@ -54,11 +54,11 @@ class Chef
54
54
  def enabled?
55
55
  # Check to see if there is a entry in /etc/fstab. Last entry for a volume wins.
56
56
  enabled = false
57
- unless ::File.exist?("/etc/fstab")
57
+ unless ::TargetIO::File.exist?("/etc/fstab")
58
58
  logger.debug "/etc/fstab not found, treating mount as not-enabled"
59
59
  return
60
60
  end
61
- ::File.foreach("/etc/fstab") do |line|
61
+ ::TargetIO::File.foreach("/etc/fstab") do |line|
62
62
  case line
63
63
  when /^[#\s]/
64
64
  next
@@ -81,8 +81,8 @@ class Chef
81
81
  # "mount" outputs the mount points as real paths. Convert
82
82
  # the mount_point of the resource to a real path in case it
83
83
  # contains symlinks in its parents dirs.
84
- real_mount_point = if ::File.exist? @new_resource.mount_point
85
- ::File.realpath(@new_resource.mount_point)
84
+ real_mount_point = if ::TargetIO::File.exist? @new_resource.mount_point
85
+ ::TargetIO::File.realpath(@new_resource.mount_point)
86
86
  else
87
87
  @new_resource.mount_point
88
88
  end
@@ -168,7 +168,7 @@ class Chef
168
168
  # and order will remain the same.
169
169
  edit_fstab
170
170
  else
171
- ::File.open("/etc/fstab", "a") do |fstab|
171
+ ::TargetIO::File.open("/etc/fstab", "a") do |fstab|
172
172
  fstab.puts("#{device_fstab} #{@new_resource.mount_point} #{@new_resource.fstype} #{@new_resource.options.nil? ? default_mount_options : @new_resource.options.join(",")} #{@new_resource.dump} #{@new_resource.pass}")
173
173
  logger.trace("#{@new_resource} is enabled at #{@new_resource.mount_point}")
174
174
  end
@@ -229,12 +229,12 @@ class Chef
229
229
  if network_device?
230
230
  # ignore trailing slash
231
231
  Regexp.escape(device_real) + "/?"
232
- elsif ::File.symlink?(device_real)
232
+ elsif ::TargetIO::File.symlink?(device_real)
233
233
  # This regular expression tries to match device_real. If that does not match it will try to match the target of device_real.
234
234
  # So given a symlink like this:
235
235
  # /dev/mapper/vgroot-tmp.vol -> /dev/dm-9
236
236
  # First it will try to match "/dev/mapper/vgroot-tmp.vol". If there is no match it will try matching for "/dev/dm-9".
237
- "(?:#{Regexp.escape(device_real)}|#{Regexp.escape(::File.expand_path(::File.readlink(device_real), ::File.dirname(device_real)))})"
237
+ "(?:#{Regexp.escape(device_real)}|#{Regexp.escape(::File.expand_path(::TargetIO::File.readlink(device_real), ::File.dirname(device_real)))})"
238
238
  else
239
239
  Regexp.escape(device_real)
240
240
  end
@@ -261,7 +261,7 @@ class Chef
261
261
  contents = []
262
262
 
263
263
  found = false
264
- ::File.readlines("/etc/fstab").reverse_each do |line|
264
+ ::TargetIO::File.readlines("/etc/fstab").reverse_each do |line|
265
265
  if !found && line =~ /^#{device_fstab_regex}\s+#{Regexp.escape(@new_resource.mount_point)}\s/
266
266
  found = true
267
267
  if remove
@@ -276,7 +276,7 @@ class Chef
276
276
  end
277
277
  end
278
278
 
279
- ::File.open("/etc/fstab", "w") do |fstab|
279
+ ::TargetIO::File.open("/etc/fstab", "w") do |fstab|
280
280
  contents.reverse_each { |line| fstab.puts line }
281
281
  end
282
282
  else
@@ -124,11 +124,6 @@ class Chef
124
124
 
125
125
  private
126
126
 
127
- # @return [String] package name with or without anchors attached to it.
128
- def resolve_package(pkg)
129
- new_resource.anchor_package_regex ? "^#{pkg}$" : pkg
130
- end
131
-
132
127
  # @return [String] version of apt-get which is installed
133
128
  def apt_version
134
129
  @apt_version ||= shell_out("apt-get --version").stdout.match(/^apt (\S+)/)[1]
@@ -179,12 +174,10 @@ class Chef
179
174
  end
180
175
 
181
176
  def resolve_package_versions(pkg)
182
- # apt-cache considers package names as regex by default. The anchor_package_regex flag will decide whether to match name exact string or not
183
- pkg_name = resolve_package(pkg)
184
177
  current_version = nil
185
178
  candidate_version = nil
186
179
  all_versions = []
187
- run_noninteractive("apt-cache", default_release_options, "policy", pkg_name).stdout.each_line do |line|
180
+ run_noninteractive("apt-cache", default_release_options, "policy", pkg).stdout.each_line do |line|
188
181
  case line
189
182
  when /^\s{2}Installed: (.+)$/
190
183
  current_version = ( $1 != "(none)" ) ? $1 : nil
@@ -223,9 +216,7 @@ class Chef
223
216
  end
224
217
 
225
218
  def resolve_virtual_package_name(pkg)
226
- # apt-cache considers package names as regex by default. The anchor_package_regex flag will decide whether to match name exact string or not
227
- pkg_name = resolve_package(pkg)
228
- showpkg = run_noninteractive("apt-cache", "showpkg", pkg_name).stdout
219
+ showpkg = run_noninteractive("apt-cache", "showpkg", pkg).stdout
229
220
  partitions = showpkg.rpartition(/Reverse Provides: ?#{$/}/)
230
221
  return nil if partitions[0] == "" && partitions[1] == "" # not found in output
231
222
 
@@ -25,8 +25,8 @@ class Chef
25
25
  class Package
26
26
  class Bff < Chef::Provider::Package
27
27
 
28
- provides :package, os: "aix"
29
- provides :bff_package
28
+ provides :package, os: "aix", target_mode: true
29
+ provides :bff_package, target_mode: true
30
30
 
31
31
  include Chef::Mixin::GetSourceFromPackage
32
32
 
@@ -134,7 +134,7 @@ class Chef
134
134
  end
135
135
 
136
136
  def package_source_found?
137
- @package_source_found ||= new_resource.source && ::File.exist?(new_resource.source)
137
+ @package_source_found ||= new_resource.source && ::TargetIO::File.exist?(new_resource.source)
138
138
  end
139
139
 
140
140
  end
@@ -144,7 +144,11 @@ class Chef
144
144
  def check_resource_semantics!; end
145
145
 
146
146
  def get_choco_version
147
- @get_choco_version ||= powershell_exec!("#{choco_exe} --version").result
147
+ # We need a different way to get the version than by simply calling "choco --version".
148
+ # If the license file is installed (for business customers) but not the Chocolatey.Extension (because you're using the choco resource to install it)
149
+ # then you get a license error. This method bypasses that by getting the version from the exe directly instead of invoking it.
150
+ # deprecated: @get_choco_version ||= powershell_exec!("#{choco_exe} --version").result
151
+ @get_choco_version ||= powershell_exec!("Get-ItemProperty #{choco_exe} | select-object -expandproperty versioninfo | select-object -expandproperty productversion").result
148
152
  end
149
153
 
150
154
  # Choco V2 uses 'Search' for remote repositories and 'List' for local packages
@@ -167,22 +171,34 @@ class Chef
167
171
  true
168
172
  end
169
173
 
170
- # walk the collection to find peer resources to ensure that
171
- # we get as much of the cache this run as possible. Unified mode
172
- # sub-resources will, of course, be incremental with this, since we can't
173
- # grab them in advance, but even in that case we're still way, way
174
- # more efficient with our queries...
174
+ # Find the set of packages to ask the chocolatey server about
175
+ #
176
+ # if walk_resource_tree is true, this finds _all_ of the packages that
177
+ # we have referenced anywhere in our recipes - this is so we can
178
+ # attempt to query them all in a single transaction. However,
179
+ # currently we don't do that - see the comment on available_packages
180
+ # for details of the why, but the TL;DR is that the public chocolatey
181
+ # servers do not support `or` type queries properly.
182
+ #
183
+ # If walk_resource_tree is false, we don't do any of that - we just filter
184
+ # the package list based on cache data. This is the default due to reasons
185
+ # explained in the comment on available_packages - the goal is to eventually
186
+ # turn this back on, hence the default false parameter here.
175
187
  #
176
188
  # @return [Array] List of chocolatey packages referenced in the run list
177
- def collect_package_requests(ignore_list: [])
189
+ def collect_package_requests(ignore_list: [], walk_resource_tree: false)
178
190
  return ["*"] if new_resource.bulk_query || Chef::Config[:always_use_bulk_chocolatey_package_list]
179
191
 
180
- # Get to the root of the resource collection
181
- rc = run_context.parent_run_context || run_context
182
- rc = rc.parent_run_context while rc.parent_run_context
192
+ if walk_resource_tree
193
+ # Get to the root of the resource collection
194
+ rc = run_context.parent_run_context || run_context
195
+ rc = rc.parent_run_context while rc.parent_run_context
183
196
 
184
- package_collection = package_name_array
185
- package_collection += nested_package_resources(rc.resource_collection)
197
+ package_collection = package_name_array
198
+ package_collection += nested_package_resources(rc.resource_collection)
199
+ else
200
+ package_collection = package_name_array
201
+ end
186
202
  # downcase the array and uniq. sorted for easier testing...
187
203
  package_collection.uniq.sort.filter { |pkg| !ignore_list.include?(pkg) }
188
204
  end
@@ -339,22 +355,33 @@ class Chef
339
355
  @@choco_available_packages[new_resource.list_options] = {}
340
356
  end
341
357
 
342
- # Attempt to get everything we need in a single query.
343
- # Grab 25 packages at a time at most, to avoid hurting servers too badly
358
+ # This would previously grab 25 packages at a time, which previously worked - however,
359
+ # upstream changed and it turns out this was only working by accident - see
360
+ # https://github.com/chocolatey/choco/issues/2116 for this. So the TL;DR ends up
361
+ # being that this can be re-enabled when the chocolatey server actually supports an
362
+ # or operator. So it makes sense to leave the logic here for this split, while we
363
+ # work with upstream to get this to be a working feature there
364
+ #
365
+ # Foot guns: there is a --id-starts-with for chocolatey, which you'd think would work,
366
+ # but that actually fails on public chocolatey as well, because it seems to do the filtering
367
+ # locally. Which means it too will omit a lot of results (this is also corroborated by
368
+ # the 2116 issue above).
344
369
  #
345
- # For v1 we actually used to grab the entire list of packages, but we found
346
- # that it could cause undue load on really large package lists
370
+ # collect_package_requests, however, continues to be useful here because it filters
371
+ # the already cached things from the list. However, for now it will no longer walk the
372
+ # resource tree until 2116 can be sorted out. When we regain that ability, we should
373
+ # re-evaluate this, since it does save a LOT of API requests!
347
374
  collect_package_requests(
348
375
  ignore_list: @@choco_available_packages[new_resource.list_options].keys
349
- ).each_slice(25) do |pkg_set|
376
+ ).each do |pkg_set|
350
377
  available_versions =
351
378
  begin
352
379
  cmd = [ query_command, "-r" ]
353
380
 
354
381
  # Chocolatey doesn't actually take a wildcard for this query, however
355
382
  # it will return all packages when using '*' as a query
356
- unless pkg_set == ["*"]
357
- cmd += pkg_set
383
+ unless pkg_set == "*"
384
+ cmd << pkg_set
358
385
  end
359
386
  cmd += common_options
360
387
  cmd.push( new_resource.list_options ) if new_resource.list_options
@@ -383,10 +410,12 @@ class Chef
383
410
  #
384
411
  # @return [Hash] name-to-version mapping of installed packages
385
412
  def installed_packages
386
- if new_resource.use_choco_list == false || !Chef::Config[:always_use_choco_list]
387
- installed_packages_via_choco
388
- else
413
+ # Logic here must be either use_choco_list is false _and_ always_use_choco_list is
414
+ # falsy, since the global overrides the local
415
+ if new_resource.use_choco_list == false && !Chef::Config[:always_use_choco_list]
389
416
  installed_packages_via_disk
417
+ else
418
+ installed_packages_via_choco
390
419
  end
391
420
  end
392
421
 
@@ -413,8 +442,8 @@ class Chef
413
442
  # that contains all possible package folders, and so we push our
414
443
  # guess to the front as an optimization.
415
444
  target_dirs << targets.first.downcase if targets.length == 1
416
- if targets.downcase is_a?(String)
417
- target_dirs << targets
445
+ if targets.is_a?(String)
446
+ target_dirs << targets.downcase
418
447
  end
419
448
  target_dirs += get_local_pkg_dirs(choco_lib_path)
420
449
  fetch_package_versions(choco_lib_path, target_dirs, targets)
@@ -465,6 +494,7 @@ class Chef
465
494
  # Fetch the local package versions from chocolatey
466
495
  def fetch_package_versions(base_dir, target_dirs, targets)
467
496
  pkg_versions = {}
497
+ targets = [targets] if targets.is_a?(String)
468
498
  target_dirs.each do |dir|
469
499
  pkg_versions.merge!(get_pkg_data(::File.join(base_dir, dir)))
470
500
  # return early if we found the single package version we were looking for
@@ -29,7 +29,7 @@ class Chef
29
29
  DPKG_INSTALLED = /^Status: install ok installed/.freeze
30
30
  DPKG_VERSION = /^Version: (.+)$/.freeze
31
31
 
32
- provides :dpkg_package
32
+ provides :dpkg_package, target_mode: true
33
33
 
34
34
  use_multipackage_api
35
35
  use_package_name_for_source
@@ -146,14 +146,14 @@ class Chef
146
146
  #
147
147
  # @return [Boolean] True if all sources exist
148
148
  def source_files_exist?
149
- resolved_source_array.all? { |s| s && ::File.exist?(s) }
149
+ resolved_source_array.all? { |s| s && ::TargetIO::File.exist?(s) }
150
150
  end
151
151
 
152
152
  # Helper to return all the names of the missing sources for error messages.
153
153
  #
154
154
  # @return [Array<String>] Array of missing sources
155
155
  def missing_sources
156
- resolved_source_array.select { |s| s.nil? || !::File.exist?(s) }
156
+ resolved_source_array.select { |s| s.nil? || !::TargetIO::File.exist?(s) }
157
157
  end
158
158
 
159
159
  def current_package_name_array
@@ -30,7 +30,7 @@ class Chef
30
30
 
31
31
  module PortsHelper
32
32
  def supports_ports?
33
- ::File.exist?("/usr/ports/Makefile")
33
+ ::TargetIO::File.exist?("/usr/ports/Makefile")
34
34
  end
35
35
 
36
36
  def port_dir(port)
@@ -15,7 +15,6 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
  #
18
- require_relative "../../http/simple"
19
18
  require_relative "../../json_compat"
20
19
  require_relative "../../exceptions"
21
20
  require_relative "../package"
@@ -27,7 +26,7 @@ class Chef
27
26
  class Habitat < Chef::Provider::Package
28
27
  use_multipackage_api
29
28
  use "../../resource/habitat/habitat_shared"
30
- provides :habitat_package
29
+ provides :habitat_package, target_mode: true
31
30
 
32
31
  def load_current_resource
33
32
  @current_resource = Chef::Resource::HabitatPackage.new(new_resource.name)
@@ -40,6 +39,9 @@ class Chef
40
39
  end
41
40
 
42
41
  def install_package(names, versions)
42
+ # License acceptance needed outside of local Chef Client
43
+ shell_out!("hab license accept") if Chef::Config.target_mode?
44
+
43
45
  names.zip(versions).map do |n, v|
44
46
  opts = ["pkg", "install", "--channel", new_resource.channel, "--url", new_resource.bldr_url]
45
47
  opts += ["--auth", new_resource.auth_token] if new_resource.auth_token
@@ -120,7 +122,7 @@ class Chef
120
122
 
121
123
  def http
122
124
  # FIXME: use SimpleJSON when the depot mime-type is fixed
123
- @http ||= Chef::HTTP::Simple.new(new_resource.bldr_url.to_s)
125
+ @http ||= TargetIO::HTTP.new(new_resource.bldr_url.to_s)
124
126
  end
125
127
 
126
128
  def candidate_versions
@@ -26,8 +26,8 @@ class Chef
26
26
  class Package
27
27
  class Ips < Chef::Provider::Package
28
28
 
29
- provides :package, platform: %w{openindiana omnios solaris2}
30
- provides :ips_package
29
+ provides :package, platform: %w{openindiana omnios solaris2}, target_mode: true
30
+ provides :ips_package, target_mode: true
31
31
 
32
32
  attr_accessor :virtual
33
33
 
@@ -30,8 +30,8 @@ class Chef
30
30
  class Package
31
31
  class Openbsd < Chef::Provider::Package
32
32
 
33
- provides :package, os: "openbsd"
34
- provides :openbsd_package
33
+ provides :package, os: "openbsd", target_mode: true
34
+ provides :openbsd_package, target_mode: true
35
35
 
36
36
  include Chef::Mixin::ShellOut
37
37
  include Chef::Mixin::GetSourceFromPackage
@@ -129,6 +129,7 @@ class Chef
129
129
  end
130
130
  end
131
131
 
132
+ # Target Mode limitation: ENV["PKG_PATH"] cannot be evaluated, as remote commands are not run in a standard shell
132
133
  def pkg_path
133
134
  ENV["PKG_PATH"] || "http://ftp.OpenBSD.org/pub/#{node["kernel"]["name"]}/#{node["kernel"]["release"]}/packages/#{node["kernel"]["machine"]}/"
134
135
  end
@@ -24,8 +24,8 @@ class Chef
24
24
  class Package
25
25
  class Pacman < Chef::Provider::Package
26
26
 
27
- provides :package, platform: "arch"
28
- provides :pacman_package
27
+ provides :package, platform: "arch", target_mode: true
28
+ provides :pacman_package, target_mode: true
29
29
 
30
30
  use_multipackage_api
31
31
  allow_nils
@@ -37,8 +37,8 @@ class Chef
37
37
 
38
38
  repos = %w{extra core community}
39
39
 
40
- if ::File.exist?("/etc/pacman.conf")
41
- pacman = ::File.read("/etc/pacman.conf")
40
+ if ::TargetIO::File.exist?("/etc/pacman.conf")
41
+ pacman = ::TargetIO::File.read("/etc/pacman.conf")
42
42
  repos = pacman.scan(/\[(.+)\]/).flatten
43
43
  end
44
44
 
@@ -24,8 +24,8 @@ class Chef
24
24
  class Package
25
25
  class Paludis < Chef::Provider::Package
26
26
 
27
- provides :package, platform: "exherbo"
28
- provides :paludis_package
27
+ provides :package, platform: "exherbo", target_mode: true
28
+ provides :paludis_package, target_mode: true
29
29
 
30
30
  def load_current_resource
31
31
  @current_resource = Chef::Resource::Package.new(new_resource.package_name)
@@ -38,7 +38,7 @@ class Chef
38
38
 
39
39
  globsafe_category = category ? Chef::Util::PathHelper.escape_glob_dir(category) : nil
40
40
  globsafe_pkg = Chef::Util::PathHelper.escape_glob_dir(pkg)
41
- possibilities = Dir["/var/db/pkg/#{globsafe_category || "*"}/#{globsafe_pkg}-*"].map { |d| d.sub(%r{/var/db/pkg/}, "") }
41
+ possibilities = TargetIO::Dir["/var/db/pkg/#{globsafe_category || "*"}/#{globsafe_pkg}-*"].map { |d| d.sub(%r{/var/db/pkg/}, "") }
42
42
  versions = possibilities.map do |entry|
43
43
  if entry =~ %r{[^/]+/#{Regexp.escape(pkg)}\-(\d[\.\d]*[a-z]?((_(alpha|beta|pre|rc|p)\d*)*)?(-r\d+)?)}
44
44
  [$&, $1]
@@ -127,6 +127,7 @@ class Chef
127
127
  command.push("-RequiredVersion #{version}") if version
128
128
  command.push("-Source #{new_resource.source}") if new_resource.source && cmdlet_name =~ Regexp.union(/Install-Package/, /Find-Package/)
129
129
  command.push("-SkipPublisherCheck") if new_resource.skip_publisher_check && cmdlet_name !~ /Find-Package/
130
+ command.push("-AllowClobber") if new_resource.allow_clobber
130
131
  if new_resource.options && cmdlet_name !~ Regexp.union(/Get-Package/, /Find-Package/)
131
132
  new_resource.options.each do |arg|
132
133
  command.push(arg) unless command.include?(arg)
@@ -24,7 +24,7 @@ class Chef
24
24
  class Provider
25
25
  class Package
26
26
  class Rpm < Chef::Provider::Package
27
- provides :rpm_package
27
+ provides :rpm_package, target_mode: true
28
28
 
29
29
  include Chef::Mixin::GetSourceFromPackage
30
30
 
@@ -51,7 +51,7 @@ class Chef
51
51
  current_resource.package_name(new_resource.package_name)
52
52
 
53
53
  if new_resource.source
54
- unless uri_scheme?(new_resource.source) || ::File.exist?(new_resource.source)
54
+ unless uri_scheme?(new_resource.source) || ::TargetIO::File.exist?(new_resource.source)
55
55
  @package_source_exists = false
56
56
  return
57
57
  end
@@ -29,8 +29,8 @@ class Chef
29
29
  class SmartOS < Chef::Provider::Package
30
30
  attr_accessor :is_virtual_package
31
31
 
32
- provides :package, platform: "smartos"
33
- provides :smartos_package
32
+ provides :package, platform: "smartos", target_mode: true
33
+ provides :smartos_package, target_mode: true
34
34
 
35
35
  def load_current_resource
36
36
  logger.trace("#{new_resource} loading current resource")
@@ -218,6 +218,7 @@ class Chef
218
218
  waiting = true
219
219
  while waiting
220
220
  result = get_change_id(id)
221
+
221
222
  case result["result"]["status"]
222
223
  when "Do", "Doing", "Undoing", "Undo"
223
224
  # Continue
@@ -329,7 +330,7 @@ class Chef
329
330
  def generate_snap_json(snap_names, action, channel, options, revision = nil)
330
331
  request = {
331
332
  "action" => action,
332
- "snaps" => snap_names,
333
+ "snaps" => Array(snap_names),
333
334
  }
334
335
  if %w{install refresh switch}.include?(action) && channel
335
336
  request["channel"] = channel
@@ -0,0 +1,79 @@
1
+ #
2
+ # Author:: T.Heinen (<thomas.heinen@gmail.com>)
3
+ # Copyright:: Copyright (c) Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require_relative "snap"
20
+
21
+ class Chef
22
+ class Provider
23
+ class Package
24
+ class SnapTM < Chef::Provider::Package::Snap
25
+ provides :snap_package, target_mode: true
26
+
27
+ def install_package(names, versions)
28
+ if new_resource.source
29
+ install_snap_from_source(names, new_resource.source)
30
+ else
31
+ Array(names).each do |snap|
32
+ snap_options = new_resource.options
33
+
34
+ snapctl([
35
+ "install",
36
+ "--channel=#{new_resource.channel}",
37
+ snap_options&.map { |opt| "--#{opt}" },
38
+ snap,
39
+ ].flatten.compact)
40
+ end
41
+ end
42
+ end
43
+
44
+ def remove_package(names, versions)
45
+ Array(names).each do |snap|
46
+ snapctl([
47
+ "remove",
48
+ snap,
49
+ ])
50
+ end
51
+ end
52
+
53
+ def snapctl(*args)
54
+ # Deferred execution can result in exit code 10
55
+ shell_out!("snap", *args, returns: [0, 10])
56
+ end
57
+
58
+ def get_latest_package_version(name, channel)
59
+ cmd = shell_out("snap info #{name}")
60
+ latest = cmd.stdout.lines.detect { |l| l.start_with? " latest/#{new_resource.channel}:" }
61
+ return unless latest
62
+
63
+ latest.split.at(1)
64
+ end
65
+
66
+ def get_installed_package_by_name(name)
67
+ cmd = shell_out("snap info #{name}")
68
+ installed = cmd.stdout.lines.detect { |l| l.start_with? "installed:" }
69
+ return {} unless installed
70
+
71
+ {
72
+ "name" => name,
73
+ "version" => installed.split.at(1),
74
+ }
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -26,7 +26,7 @@ class Chef
26
26
 
27
27
  include Chef::Mixin::GetSourceFromPackage
28
28
 
29
- provides :solaris_package
29
+ provides :solaris_package, target_mode: true
30
30
 
31
31
  # def initialize(*args)
32
32
  # super
@@ -50,7 +50,7 @@ class Chef
50
50
  current_resource.package_name(new_resource.package_name)
51
51
 
52
52
  if new_resource.source
53
- @package_source_found = ::File.exist?(new_resource.source)
53
+ @package_source_found = ::TargetIO::File.exist?(new_resource.source)
54
54
  if @package_source_found
55
55
  logger.trace("#{new_resource} checking pkg status")
56
56
  shell_out("pkginfo", "-l", "-d", new_resource.source, new_resource.package_name).stdout.each_line do |line|
@@ -101,7 +101,7 @@ class Chef
101
101
  def install_package(name, version)
102
102
  logger.trace("#{new_resource} package install options: #{options}")
103
103
  if options.nil?
104
- command = if ::File.directory?(new_resource.source) # CHEF-4469
104
+ command = if ::TargetIO::File.directory?(new_resource.source) # CHEF-4469
105
105
  [ "pkgadd", "-n", "-d", new_resource.source, new_resource.package_name ]
106
106
  else
107
107
  [ "pkgadd", "-n", "-d", new_resource.source, "all" ]
@@ -109,7 +109,7 @@ class Chef
109
109
  shell_out!(command)
110
110
  logger.trace("#{new_resource} installed version #{new_resource.version} from: #{new_resource.source}")
111
111
  else
112
- command = if ::File.directory?(new_resource.source) # CHEF-4469
112
+ command = if ::TargetIO::File.directory?(new_resource.source) # CHEF-4469
113
113
  [ "pkgadd", "-n", options, "-d", new_resource.source, new_resource.package_name ]
114
114
  else
115
115
  [ "pkgadd", "-n", options, "-d", new_resource.source, "all" ]