chef 18.2.7 → 18.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/chef-universal-mingw-ucrt.gemspec +1 -1
  4. data/chef.gemspec +3 -3
  5. data/lib/chef/application/base.rb +2 -0
  6. data/lib/chef/chef_fs/file_pattern.rb +1 -1
  7. data/lib/chef/chef_fs/path_utils.rb +7 -9
  8. data/lib/chef/client.rb +2 -2
  9. data/lib/chef/cookbook/synchronizer.rb +19 -2
  10. data/lib/chef/cookbook_version.rb +1 -1
  11. data/lib/chef/delayed_evaluator.rb +4 -0
  12. data/lib/chef/file_access_control/windows.rb +4 -1
  13. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +2 -0
  14. data/lib/chef/http/ssl_policies.rb +2 -2
  15. data/lib/chef/mixin/homebrew_user.rb +15 -5
  16. data/lib/chef/monkey_patches/net-http.rb +127 -0
  17. data/lib/chef/node/attribute_collections.rb +10 -1
  18. data/lib/chef/node/immutable_collections.rb +7 -3
  19. data/lib/chef/node/mixin/state_tracking.rb +1 -1
  20. data/lib/chef/node/mixin/state_tracking_array.rb +41 -0
  21. data/lib/chef/node.rb +22 -0
  22. data/lib/chef/provider/launchd.rb +1 -1
  23. data/lib/chef/provider/mount/linux.rb +1 -1
  24. data/lib/chef/provider/mount/mount.rb +5 -5
  25. data/lib/chef/provider/package/apt.rb +11 -2
  26. data/lib/chef/provider/package/chocolatey.rb +239 -18
  27. data/lib/chef/provider/package/zypper.rb +6 -0
  28. data/lib/chef/provider/powershell_script.rb +96 -6
  29. data/lib/chef/provider/remote_file/http.rb +1 -1
  30. data/lib/chef/provider/service/systemd.rb +23 -8
  31. data/lib/chef/provider/service/windows.rb +1 -0
  32. data/lib/chef/provider/service.rb +14 -0
  33. data/lib/chef/provider/user.rb +5 -1
  34. data/lib/chef/provider/yum_repository.rb +1 -1
  35. data/lib/chef/recipe.rb +3 -11
  36. data/lib/chef/resource/_rest_resource.rb +1 -1
  37. data/lib/chef/resource/apt_package.rb +19 -0
  38. data/lib/chef/resource/apt_repository.rb +26 -6
  39. data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
  40. data/lib/chef/resource/chocolatey_installer.rb +207 -0
  41. data/lib/chef/resource/chocolatey_package.rb +8 -0
  42. data/lib/chef/resource/homebrew_cask.rb +6 -7
  43. data/lib/chef/resource/homebrew_package.rb +1 -1
  44. data/lib/chef/resource/homebrew_tap.rb +5 -5
  45. data/lib/chef/resource/launchd.rb +5 -1
  46. data/lib/chef/resource/locale.rb +5 -2
  47. data/lib/chef/resource/macos_pkg.rb +111 -0
  48. data/lib/chef/resource/powershell_script.rb +5 -1
  49. data/lib/chef/resource/service.rb +3 -0
  50. data/lib/chef/resource/sudo.rb +37 -2
  51. data/lib/chef/resource/support/ulimit.erb +40 -0
  52. data/lib/chef/resource/user_ulimit.rb +38 -0
  53. data/lib/chef/resource/windows_certificate.rb +1 -1
  54. data/lib/chef/resource/windows_security_policy.rb +2 -2
  55. data/lib/chef/resource.rb +11 -1
  56. data/lib/chef/resources.rb +2 -0
  57. data/lib/chef/version.rb +1 -1
  58. data/lib/chef/win32/security.rb +7 -1
  59. data/spec/data/trusted_certs/example.crt +29 -20
  60. data/spec/data/trusted_certs/example_no_cn.crt +30 -34
  61. data/spec/functional/resource/chocolatey_package_spec.rb +32 -20
  62. data/spec/functional/resource/execute_spec.rb +1 -1
  63. data/spec/functional/resource/windows_certificate_spec.rb +25 -0
  64. data/spec/functional/resource/zypper_package_spec.rb +10 -0
  65. data/spec/unit/client_spec.rb +2 -2
  66. data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +1 -1
  67. data/spec/unit/delayed_evaluator_spec.rb +35 -0
  68. data/spec/unit/mixin/homebrew_user_spec.rb +30 -7
  69. data/spec/unit/node/vivid_mash_spec.rb +42 -0
  70. data/spec/unit/node_spec.rb +6 -0
  71. data/spec/unit/provider/apt_repository_spec.rb +17 -7
  72. data/spec/unit/provider/launchd_spec.rb +2 -2
  73. data/spec/unit/provider/mount/aix_spec.rb +2 -2
  74. data/spec/unit/provider/mount/linux_spec.rb +6 -5
  75. data/spec/unit/provider/mount/mount_spec.rb +8 -8
  76. data/spec/unit/provider/package/apt_spec.rb +18 -13
  77. data/spec/unit/provider/package/chocolatey_spec.rb +53 -9
  78. data/spec/unit/provider/package/rpm_spec.rb +2 -2
  79. data/spec/unit/provider/package/zypper_spec.rb +10 -0
  80. data/spec/unit/provider/powershell_script_spec.rb +100 -4
  81. data/spec/unit/provider/remote_file/http_spec.rb +4 -4
  82. data/spec/unit/provider/service/systemd_service_spec.rb +1 -0
  83. data/spec/unit/provider/user/linux_spec.rb +10 -0
  84. data/spec/unit/resource/apt_repository_spec.rb +5 -0
  85. data/spec/unit/resource/chef_client_systemd_timer_spec.rb +1 -1
  86. data/spec/unit/resource/chocolatey_installer_spec.rb +151 -0
  87. data/spec/unit/resource/macos_pkg_spec.rb +38 -0
  88. data/spec/unit/resource/powershell_script_spec.rb +2 -2
  89. data/spec/unit/resource_spec.rb +86 -0
  90. metadata +29 -16
  91. /data/spec/functional/assets/chocolatey_feed/{test-A.1.0.nupkg → test-A.1.0.0.nupkg} +0 -0
  92. /data/spec/functional/assets/chocolatey_feed/{test-A.1.5.nupkg → test-A.1.5.0.nupkg} +0 -0
  93. /data/spec/functional/assets/chocolatey_feed/{test-A.2.0.nupkg → test-A.2.0.0.nupkg} +0 -0
  94. /data/spec/functional/assets/chocolatey_feed/{test-B.1.0.nupkg → test-B.1.0.0.nupkg} +0 -0
