chef 18.2.7-x64-mingw-ucrt → 18.3.0-x64-mingw-ucrt
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/chef-universal-mingw-ucrt.gemspec +1 -1
- 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/ssl_policies.rb +2 -2
- data/lib/chef/mixin/homebrew_user.rb +12 -5
- 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/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/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/version.rb +1 -1
- data/lib/chef/win32/security.rb +7 -1
- data/spec/functional/resource/chocolatey_package_spec.rb +32 -20
- data/spec/functional/resource/execute_spec.rb +1 -1
- 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_spec.rb +86 -0
- metadata +13 -12
- /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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 034b891e91a35febfaea15c74c7236eba8d503221d7f4aaa8ac8cca985b296e7
|
4
|
+
data.tar.gz: 84a49732354b3f8b2c11d2713093c5317b6c6d8e335d1f850458cf9abbf5038d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 781e2665ae7cc103a9140bf5f024dca9222dae1aa00d7119bab296007409e77a6854102e6367caa48b65ad0e1546e349453b57865ace723216259f9acdb48d6f
|
7
|
+
data.tar.gz: ffa726a2dd3f8f9228b08dc8741d92ae96f4b2703484dcd4ab9c72ba8eefdef9ad89230d15d669dbf2eeda017d0e2842241d8bb1a7e080d754906d01b00ebbdf
|
@@ -15,7 +15,7 @@ gemspec.add_dependency "wmi-lite", "~> 1.0"
|
|
15
15
|
gemspec.add_dependency "win32-taskscheduler", "~> 2.0"
|
16
16
|
gemspec.add_dependency "iso8601", ">= 0.12.1", "< 0.14" # validate 0.14 when it comes out
|
17
17
|
gemspec.add_dependency "win32-certstore", "~> 0.6.15" # 0.5+ required for specifying user vs. system store
|
18
|
-
gemspec.add_dependency "chef-powershell", "~> 18.
|
18
|
+
gemspec.add_dependency "chef-powershell", "~> 18.1.0" # The guts of the powershell_exec code have been moved to its own gem, chef-powershell. It's part of the chef-powershell-shim repo.
|
19
19
|
|
20
20
|
gemspec.extensions << "ext/win32-eventlog/Rakefile"
|
21
21
|
gemspec.files += Dir.glob("{distro,ext}/**/*")
|
@@ -24,6 +24,8 @@ require "chef-utils/dist" unless defined?(ChefUtils::Dist)
|
|
24
24
|
require_relative "../daemon"
|
25
25
|
require "chef-config/mixin/dot_d"
|
26
26
|
require "license_acceptance/cli_flags/mixlib_cli"
|
27
|
+
require "chef/monkey_patches/net-http"
|
28
|
+
|
27
29
|
module Mixlib
|
28
30
|
autoload :Archive, "mixlib/archive"
|
29
31
|
end
|
data/lib/chef/client.rb
CHANGED
@@ -663,7 +663,7 @@ class Chef
|
|
663
663
|
logger.trace("New client keys created in the Certificate Store - skipping registration")
|
664
664
|
end
|
665
665
|
events.skipping_registration(client_name, config)
|
666
|
-
elsif File.
|
666
|
+
elsif File.exist?(config[:client_key])
|
667
667
|
events.skipping_registration(client_name, config)
|
668
668
|
logger.trace("Client key #{config[:client_key]} is present - skipping registration")
|
669
669
|
else
|
@@ -1069,7 +1069,7 @@ class Chef
|
|
1069
1069
|
end
|
1070
1070
|
|
1071
1071
|
def empty_directory?(path)
|
1072
|
-
!File.
|
1072
|
+
!File.exist?(path) || (Dir.entries(path).size <= 2)
|
1073
1073
|
end
|
1074
1074
|
|
1075
1075
|
def is_last_element?(index, object)
|
@@ -18,6 +18,7 @@ require_relative "../util/threaded_job_queue"
|
|
18
18
|
require_relative "../server_api"
|
19
19
|
require "singleton" unless defined?(Singleton)
|
20
20
|
require "chef-utils/dist" unless defined?(ChefUtils::Dist)
|
21
|
+
require "set" unless defined?(Set)
|
21
22
|
|
22
23
|
class Chef
|
23
24
|
|
@@ -219,14 +220,31 @@ class Chef
|
|
219
220
|
|
220
221
|
# remove deleted files in cookbooks that are being used on the node
|
221
222
|
def remove_deleted_files
|
223
|
+
cache_file_hash = {}
|
224
|
+
@cookbooks_by_name.each_key do |k|
|
225
|
+
cache_file_hash[k] = {}
|
226
|
+
end
|
227
|
+
|
228
|
+
# First populate files from cache
|
222
229
|
cache.find(File.join(%w{cookbooks ** {*,.*}})).each do |cache_file|
|
223
230
|
md = cache_file.match(%r{^cookbooks/([^/]+)/([^/]+)/(.*)})
|
224
231
|
next unless md
|
225
232
|
|
226
|
-
(
|
233
|
+
(cookbook_name, segment, file) = md[1..3]
|
227
234
|
if have_cookbook?(cookbook_name)
|
235
|
+
cache_file_hash[cookbook_name][segment] ||= {}
|
236
|
+
cache_file_hash[cookbook_name][segment]["#{segment}/#{file}"] = cache_file
|
237
|
+
end
|
238
|
+
end
|
239
|
+
# Determine which files don't match manifest
|
240
|
+
@cookbooks_by_name.each_key do |cookbook_name|
|
241
|
+
cache_file_hash[cookbook_name].each_key do |segment|
|
228
242
|
manifest_segment = cookbook_segment(cookbook_name, segment)
|
229
|
-
|
243
|
+
manifest_record_paths = manifest_segment.map { |manifest_record| manifest_record["path"] }.to_set
|
244
|
+
to_be_removed = cache_file_hash[cookbook_name][segment].keys.to_set - manifest_record_paths
|
245
|
+
to_be_removed.each do |path|
|
246
|
+
cache_file = cache_file_hash[cookbook_name][segment][path]
|
247
|
+
|
230
248
|
Chef::Log.info("Removing #{cache_file} from the cache; its is no longer in the cookbook manifest.")
|
231
249
|
cache.delete(cache_file)
|
232
250
|
@events.removed_cookbook_file(cache_file)
|
@@ -103,10 +103,10 @@ class Chef
|
|
103
103
|
unless config[:ssl_client_cert] && config[:ssl_client_key]
|
104
104
|
raise Chef::Exceptions::ConfigurationError, "You must configure ssl_client_cert and ssl_client_key together"
|
105
105
|
end
|
106
|
-
unless ::File.
|
106
|
+
unless ::File.exist?(config[:ssl_client_cert])
|
107
107
|
raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_cert #{config[:ssl_client_cert]} does not exist"
|
108
108
|
end
|
109
|
-
unless ::File.
|
109
|
+
unless ::File.exist?(config[:ssl_client_key])
|
110
110
|
raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist"
|
111
111
|
end
|
112
112
|
|
@@ -57,18 +57,25 @@ class Chef
|
|
57
57
|
@homebrew_owner_username
|
58
58
|
end
|
59
59
|
|
60
|
+
def homebrew_bin_path(brew_bin_path = nil)
|
61
|
+
if brew_bin_path && ::File.exist?(brew_bin_path)
|
62
|
+
brew_bin_path
|
63
|
+
else
|
64
|
+
brew_bin_path = [which("brew"), "/opt/homebrew/bin/brew", "/usr/local/bin/brew", "/home/linuxbrew/.linuxbrew/bin/brew"].uniq.select { |x| ::File.exist?(x) && ::File.executable?(x) }.first
|
65
|
+
brew_bin_path || nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
60
69
|
private
|
61
70
|
|
62
71
|
def calculate_owner
|
63
|
-
|
64
|
-
if
|
72
|
+
brew_path = homebrew_bin_path
|
73
|
+
if brew_path
|
65
74
|
# By default, this follows symlinks which is what we want
|
66
|
-
owner = ::File.stat(default_brew_path).uid
|
67
|
-
elsif (brew_path = shell_out("which brew").stdout.strip) && !brew_path.empty?
|
68
75
|
owner = ::File.stat(brew_path).uid
|
69
76
|
else
|
70
77
|
raise Chef::Exceptions::CannotDetermineHomebrewOwner,
|
71
|
-
'Could not find the "brew" executable
|
78
|
+
'Could not find the "brew" executable anywhere on the path.'
|
72
79
|
end
|
73
80
|
|
74
81
|
Chef::Log.debug "Found Homebrew owner #{Etc.getpwuid(owner).name}; executing `brew` commands as them"
|
@@ -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)
|
@@ -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."
|
@@ -440,7 +440,7 @@ class Chef
|
|
440
440
|
def export_cert(cert_obj, output_path:, store_name:, store_location:, pfx_password:)
|
441
441
|
# Delete the cert if it exists on disk already.
|
442
442
|
# We want to ensure we're not randomly loading an old stinky cert.
|
443
|
-
if ::File.
|
443
|
+
if ::File.exist?(output_path)
|
444
444
|
::File.delete(output_path)
|
445
445
|
end
|
446
446
|
|