chef 18.1.29 → 18.3.0
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/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/apt/chef-integration-test-1.0/debian/rules +0 -0
- data/spec/data/apt/chef-integration-test-1.1/debian/rules +0 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/rules +0 -0
- data/spec/data/trusted_certs/intermediate.pem +38 -27
- data/spec/data/trusted_certs/opscode.pem +33 -54
- data/spec/functional/assets/chefinittest +0 -0
- data/spec/functional/assets/testchefsubsys +0 -0
- data/spec/functional/provider/remote_file/cache_control_data_spec.rb +0 -0
- data/spec/functional/resource/aix_service_spec.rb +0 -0
- data/spec/functional/resource/aixinit_service_spec.rb +0 -0
- 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 +19 -15
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3856e8d0d5224634cad3eb9d43ecf3e87cc504ee881474f7698a14eb90e15088
|
4
|
+
data.tar.gz: 7830af2c8acab4e76176876a2aaac1363d9a8ff706a78422ec98d6d522772856
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4503271efa5b5e0713e2753056c32f6c9fb044935802571d8ef3a4024788dd23f9b6ca7da74e1210d1eaedf03b2b44ecc6e7a0e28059078e815b78161ca4e502
|
7
|
+
data.tar.gz: 150281399db54afc60e2f910b3dd4322b0d6f287f97d57b9c530fea39d705bbc4dd0b89cb43807f642674c0ae0ce20d40964bba5fe757a76d4af71fa6b7dc7d1
|
@@ -15,9 +15,9 @@ 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", "~> 1.0
|
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}/**/*")
|
22
22
|
|
23
|
-
gemspec
|
23
|
+
gemspec
|
data/chef.gemspec
CHANGED
@@ -49,8 +49,7 @@ Gem::Specification.new do |s|
|
|
49
49
|
s.add_dependency "net-ftp" # remote_file resource
|
50
50
|
s.add_dependency "erubis", "~> 2.7" # template resource / cookbook syntax check
|
51
51
|
s.add_dependency "diff-lcs", ">= 1.2.4", "!= 1.4.0", "< 1.6.0" # 1.4 breaks output. Used in lib/chef/util/diff
|
52
|
-
|
53
|
-
s.add_dependency "ffi-libarchive", "~> 1.1", ">= 1.1.3"
|
52
|
+
s.add_dependency "ffi-libarchive", "~> 1.0", ">= 1.0.3" # archive_file resource
|
54
53
|
s.add_dependency "chef-zero", ">= 14.0.11"
|
55
54
|
s.add_dependency "chef-vault" # chef-vault resources and helpers
|
56
55
|
|
@@ -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)
|
@@ -124,11 +124,11 @@ class Chef
|
|
124
124
|
end
|
125
125
|
|
126
126
|
def self.get_cert_user
|
127
|
-
Chef::Config[:auth_key_registry_type] == "user" ?
|
127
|
+
Chef::Config[:auth_key_registry_type] == "user" ? "CurrentUser" : "LocalMachine"
|
128
128
|
end
|
129
129
|
|
130
130
|
def self.get_registry_user
|
131
|
-
Chef::Config[:auth_key_registry_type] == "user" ?
|
131
|
+
Chef::Config[:auth_key_registry_type] == "user" ? "HKEY_CURRENT_USER" : "HKEY_LOCAL_MACHINE"
|
132
132
|
end
|
133
133
|
|
134
134
|
def self.check_certstore_for_key(client_name)
|
@@ -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)
|
@@ -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
|