@@ -351,7 +351,7 @@ action_class do
351
351
  Chef.run_context.transport.connection
352
352
  end
353
353
 
354
- # Remove all empty keys (recusively) from Hash.
354
+ # Remove all empty keys (recursively) from Hash.
355
355
  # @see https://stackoverflow.com/questions/56457020/#answer-56458673
356
356
  def deep_compact!(hsh)
357
357
  raise TypeError unless hsh.is_a? Hash
@@ -52,6 +52,21 @@ class Chef
52
52
  options '--no-install-recommends'
53
53
  end
54
54
  ```
55
+
56
+ **Prevent the apt_package resource from installing packages with pattern matching names**:
57
+
58
+ By default, the apt_package resource will install the named package.
59
+ If it can't find a package with the exact same name, it will treat the package name as regular expression string and match with any package that matches that regular expression.
60
+ This may lead Chef Infra Client to install one or more packages with names that match that regular expression.
61
+
62
+ In this example, `anchor_package_regex true` prevents the apt_package resource from installing matching packages if it can't find the `lua5.3` package.
63
+
64
+ ```ruby
65
+ apt_package 'lua5.3' do
66
+ version '5.3.3-1.1ubuntu2'
67
+ anchor_package_regex true
68
+ end
69
+ ```
55
70
  DOC
56
71
 
57
72
  description "Use the **apt_package** resource to manage packages on Debian, Ubuntu, and other platforms that use the APT package system."
@@ -75,6 +90,10 @@ class Chef
75
90
  description: "A Hash of response file variables in the form of {'VARIABLE' => 'VALUE'}.",
76
91
  default: {}, desired_state: false
77
92
 
93
+ property :anchor_package_regex, [TrueClass, FalseClass],
94
+ introduced: "18.3",
95
+ description: "A Boolean flag that indicates whether the package name, which can be a regular expression, must match the entire name of the package (true) or if the regular expression is allowed to match a subset of the name (false).",
96
+ default: false
78
97
  end
79
98
  end
80
99
  end
@@ -98,6 +98,19 @@ class Chef
98
98
  end
99
99
  ```
100
100
 
