chef 18.1.29-x64-mingw-ucrt → 18.3.0-x64-mingw-ucrt
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/chef-universal-mingw-ucrt.gemspec +2 -2
- data/chef.gemspec +1 -2
- data/distro/powershell/chef/chef.psm1 +459 -0
- data/lib/chef/application/base.rb +2 -0
- data/lib/chef/client.rb +2 -2
- data/lib/chef/cookbook/synchronizer.rb +20 -2
- data/lib/chef/cookbook_version.rb +1 -1
- data/lib/chef/http/authenticator.rb +2 -2
- data/lib/chef/http/ssl_policies.rb +2 -2
- data/lib/chef/mixin/homebrew_user.rb +12 -5
- data/lib/chef/mixin/proxified_socket.rb +1 -1
- data/lib/chef/monkey_patches/net-http.rb +127 -0
- data/lib/chef/node/attribute_collections.rb +8 -0
- data/lib/chef/node/immutable_collections.rb +5 -2
- data/lib/chef/node/mixin/state_tracking.rb +1 -1
- data/lib/chef/platform/query_helpers.rb +4 -2
- data/lib/chef/provider/launchd.rb +1 -1
- data/lib/chef/provider/mount/linux.rb +1 -1
- data/lib/chef/provider/mount/mount.rb +5 -5
- data/lib/chef/provider/package/chocolatey.rb +18 -1
- data/lib/chef/provider/package/zypper.rb +1 -0
- data/lib/chef/provider/remote_file/http.rb +1 -1
- data/lib/chef/provider/yum_repository.rb +1 -1
- data/lib/chef/resource/apt_repository.rb +25 -6
- data/lib/chef/resource/homebrew_cask.rb +6 -7
- data/lib/chef/resource/homebrew_package.rb +1 -1
- data/lib/chef/resource/homebrew_tap.rb +5 -5
- data/lib/chef/resource/launchd.rb +5 -1
- data/lib/chef/resource/macos_userdefaults.rb +9 -5
- data/lib/chef/resource/selinux_login.rb +129 -0
- data/lib/chef/resource/selinux_user.rb +137 -0
- data/lib/chef/resource/windows_certificate.rb +1 -1
- data/lib/chef/resource/windows_security_policy.rb +2 -2
- data/lib/chef/resource.rb +11 -1
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/security.rb +7 -1
- data/spec/data/trusted_certs/intermediate.pem +38 -27
- data/spec/data/trusted_certs/opscode.pem +33 -54
- data/spec/functional/resource/chocolatey_package_spec.rb +32 -20
- data/spec/functional/resource/execute_spec.rb +1 -1
- data/spec/functional/resource/macos_userdefaults_spec.rb +4 -4
- data/spec/functional/resource/windows_certificate_spec.rb +25 -0
- data/spec/unit/client_spec.rb +2 -2
- data/spec/unit/mixin/homebrew_user_spec.rb +30 -7
- data/spec/unit/node/vivid_mash_spec.rb +42 -0
- data/spec/unit/provider/apt_repository_spec.rb +17 -7
- data/spec/unit/provider/launchd_spec.rb +2 -2
- data/spec/unit/provider/mount/aix_spec.rb +2 -2
- data/spec/unit/provider/mount/linux_spec.rb +6 -5
- data/spec/unit/provider/mount/mount_spec.rb +8 -8
- data/spec/unit/provider/package/chocolatey_spec.rb +19 -3
- data/spec/unit/provider/package/rpm_spec.rb +2 -2
- data/spec/unit/provider/package/zypper_spec.rb +10 -0
- data/spec/unit/provider/remote_file/http_spec.rb +4 -4
- data/spec/unit/resource/apt_repository_spec.rb +5 -0
- data/spec/unit/resource/macos_user_defaults_spec.rb +4 -4
- data/spec/unit/resource/selinux_login_spec.rb +73 -0
- data/spec/unit/resource/selinux_user_spec.rb +92 -0
- data/spec/unit/resource_spec.rb +86 -0
- metadata +22 -17
- data/lib/chef/powershell.rb +0 -81
- /data/spec/functional/assets/chocolatey_feed/{test-A.1.0.nupkg → test-A.1.0.0.nupkg} +0 -0
- /data/spec/functional/assets/chocolatey_feed/{test-A.1.5.nupkg → test-A.1.5.0.nupkg} +0 -0
- /data/spec/functional/assets/chocolatey_feed/{test-A.2.0.nupkg → test-A.2.0.0.nupkg} +0 -0
- /data/spec/functional/assets/chocolatey_feed/{test-B.1.0.nupkg → test-B.1.0.0.nupkg} +0 -0
@@ -0,0 +1,127 @@
|
|
1
|
+
if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
|
2
|
+
require "net/http" unless defined?(Net::HTTP)
|
3
|
+
# This is monkey-patch for ruby 3.1.x
|
4
|
+
# Due to change https://github.com/ruby/net-http/pull/10, when making net/http requests to a url which supports only IPv6 and not IPv4,
|
5
|
+
# ruby waits for IPv4 request to timeout first, then makes IPv6 request. This increased response time.
|
6
|
+
# NOTE 1: This is already reverted https://github.com/ruby/ruby/commit/f88bff770578583a708093f4a0d8b1483a1d2039 but under ruby 3.2.2
|
7
|
+
# NOTE 2: We are patching action `connect` from here https://github.com/ruby/ruby/blob/f88bff770578583a708093f4a0d8b1483a1d2039/lib/net/http.rb#L1000
|
8
|
+
|
9
|
+
module Net
|
10
|
+
class HTTP
|
11
|
+
def connect
|
12
|
+
if use_ssl?
|
13
|
+
# reference early to load OpenSSL before connecting,
|
14
|
+
# as OpenSSL may take time to load.
|
15
|
+
@ssl_context = OpenSSL::SSL::SSLContext.new
|
16
|
+
end
|
17
|
+
|
18
|
+
if proxy?
|
19
|
+
conn_addr = proxy_address
|
20
|
+
conn_port = proxy_port
|
21
|
+
else
|
22
|
+
conn_addr = conn_address
|
23
|
+
conn_port = port
|
24
|
+
end
|
25
|
+
|
26
|
+
puts "opening connection to #{conn_addr}:#{conn_port}..."
|
27
|
+
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
|
28
|
+
begin
|
29
|
+
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
|
30
|
+
rescue => e
|
31
|
+
raise e, "Failed to open TCP connection to " +
|
32
|
+
"#{conn_addr}:#{conn_port} (#{e.message})"
|
33
|
+
end
|
34
|
+
}
|
35
|
+
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
36
|
+
puts "opened"
|
37
|
+
if use_ssl?
|
38
|
+
if proxy?
|
39
|
+
plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
|
40
|
+
write_timeout: @write_timeout,
|
41
|
+
continue_timeout: @continue_timeout,
|
42
|
+
debug_output: @debug_output)
|
43
|
+
buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n"
|
44
|
+
buf << "Host: #{@address}:#{@port}\r\n"
|
45
|
+
if proxy_user
|
46
|
+
credential = ["#{proxy_user}:#{proxy_pass}"].pack("m0")
|
47
|
+
buf << "Proxy-Authorization: Basic #{credential}\r\n"
|
48
|
+
end
|
49
|
+
buf << "\r\n"
|
50
|
+
plain_sock.write(buf)
|
51
|
+
HTTPResponse.read_new(plain_sock).value
|
52
|
+
# assuming nothing left in buffers after successful CONNECT response
|
53
|
+
end
|
54
|
+
|
55
|
+
ssl_parameters = {}
|
56
|
+
iv_list = instance_variables
|
57
|
+
SSL_IVNAMES.each_with_index do |ivname, i|
|
58
|
+
if iv_list.include?(ivname)
|
59
|
+
value = instance_variable_get(ivname)
|
60
|
+
unless value.nil?
|
61
|
+
ssl_parameters[SSL_ATTRIBUTES[i]] = value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
@ssl_context.set_params(ssl_parameters)
|
66
|
+
unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
|
67
|
+
@ssl_context.session_cache_mode =
|
68
|
+
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
|
69
|
+
OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
|
70
|
+
end
|
71
|
+
if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
|
72
|
+
@ssl_context.session_new_cb = proc { |sock, sess| @ssl_session = sess }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Still do the post_connection_check below even if connecting
|
76
|
+
# to IP address
|
77
|
+
verify_hostname = @ssl_context.verify_hostname
|
78
|
+
|
79
|
+
# requiring 'resolv' near the top of the file causes registry.rb monkey patch to fail
|
80
|
+
# Windows 2012 R2 somehow fails to have Resolv defined unless we require it manually
|
81
|
+
require "resolv" unless defined?(Resolv)
|
82
|
+
|
83
|
+
# Server Name Indication (SNI) RFC 3546/6066
|
84
|
+
case @address
|
85
|
+
when ::Resolv::IPv4::Regex, ::Resolv::IPv6::Regex
|
86
|
+
# don't set SNI, as IP addresses in SNI is not valid
|
87
|
+
# per RFC 6066, section 3.
|
88
|
+
|
89
|
+
# Avoid openssl warning
|
90
|
+
@ssl_context.verify_hostname = false
|
91
|
+
else
|
92
|
+
ssl_host_address = @address
|
93
|
+
end
|
94
|
+
|
95
|
+
puts "starting SSL for #{conn_addr}:#{conn_port}..."
|
96
|
+
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
|
97
|
+
s.sync_close = true
|
98
|
+
s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
|
99
|
+
|
100
|
+
if @ssl_session &&
|
101
|
+
(Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout)
|
102
|
+
s.session = @ssl_session
|
103
|
+
end
|
104
|
+
ssl_socket_connect(s, @open_timeout)
|
105
|
+
if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
|
106
|
+
s.post_connection_check(@address)
|
107
|
+
end
|
108
|
+
puts "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
|
109
|
+
end
|
110
|
+
@socket = BufferedIO.new(s, read_timeout: @read_timeout,
|
111
|
+
write_timeout: @write_timeout,
|
112
|
+
continue_timeout: @continue_timeout,
|
113
|
+
debug_output: @debug_output)
|
114
|
+
@last_communicated = nil
|
115
|
+
on_connect
|
116
|
+
rescue => exception
|
117
|
+
if s
|
118
|
+
puts "Conn close because of connect error #{exception}"
|
119
|
+
s.close
|
120
|
+
end
|
121
|
+
raise
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
else
|
126
|
+
warn "Not applying net/http monkey patch needed for ruby 3.1"
|
127
|
+
end
|
@@ -39,11 +39,19 @@ class Chef
|
|
39
39
|
MUTATOR_METHODS.each do |mutator|
|
40
40
|
define_method(mutator) do |*args, &block|
|
41
41
|
ret = super(*args, &block)
|
42
|
+
# TODO: use `send_reset_cache(__path__)` for all mutator methods?
|
42
43
|
send_reset_cache
|
43
44
|
ret
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
def <<(obj)
|
49
|
+
ret = super(obj)
|
50
|
+
# NOTE: Expecting __path__ to be top-level attribute only
|
51
|
+
send_reset_cache(__path__)
|
52
|
+
ret
|
53
|
+
end
|
54
|
+
|
47
55
|
def delete(key, &block)
|
48
56
|
send_reset_cache(__path__, key)
|
49
57
|
super
|
@@ -32,13 +32,16 @@ class Chef
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def convert_value(value)
|
35
|
+
# The order in this case statement is *important*.
|
36
|
+
# ImmutableMash and ImmutableArray should be tested first,
|
37
|
+
# as this saves unnecessary creation of intermediate objects
|
35
38
|
case value
|
39
|
+
when ImmutableMash, ImmutableArray
|
40
|
+
value
|
36
41
|
when Hash
|
37
42
|
ImmutableMash.new(value, __root__, __node__, __precedence__)
|
38
43
|
when Array
|
39
44
|
ImmutableArray.new(value, __root__, __node__, __precedence__)
|
40
|
-
when ImmutableMash, ImmutableArray
|
41
|
-
value
|
42
45
|
else
|
43
46
|
safe_dup(value).freeze
|
44
47
|
end
|
@@ -78,7 +78,7 @@ class Chef
|
|
78
78
|
|
79
79
|
def send_reset_cache(path = nil, key = nil)
|
80
80
|
next_path = [ path, key ].flatten.compact
|
81
|
-
__root__.reset_cache(next_path.first) if !__root__.nil? && __root__.respond_to?(:reset_cache)
|
81
|
+
__root__.reset_cache(next_path.first) if !__root__.nil? && __root__.respond_to?(:reset_cache)
|
82
82
|
end
|
83
83
|
|
84
84
|
def copy_state_to(ret, next_path)
|
@@ -17,11 +17,14 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require "chef-utils" unless defined?(ChefUtils::CANARY)
|
20
|
+
require_relative "../mixin/powershell_exec"
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Platform
|
23
24
|
|
24
25
|
class << self
|
26
|
+
include Chef::Mixin::PowershellExec
|
27
|
+
|
25
28
|
def windows?
|
26
29
|
ChefUtils.windows?
|
27
30
|
end
|
@@ -58,8 +61,7 @@ class Chef
|
|
58
61
|
end
|
59
62
|
|
60
63
|
def dsc_refresh_mode_disabled?(node)
|
61
|
-
|
62
|
-
exec = Chef::PowerShell.new("Get-DscLocalConfigurationManager")
|
64
|
+
exec = powershell_exec!("Get-DscLocalConfigurationManager")
|
63
65
|
exec.error!
|
64
66
|
exec.result["RefreshMode"] == "Disabled"
|
65
67
|
end
|
@@ -39,7 +39,7 @@ class Chef
|
|
39
39
|
|
40
40
|
def mounted?
|
41
41
|
mounted = false
|
42
|
-
real_mount_point = if ::File.
|
42
|
+
real_mount_point = if ::File.exist? @new_resource.mount_point
|
43
43
|
::File.realpath(@new_resource.mount_point)
|
44
44
|
else
|
45
45
|
@new_resource.mount_point
|
@@ -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.
|
45
|
+
if device_should_exist? && !::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.
|
47
|
+
elsif @new_resource.mount_point != "none" && !::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
|
|
@@ -81,7 +81,7 @@ 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.
|
84
|
+
real_mount_point = if ::File.exist? @new_resource.mount_point
|
85
85
|
::File.realpath(@new_resource.mount_point)
|
86
86
|
else
|
87
87
|
@new_resource.mount_point
|
@@ -186,7 +186,7 @@ class Chef
|
|
186
186
|
def device_should_exist?
|
187
187
|
( @new_resource.device != "none" ) &&
|
188
188
|
( not network_device? ) &&
|
189
|
-
( not %w{ cgroup tmpfs fuse vboxsf zfs }.include? @new_resource.fstype )
|
189
|
+
( not %w{ cgroup tmpfs fuse vboxsf zfs efivarfs }.include? @new_resource.fstype )
|
190
190
|
end
|
191
191
|
|
192
192
|
private
|
@@ -287,4 +287,4 @@ class Chef
|
|
287
287
|
end
|
288
288
|
end
|
289
289
|
end
|
290
|
-
end
|
290
|
+
end
|
@@ -130,6 +130,21 @@ class Chef
|
|
130
130
|
# install from, but like the rubygem provider's sources which are more like repos.
|
131
131
|
def check_resource_semantics!; end
|
132
132
|
|
133
|
+
def self.get_choco_version
|
134
|
+
@get_choco_version ||= powershell_exec!("choco --version").result
|
135
|
+
end
|
136
|
+
|
137
|
+
# Choco V2 uses 'Search' for remote repositories and 'List' for local packages
|
138
|
+
def self.query_command
|
139
|
+
return "list" if get_choco_version.match?(/^1/)
|
140
|
+
|
141
|
+
"search"
|
142
|
+
end
|
143
|
+
|
144
|
+
def query_command
|
145
|
+
self.class.query_command
|
146
|
+
end
|
147
|
+
|
133
148
|
private
|
134
149
|
|
135
150
|
def version_compare(v1, v2)
|
@@ -225,7 +240,7 @@ class Chef
|
|
225
240
|
package_name_array.each do |pkg|
|
226
241
|
available_versions =
|
227
242
|
begin
|
228
|
-
cmd = [
|
243
|
+
cmd = [ query_command, "-r", pkg ]
|
229
244
|
cmd += common_options
|
230
245
|
cmd.push( new_resource.list_options ) if new_resource.list_options
|
231
246
|
|
@@ -242,6 +257,8 @@ class Chef
|
|
242
257
|
# Installed packages in chocolatey as a Hash of names mapped to versions
|
243
258
|
# (names are downcased for case-insensitive matching)
|
244
259
|
#
|
260
|
+
# Beginning with Choco 2.0, "list" returns local packages only while "search" returns packages from external package sources
|
261
|
+
#
|
245
262
|
# @return [Hash] name-to-version mapping of installed packages
|
246
263
|
def installed_packages
|
247
264
|
@installed_packages ||= Hash[*parse_list_output("list", "-l", "-r").flatten]
|
@@ -141,6 +141,7 @@ class Chef
|
|
141
141
|
if md = line.match(/^(\S*)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(.*)$/)
|
142
142
|
(status, name, type, version, arch, repo) = [ md[1], md[2], md[3], md[4], md[5], md[6] ]
|
143
143
|
next if version == "Version" # header
|
144
|
+
next if name != package_name
|
144
145
|
|
145
146
|
# sometimes even though we request a specific version in the search string above and have match exact, we wind up
|
146
147
|
# with other versions in the output, particularly getting the installed version when downgrading.
|
@@ -45,7 +45,7 @@ class Chef
|
|
45
45
|
if new_resource.make_cache
|
46
46
|
notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers
|
47
47
|
# makecache fast only works on non-dnf systems.
|
48
|
-
if !which
|
48
|
+
if !which("dnf") && new_resource.makecache_fast
|
49
49
|
notifies :run, "execute[yum-makecache-fast-#{new_resource.repositoryid}]", :immediately
|
50
50
|
else
|
51
51
|
notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately
|
@@ -98,6 +98,18 @@ class Chef
|
|
98
98
|
end
|
99
99
|
```
|
100
100
|
|
101
|
+
**Add repository that needs custom options**:
|
102
|
+
```ruby
|
103
|
+
apt_repository 'corretto' do
|
104
|
+
uri 'https://apt.corretto.aws'
|
105
|
+
arch 'amd64'
|
106
|
+
distribution 'stable'
|
107
|
+
components ['main']
|
108
|
+
options ['target-=Contents-deb']
|
109
|
+
key 'https://apt.corretto.aws/corretto.key'
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
101
113
|
**Remove a repository from the list**:
|
102
114
|
|
103
115
|
```ruby
|
@@ -159,6 +171,10 @@ class Chef
|
|
159
171
|
description: "Determines whether to rebuild the APT package cache.",
|
160
172
|
default: true, desired_state: false
|
161
173
|
|
174
|
+
property :options, [String, Array],
|
175
|
+
description: "Additional options to set for the repository",
|
176
|
+
default: [], coerce: proc { |x| Array(x) }
|
177
|
+
|
162
178
|
default_action :add
|
163
179
|
allowed_actions :add, :remove
|
164
180
|
|
@@ -388,19 +404,21 @@ class Chef
|
|
388
404
|
# @param [Array] components
|
389
405
|
# @param [Boolean] trusted
|
390
406
|
# @param [String] arch
|
407
|
+
# @param [Array] options
|
391
408
|
# @param [Boolean] add_src
|
392
409
|
#
|
393
410
|
# @return [String] complete repo config text
|
394
|
-
def build_repo(uri, distribution, components, trusted, arch, add_src = false)
|
411
|
+
def build_repo(uri, distribution, components, trusted, arch, options, add_src = false)
|
395
412
|
uri = make_ppa_url(uri) if is_ppa_url?(uri)
|
396
413
|
|
397
414
|
uri = Addressable::URI.parse(uri)
|
398
415
|
components = Array(components).join(" ")
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
416
|
+
options_list = []
|
417
|
+
options_list << "arch=#{arch}" if arch
|
418
|
+
options_list << "trusted=yes" if trusted
|
419
|
+
options_list += options
|
420
|
+
optstr = unless options_list.empty?
|
421
|
+
"[" + options_list.join(" ") + "]"
|
404
422
|
end
|
405
423
|
info = [ optstr, uri.normalize.to_s, distribution, components ].compact.join(" ")
|
406
424
|
repo = "deb #{info}\n"
|
@@ -461,6 +479,7 @@ class Chef
|
|
461
479
|
repo_components,
|
462
480
|
new_resource.trusted,
|
463
481
|
new_resource.arch,
|
482
|
+
new_resource.options,
|
464
483
|
new_resource.deb_src
|
465
484
|
)
|
466
485
|
|
@@ -45,8 +45,7 @@ class Chef
|
|
45
45
|
default: true
|
46
46
|
|
47
47
|
property :homebrew_path, String,
|
48
|
-
description: "The path to the
|
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 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, /opt/homebrew/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.'"
|
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?("/
|
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."
|
@@ -50,15 +50,17 @@ class Chef
|
|
50
50
|
end
|
51
51
|
```
|
52
52
|
|
53
|
-
**
|
53
|
+
**Setting a value for specific user and hosts**
|
54
54
|
|
55
55
|
```ruby
|
56
|
-
macos_userdefaults '
|
57
|
-
key '
|
58
|
-
value
|
59
|
-
|
56
|
+
macos_userdefaults 'Enable macOS firewall' do
|
57
|
+
key 'globalstate'
|
58
|
+
value 1
|
59
|
+
user 'jane'
|
60
|
+
host :current
|
60
61
|
end
|
61
62
|
```
|
63
|
+
|
62
64
|
DOC
|
63
65
|
|
64
66
|
property :domain, String,
|
@@ -79,6 +81,7 @@ class Chef
|
|
79
81
|
|
80
82
|
property :host, [String, Symbol],
|
81
83
|
description: "Set either :current, :all or a hostname to set the user default at the host level.",
|
84
|
+
default: :all,
|
82
85
|
desired_state: false,
|
83
86
|
introduced: "16.3"
|
84
87
|
|
@@ -94,6 +97,7 @@ class Chef
|
|
94
97
|
|
95
98
|
property :user, [String, Symbol],
|
96
99
|
description: "The system user that the default will be applied to. Set :current for current user, :all for all users or pass a valid username",
|
100
|
+
default: :current,
|
97
101
|
desired_state: false
|
98
102
|
|
99
103
|
property :sudo, [TrueClass, FalseClass],
|