101
+ **Add repository that needs custom options**:
102
+
103
+ ```ruby
104
+ apt_repository 'corretto' do
105
+ uri 'https://apt.corretto.aws'
106
+ arch 'amd64'
107
+ distribution 'stable'
108
+ components ['main']
109
+ options ['target-=Contents-deb']
110
+ key 'https://apt.corretto.aws/corretto.key'
111
+ end
112
+ ```
113
+
101
114
  **Remove a repository from the list**:
102
115
 
103
116
  ```ruby
@@ -159,6 +172,10 @@ class Chef
159
172
  description: "Determines whether to rebuild the APT package cache.",
160
173
  default: true, desired_state: false
161
174
 
175
+ property :options, [String, Array],
176
+ description: "Additional options to set for the repository.",
177
+ default: [], coerce: proc { |x| Array(x) }
178
+
162
179
  default_action :add
163
180
  allowed_actions :add, :remove
164
181
 
@@ -388,19 +405,21 @@ class Chef
388
405
  # @param [Array] components
389
406
  # @param [Boolean] trusted
390
407
  # @param [String] arch
408
+ # @param [Array] options
391
409
  # @param [Boolean] add_src
392
410
  #
393
411
  # @return [String] complete repo config text
394
- def build_repo(uri, distribution, components, trusted, arch, add_src = false)
412
+ def build_repo(uri, distribution, components, trusted, arch, options, add_src = false)
395
413
  uri = make_ppa_url(uri) if is_ppa_url?(uri)
396
414
 
397
415
  uri = Addressable::URI.parse(uri)
398
416
  components = Array(components).join(" ")
399
- options = []
400
- options << "arch=#{arch}" if arch
401
- options << "trusted=yes" if trusted
402
- optstr = unless options.empty?
403
- "[" + options.join(" ") + "]"
417
+ options_list = []
418
+ options_list << "arch=#{arch}" if arch
419
+ options_list << "trusted=yes" if trusted
420
+ options_list += options
421
+ optstr = unless options_list.empty?
422
+ "[" + options_list.join(" ") + "]"
404
423
  end
405
424
  info = [ optstr, uri.normalize.to_s, distribution, components ].compact.join(" ")
406
425
  repo = "deb #{info}\n"
@@ -461,6 +480,7 @@ class Chef
461
480
  repo_components,
462
481
  new_resource.trusted,
463
482
  new_resource.arch,
483
+ new_resource.options,
464
484
  new_resource.deb_src
465
485
  )
466
486
 
@@ -176,7 +176,7 @@ class Chef
176
176
  }
177
177
 
178
178
  unit["Service"]["ConditionACPower"] = "true" unless new_resource.run_on_battery
179
- unit["Service"]["CPUQuota"] = new_resource.cpu_quota if new_resource.cpu_quota
179
+ unit["Service"]["CPUQuota"] = "#{new_resource.cpu_quota}%" if new_resource.cpu_quota
180
180
  unit["Service"]["Environment"] = new_resource.environment.collect { |k, v| "\"#{k}=#{v}\"" } unless new_resource.environment.empty?
181
181
  unit
182
182
  end
@@ -0,0 +1,207 @@
1
+ class Chef
2
+ class Resource
3
+ class ChocolateyInstaller < Chef::Resource
4
+ provides :chocolatey_installer
5
+
6
+ description "Use the chocolatey_installer resource to ensure that Chocolatey itself is installed to your specification. Use the Chocolatey Feature resource to customize your install. Then use the Chocolatey Package resource to install packages on Windows via Chocolatey."
7
+ introduced "18.3"
8
+ examples <<~DOC
9
+ **Install Chocolatey**
10
+
11
+ ```ruby
12
+ chocolatey_installer 'latest' do
13
+ action :install
14
+ end
15
+ ```
16
+
17
+ **Uninstall Chocolatey**
18
+
19
+ ```ruby
20
+ chocolatey_installer 'Some random verbiage' do
21
+ action :uninstall
22
+ end
23
+ ```
24
+
25
+ **Install Chocolatey with Parameters**
26
+
27
+ ```ruby
28
+ chocolatey_installer 'latest' do
29
+ action :install
30
+ download_url "https://www.contoso.com/foo"
31
+ chocolatey_version '2.12.24'
32
+ end
33
+ ```
34
+
35
+ ```ruby
36
+ chocolatey_installer 'latest' do
37
+ action :install
38
+ download_url "c:\\foo\foo.nupkg"
39
+ chocolatey_version '2.12.24'
40
+ end
41
+ ```
42
+
43
+ **Upgrade Chocolatey with Parameters**
44
+
45
+ ```ruby
46
+ chocolatey_installer 'latest' do
47
+ action :upgrade
48
+ chocolatey_version '2.12.24'
49
+ end
50
+ ```
51
+ DOC
52
+
53
+ allowed_actions :install, :uninstall, :upgrade
54
+
55
+ property :download_url, String,
56
+ description: "The URL to download Chocolatey from. This sets the value of $env:ChocolateyDownloadUrl and causes the installer to choose an alternate download location. If this is not set, Chocolatey installs fall back to the official Chocolatey community repository to download Chocolatey from. It can also be used for offline installation by providing a path to a Chocolatey.nupkg."
57
+
58
+ property :chocolatey_version, String,
59
+ description: "Specifies a target version of Chocolatey to install. By default, the latest stable version is installed. This will use the value in $env:ChocolateyVersion by default, if that environment variable is present. This parameter is ignored if download_url is set."
60
+
61
+ property :use_native_unzip, [TrueClass, FalseClass], default: false,
62
+ description: "If set, uses built-in Windows decompression tools instead of 7zip when unpacking the downloaded nupkg. This will be set by default if use_native_unzip is set to a value other than 'false' or '0'. This parameter will be ignored in PS 5+ in favour of using the Expand-Archive built in PowerShell cmdlet directly."
63
+
64
+ property :ignore_proxy, [TrueClass, FalseClass], default: false,
65
+ description: "If set, ignores any configured proxy. This will override any proxy environment variables or parameters. This will be set by default if ignore_proxy is set to a value other than 'false' or '0'."
66
+
67
+ property :proxy_url, String,
68
+ description: "Specifies the proxy URL to use during the download."
69
+
70
+ property :proxy_user, String,
71
+ description: "The username to use to build a proxy credential with. Will be consumed by the proxy_credential property if both this property and proxy_password are set"
72
+
73
+ property :proxy_password, String,
74
+ description: "The password to use to build a proxy credential with. Will be consumed by the proxy_credential property if both this property and proxy_user are set"
75
+
76
+ load_current_value do
77
+ current_state = is_choco_installed?
78
+ current_value_does_not_exist! if current_state == false
79
+ current_state
80
+ end
81
+
82
+ def is_choco_installed?
83
+ ::File.exist?("#{ENV["ALLUSERSPROFILE"]}\\chocolatey\\bin\\choco.exe")
84
+ end
85
+
86
+ def get_choco_version
87
+ powershell_exec("choco --version").result
88
+ end
89
+
90
+ def existing_version
91
+ Gem::Version.new(get_choco_version)
92
+ end
93
+
94
+ def define_resource_requirements
95
+ requirements.assert(:install, :upgrade).each do |a|
96
+ a.assertion do
97
+ # This is an exclusive OR - XOR - we're trying to coax an error out if one, but not both,
98
+ # parameters are empty.
99
+ new_resource.proxy_user.nil? != new_resource.proxy_password.nil?
100
+ end
101
+ a.failure_message(Chef::Exceptions::ValidationFailed, "You must specify both a proxy_user and a proxy_password")
102
+ a.whyrun("Assuming that if you have configured a 'proxy_user' you must also supply a 'proxy_password'")
103
+ end
104
+ end
105
+
106
+ action :install, description: "Installs Chocolatey package manager" do
107
+ if new_resource.download_url
108
+ powershell_exec("Set-Item -path env:ChocolateyDownloadUrl -Value #{new_resource.download_url}")
109
+ end
110
+
111
+ if new_resource.chocolatey_version
112
+ powershell_exec("Set-Item -path env:ChocolateyVersion -Value #{new_resource.chocolatey_version}")
113
+ end
114
+
115
+ if new_resource.use_native_unzip
116
+ powershell_exec("Set-Item -path env:ChocolateyUseWindowsCompression -Value true")
117
+ end
118
+
119
+ if new_resource.ignore_proxy
120
+ powershell_exec("Set-Item -path env:ChocolateyIgnoreProxy -Value true")
121
+ end
122
+
123
+ if new_resource.proxy_url
124
+ powershell_exec("Set-Item -path env:ChocolateyProxyLocation -Value #{new_resource.proxy_url}")
125
+ end
126
+
127
+ if new_resource.proxy_user && new_resource.proxy_password
128
+ powershell_exec("Set-Item -path env:ChocolateyProxyUser -Value #{new_resource.proxy_user}; Set-Item -path env:ChocolateyProxyPassword -Value #{new_resource.proxy_password}")
129
+ end
130
+
131
+ # note that Invoke-Expression is being called on the downloaded script (outer parens),
132
+ # not triggering the script download (inner parens)
133
+ converge_if_changed do
134
+ powershell_exec("Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))").error!
135
+ end
136
+ end
137
+
138
+ action :upgrade, description: "Upgrades the Chocolatey package manager" do
139
+ if new_resource.chocolatey_version
140
+ proposed_version = Gem::Version.new(new_resource.chocolatey_version)
141
+ else
142
+ proposed_version = nil
143
+ end
144
+
145
+ if new_resource.download_url
146
+ powershell_exec("Set-Item -path env:ChocolateyDownloadUrl -Value #{new_resource.download_url}")
147
+ end
148
+
149
+ if new_resource.chocolatey_version
150
+ powershell_exec("Set-Item -path env:ChocolateyVersion -Value #{new_resource.chocolatey_version}")
151
+ end
152
+
153
+ if new_resource.use_native_unzip
154
+ powershell_exec("Set-Item -path env:ChocolateyUseWindowsCompression -Value true")
155
+ end
156
+
157
+ if new_resource.ignore_proxy
158
+ powershell_exec("Set-Item -path env:ChocolateyIgnoreProxy -Value true")
159
+ end
160
+
161
+ if new_resource.proxy_url
162
+ powershell_exec("Set-Item -path env:ChocolateyProxyLocation -Value #{new_resource.proxy_url}")
163
+ end
164
+
165
+ if new_resource.proxy_user && new_resource.proxy_password
166
+ powershell_exec("Set-Item -path env:ChocolateyProxyUser -Value #{new_resource.proxy_user}; Set-Item -path env:ChocolateyProxyPassword -Value #{new_resource.proxy_password}")
167
+ end
168
+
169
+ if proposed_version && existing_version < proposed_version
170
+ powershell_exec("Set-Item -path env:ChocolateyVersion -Value #{proposed_version}")
171
+ else
172
+ powershell_exec("Remove-Item -path env:ChocolateyVersion")
173
+ end
174
+
175
+ converge_by("upgrade choco version") do
176
+ powershell_exec("choco upgrade Chocolatey -y").result
177
+ end
178
+ end
179
+
180
+ action :uninstall, description: "Uninstall Chocolatey package manager" do
181
+ path = "c:\\programdata\\chocolatey\\bin"
182
+ if File.exists?(path)
183
+ converge_by("Uninstall Choco") do
184
+ powershell_code = <<~CODE
185
+ Remove-Item $env:ALLUSERSPROFILE\\chocolatey -Recurse -Force
186
+ [Environment]::SetEnvironmentVariable("ChocolateyLastPathUpdate", $null ,"User")
187
+ [Environment]::SetEnvironmentVariable("ChocolateyToolsLocation", $null ,"User")
188
+ [Environment]::SetEnvironmentVariable("ChocolateyInstall", $null ,"Machine")
189
+ $path = [System.Environment]::GetEnvironmentVariable(
190
+ 'PATH',
191
+ 'Machine'
192
+ )
193
+ $path = ($path.Split(';') | Where-Object { $_ -ne "#{path}" }) -join ";"
194
+ [System.Environment]::SetEnvironmentVariable(
195
+ 'PATH',
196
+ $path,
197
+ 'Machine'
198
+ )
199
+ CODE
200
+ powershell_exec(powershell_code).error!
201
+ end
202
+ end
203
+ Chef::Log.warn("Chocolatey is already uninstalled.")
204
+ end
205
+ end
206
+ end
207
+ end
@@ -67,6 +67,14 @@ class Chef
67
67
  description: "The name of the package. Default value: the name of the resource block.",
68
68
  coerce: proc { |x| [x].flatten }
69
69
 
70
+ property :bulk_query, [TrueClass, FalseClass],
71
+ description: "Bulk query the chocolatey server? This will cause the provider to list all packages instead of doing individual queries.",
72
+ default: false
73
+
74
+ property :use_choco_list, [TrueClass, FalseClass],
75
+ description: "Use choco list for getting the locally installed packages, rather than reading the nupkg database directly? This defaults to false, since reading the package data is faster.",
76
+ default: false
77
+
70
78
  property :version, [String, Array],
71
79
  description: "The version of a package to be installed or upgraded.",
72
80
  coerce: proc { |x| [x].flatten }
@@ -45,8 +45,7 @@ class Chef
45
45
  default: true
46
46
 
47
47
  property :homebrew_path, String,
48
- description: "The path to the homebrew binary.",
49
- default: "/usr/local/bin/brew"
48
+ description: "The path to the Homebrew binary."
50
49
 
51
50
  property :owner, [String, Integer],
52
51
  description: "The owner of the Homebrew installation.",
@@ -56,14 +55,14 @@ class Chef
56
55
  action :install, description: "Install an application that is packaged as a Homebrew cask." do
57
56
  if new_resource.install_cask
58
57
  homebrew_tap "homebrew/cask" do
59
- homebrew_path new_resource.homebrew_path
58
+ homebrew_path homebrew_bin_path(new_resource.homebrew_path)
60
59
  owner new_resource.owner
61
60
  end
62
61
  end
63
62
 
64
63
  unless casked?
65
64
  converge_by("install cask #{new_resource.cask_name} #{new_resource.options}") do
66
- shell_out!("#{new_resource.homebrew_path} install --cask #{new_resource.cask_name} #{new_resource.options}",
65
+ shell_out!("#{homebrew_bin_path(new_resource.homebrew_path)} install --cask #{new_resource.cask_name} #{new_resource.options}",
67
66
  user: new_resource.owner,
68
67
  env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner },
69
68
  cwd: ::Dir.home(new_resource.owner))
@@ -74,14 +73,14 @@ class Chef
74
73
  action :remove, description: "Remove an application that is packaged as a Homebrew cask." do
75
74
  if new_resource.install_cask
76
75
  homebrew_tap "homebrew/cask" do
77
- homebrew_path new_resource.homebrew_path
76
+ homebrew_path homebrew_bin_path(new_resource.homebrew_path)
78
77
  owner new_resource.owner
79
78
  end
80
79
  end
81
80
 
82
81
  if casked?
83
82
  converge_by("uninstall cask #{new_resource.cask_name}") do
84
- shell_out!("#{new_resource.homebrew_path} uninstall --cask #{new_resource.cask_name}",
83
+ shell_out!("#{homebrew_bin_path(new_resource.homebrew_path)} uninstall --cask #{new_resource.cask_name}",
85
84
  user: new_resource.owner,
86
85
  env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner },
87
86
  cwd: ::Dir.home(new_resource.owner))
@@ -99,7 +98,7 @@ class Chef
99
98
  # @return [Boolean]
100
99
  def casked?
101
100
  unscoped_name = new_resource.cask_name.split("/").last
102
- shell_out!("#{new_resource.homebrew_path} list --cask 2>/dev/null",
101
+ shell_out!("#{homebrew_bin_path(new_resource.homebrew_path)} list --cask 2>/dev/null",
103
102
  user: new_resource.owner,
104
103
  env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner },
105
104
  cwd: ::Dir.home(new_resource.owner)).stdout.split.include?(unscoped_name)
@@ -63,7 +63,7 @@ class Chef
63
63
  allowed_actions :install, :upgrade, :remove, :purge
64
64
 
65
65
  property :homebrew_user, [ String, Integer ],
66
- description: "The name or uid of the Homebrew owner to be used by #{ChefUtils::Dist::Infra::PRODUCT} when executing a command.\n\n#{ChefUtils::Dist::Infra::PRODUCT}, by default, will attempt to execute a Homebrew command as the owner of the `/usr/local/bin/brew` executable. If that executable does not exist, #{ChefUtils::Dist::Infra::PRODUCT} will attempt to find the user by executing `which brew`. If that executable cannot be found, #{ChefUtils::Dist::Infra::PRODUCT} will print an error message: `Could not find the 'brew' executable in /usr/local/bin or anywhere on the path.`.\n\nSet this property to specify the Homebrew owner for situations where Chef Infra Client cannot automatically detect the correct owner.'"
66
+ description: "The name or UID of the Homebrew owner to be used by #{ChefUtils::Dist::Infra::PRODUCT} when executing a command.\n\n#{ChefUtils::Dist::Infra::PRODUCT}, by default, will attempt to execute a Homebrew command as the owner of the `/usr/local/bin/brew` executable on x86_64 machines or `/opt/homebrew/bin/brew` executable on arm64 machines. If that executable doesn't exist, #{ChefUtils::Dist::Infra::PRODUCT} will attempt to find the user by executing `which brew`. If that executable can't be found, #{ChefUtils::Dist::Infra::PRODUCT} will print an error message: `Couldn't find the 'brew' executable anywhere on the path.`.\n\nSet this property to specify the Homebrew owner for situations where Chef Infra Client cannot automatically detect the correct owner.'"
67
67
 
68
68
  end
69
69
  end
@@ -41,8 +41,7 @@ class Chef
41
41
  description: "The URL of the tap."
42
42
 
43
43
  property :homebrew_path, String,
44
- description: "The path to the Homebrew binary.",
45
- default: "/usr/local/bin/brew"
44
+ description: "The path to the Homebrew binary."
46
45
 
47
46
  property :owner, String,
48
47
  description: "The owner of the Homebrew installation.",
@@ -52,7 +51,7 @@ class Chef
52
51
  action :tap, description: "Add a Homebrew tap." do
53
52
  unless tapped?(new_resource.tap_name)
54
53
  converge_by("tap #{new_resource.tap_name}") do
55
- shell_out!("#{new_resource.homebrew_path} tap #{new_resource.tap_name} #{new_resource.url || ""}",
54
+ shell_out!("#{homebrew_bin_path(new_resource.homebrew_path)} tap #{new_resource.tap_name} #{new_resource.url || ""}",
56
55
  user: new_resource.owner,
57
56
  env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner },
58
57
  cwd: ::Dir.home(new_resource.owner))
@@ -63,7 +62,7 @@ class Chef
63
62
  action :untap, description: "Remove a Homebrew tap." do
64
63
  if tapped?(new_resource.tap_name)
65
64
  converge_by("untap #{new_resource.tap_name}") do
66
- shell_out!("#{new_resource.homebrew_path} untap #{new_resource.tap_name}",
65
+ shell_out!("#{homebrew_bin_path(new_resource.homebrew_path)} untap #{new_resource.tap_name}",
67
66
  user: new_resource.owner,
68
67
  env: { "HOME" => ::Dir.home(new_resource.owner), "USER" => new_resource.owner },
69
68
  cwd: ::Dir.home(new_resource.owner))
@@ -75,8 +74,9 @@ class Chef
75
74
  #
76
75
  # @return [Boolean]
77
76
  def tapped?(name)
77
+ base_path = ["#{::File.dirname(which("brew"))}/../homebrew", "#{::File.dirname(which("brew"))}/../Homebrew", "/opt/homebrew", "/usr/local/Homebrew", "/home/linuxbrew/.linuxbrew"].uniq.select { |x| Dir.exist?(x) }.first
78
78
  tap_dir = name.gsub("/", "/homebrew-")
79
- ::File.directory?("/usr/local/Homebrew/Library/Taps/#{tap_dir}")
79
+ ::File.directory?("#{base_path}/Library/Taps/#{tap_dir}")
80
80
  end
81
81
  end
82
82
  end
@@ -202,7 +202,11 @@ class Chef
202
202
  description: "The first argument of `execvp`, typically the file name associated with the file to be executed. This value must be specified if `program_arguments` is not specified, and vice-versa."
203
203
 
204
204
  property :program_arguments, Array,
205
- description: "The second argument of `execvp`. If program is not specified, this property must be specified and will be handled as if it were the first argument."
205
+ description: "The second argument of `execvp`. If program is not specified, this property must be specified and will be handled as if it were the first argument.",
206
+ coerce: proc { |args|
207
+ # Cast all values to a string. Launchd only supports string values
208
+ args.map(&:to_s)
209
+ }
206
210
 
207
211
  property :queue_directories, Array,
208
212
  description: "An array of non-empty directories which, if any are modified, will cause a job to be started."
@@ -112,8 +112,11 @@ class Chef
112
112
  end
113
113
 
114
114
  requirements.assert(:all_actions) do |a|
115
- # RHEL/CentOS type platforms don't have locale-gen
116
- a.assertion { which("locale-gen") }
115
+ a.assertion do
116
+ # RHEL/CentOS type platforms don't have locale-gen
117
+ # Windows has locale-gen as part of the install, but not in the path
118
+ which("locale-gen") || windows?
119
+ end
117
120
  a.failure_message(Chef::Exceptions::ProviderNotFound, "The locale resource requires the locale-gen tool")
118
121
  end
119
122
  end
@@ -0,0 +1,111 @@
1
+ #
2
+ # Author:: Joshua Timberman (<jtimberman@chef.io>)
3
+ # Author:: William Theaker (<william.theaker+chef@gusto.com>)
4
+ # Copyright:: Copyright (c) Chef Software Inc.
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 "../resource"
20
+
21
+ class Chef
22
+ class Resource
23
+ class MacosPkg < Chef::Resource
24
+ provides(:macos_pkg) { true }
25
+
26
+ description "Use the **macos_pkg** resource to install a macOS `.pkg` file, optionally downloading it from a remote source. A `package_id` property must be provided for idempotency. Either a `file` or `source` property is required."
27
+ introduced "18.1"
28
+ examples <<~DOC
29
+ **Install osquery**:
30
+
31
+ ```ruby
32
+ macos_pkg 'osquery' do
33
+ checksum '1fea8ac9b603851d2e76c5fc73138a468a3075a3002c8cb1fd7fff53b889c4dd'
34
+ package_id 'io.osquery.agent'
35
+ source 'https://pkg.osquery.io/darwin/osquery-5.8.2.pkg'
36
+ action :install
37
+ end
38
+ ```
39
+ DOC
40
+
41
+ allowed_actions :install
42
+ default_action :install
43
+
44
+ property :checksum, String,
45
+ description: "The sha256 checksum of the `.pkg` file to download."
46
+
47
+ property :file, String,
48
+ description: "The absolute path to the `.pkg` file on the local system."
49
+
50
+ property :headers, Hash,
51
+ description: "Allows custom HTTP headers (like cookies) to be set on the `remote_file` resource.",
52
+ desired_state: false
53
+
54
+ property :package_id, String,
55
+ description: "The package ID registered with `pkgutil` when a `pkg` or `mpkg` is installed.",
56
+ required: true
57
+
58
+ property :source, String,
59
+ description: "The remote URL used to download the `.pkg` file."
60
+
61
+ property :target, String,
62
+ description: "The device to install the package on.",
63
+ default: "/"
64
+
65
+ load_current_value do |new_resource|
66
+ if shell_out("pkgutil --pkg-info '#{new_resource.package_id}'").exitstatus == 0
67
+ Chef::Log.debug "#{new_resource.package_id} is already installed. To upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\""
68
+ else
69
+ current_value_does_not_exist!
70
+ end
71
+ end
72
+
73
+ action :install, description: "Installs the pkg." do
74
+ if new_resource.source.nil? && new_resource.file.nil?
75
+ raise "Must provide either a file or source property for macos_pkg resources."
76
+ end
77
+
78
+ if current_resource.nil?
79
+ if new_resource.source
80
+ remote_file pkg_file do
81
+ source new_resource.source
82
+ headers new_resource.headers if new_resource.headers
83
+ checksum new_resource.checksum if new_resource.checksum
84
+ end
85
+ end
86
+
87
+ converge_by "install #{pkg_file}" do
88
+ install_cmd = "installer -pkg #{pkg_file} -target #{new_resource.target}"
89
+
90
+ execute install_cmd do
91
+ action :run
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ action_class do
98
+ # @return [String] the path to the pkg file
99
+ def pkg_file
100
+ @pkg_file ||= if new_resource.file.nil?
101
+ uri = URI.parse(new_resource.source)
102
+ filename = ::File.basename(uri.path)
103
+ "#{Chef::Config[:file_cache_path]}/#{filename}"
104
+ else
105
+ new_resource.file
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -21,7 +21,7 @@ class Chef
21
21
  class Resource
22
22
  class PowershellScript < Chef::Resource::WindowsScript
23
23
 
24
- set_guard_inherited_attributes(:interpreter)
24
+ set_guard_inherited_attributes(:interpreter, :use_inline_powershell)
25
25
 
26
26
  provides :powershell_script, os: "windows"
27
27
 
@@ -39,6 +39,10 @@ class Chef
39
39
  equal_to: %w{powershell pwsh},
40
40
  description: "The interpreter type, `powershell` or `pwsh` (PowerShell Core)"
41
41
 
42
+ property :use_inline_powershell, [true, false],
43
+ default: false,
44
+ description: "Use inline powershell.dll rather than shelling out - this is faster, but could have different semantics to the traditional method. In particular, it does not allow for streaming output, nor does it allow for passing custom parameters to the interpreter"
45
+
42
46
  property :convert_boolean_return, [true, false],
43
47
  default: false,
44
48
  description: <<~DESC
@@ -93,6 +93,9 @@ class Chef
93
93
  # if the service is masked or not
94
94
  property :masked, [ TrueClass, FalseClass ], skip_docs: true
95
95
 
96
+ # if the service is static or not
97
+ property :static, [ TrueClass, FalseClass ], skip_docs: true
98
+
96
99
  # if the service is indirect or not
97
100
  property :indirect, [ TrueClass, FalseClass ], skip_docs: true
98
101