chef 18.1.29 → 18.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/chef-universal-mingw-ucrt.gemspec +2 -2
  3. data/chef.gemspec +1 -2
  4. data/lib/chef/application/base.rb +2 -0
  5. data/lib/chef/client.rb +2 -2
  6. data/lib/chef/cookbook/synchronizer.rb +20 -2
  7. data/lib/chef/cookbook_version.rb +1 -1
  8. data/lib/chef/http/authenticator.rb +2 -2
  9. data/lib/chef/http/ssl_policies.rb +2 -2
  10. data/lib/chef/mixin/homebrew_user.rb +12 -5
  11. data/lib/chef/mixin/proxified_socket.rb +1 -1
  12. data/lib/chef/monkey_patches/net-http.rb +127 -0
  13. data/lib/chef/node/attribute_collections.rb +8 -0
  14. data/lib/chef/node/immutable_collections.rb +5 -2
  15. data/lib/chef/node/mixin/state_tracking.rb +1 -1
  16. data/lib/chef/platform/query_helpers.rb +4 -2
  17. data/lib/chef/provider/launchd.rb +1 -1
  18. data/lib/chef/provider/mount/linux.rb +1 -1
  19. data/lib/chef/provider/mount/mount.rb +5 -5
  20. data/lib/chef/provider/package/chocolatey.rb +18 -1
  21. data/lib/chef/provider/package/zypper.rb +1 -0
  22. data/lib/chef/provider/remote_file/http.rb +1 -1
  23. data/lib/chef/provider/yum_repository.rb +1 -1
  24. data/lib/chef/resource/apt_repository.rb +25 -6
  25. data/lib/chef/resource/homebrew_cask.rb +6 -7
  26. data/lib/chef/resource/homebrew_package.rb +1 -1
  27. data/lib/chef/resource/homebrew_tap.rb +5 -5
  28. data/lib/chef/resource/launchd.rb +5 -1
  29. data/lib/chef/resource/macos_userdefaults.rb +9 -5
  30. data/lib/chef/resource/selinux_login.rb +129 -0
  31. data/lib/chef/resource/selinux_user.rb +137 -0
  32. data/lib/chef/resource/windows_certificate.rb +1 -1
  33. data/lib/chef/resource/windows_security_policy.rb +2 -2
  34. data/lib/chef/resource.rb +11 -1
  35. data/lib/chef/resources.rb +2 -0
  36. data/lib/chef/version.rb +1 -1
  37. data/lib/chef/win32/security.rb +7 -1
  38. data/spec/data/apt/chef-integration-test-1.0/debian/rules +0 -0
  39. data/spec/data/apt/chef-integration-test-1.1/debian/rules +0 -0
  40. data/spec/data/apt/chef-integration-test2-1.0/debian/rules +0 -0
  41. data/spec/data/trusted_certs/intermediate.pem +38 -27
  42. data/spec/data/trusted_certs/opscode.pem +33 -54
  43. data/spec/functional/assets/chefinittest +0 -0
  44. data/spec/functional/assets/testchefsubsys +0 -0
  45. data/spec/functional/provider/remote_file/cache_control_data_spec.rb +0 -0
  46. data/spec/functional/resource/aix_service_spec.rb +0 -0
  47. data/spec/functional/resource/aixinit_service_spec.rb +0 -0
  48. data/spec/functional/resource/chocolatey_package_spec.rb +32 -20
  49. data/spec/functional/resource/execute_spec.rb +1 -1
  50. data/spec/functional/resource/macos_userdefaults_spec.rb +4 -4
  51. data/spec/functional/resource/windows_certificate_spec.rb +25 -0
  52. data/spec/unit/client_spec.rb +2 -2
  53. data/spec/unit/mixin/homebrew_user_spec.rb +30 -7
  54. data/spec/unit/node/vivid_mash_spec.rb +42 -0
  55. data/spec/unit/provider/apt_repository_spec.rb +17 -7
  56. data/spec/unit/provider/launchd_spec.rb +2 -2
  57. data/spec/unit/provider/mount/aix_spec.rb +2 -2
  58. data/spec/unit/provider/mount/linux_spec.rb +6 -5
  59. data/spec/unit/provider/mount/mount_spec.rb +8 -8
  60. data/spec/unit/provider/package/chocolatey_spec.rb +19 -3
  61. data/spec/unit/provider/package/rpm_spec.rb +2 -2
  62. data/spec/unit/provider/package/zypper_spec.rb +10 -0
  63. data/spec/unit/provider/remote_file/http_spec.rb +4 -4
  64. data/spec/unit/resource/apt_repository_spec.rb +5 -0
  65. data/spec/unit/resource/macos_user_defaults_spec.rb +4 -4
  66. data/spec/unit/resource/selinux_login_spec.rb +73 -0
  67. data/spec/unit/resource/selinux_user_spec.rb +92 -0
  68. data/spec/unit/resource_spec.rb +86 -0
  69. metadata +19 -15
  70. data/lib/chef/powershell.rb +0 -81
  71. /data/spec/functional/assets/chocolatey_feed/{test-A.1.0.nupkg → test-A.1.0.0.nupkg} +0 -0
  72. /data/spec/functional/assets/chocolatey_feed/{test-A.1.5.nupkg → test-A.1.5.0.nupkg} +0 -0
  73. /data/spec/functional/assets/chocolatey_feed/{test-A.2.0.nupkg → test-A.2.0.0.nupkg} +0 -0
  74. /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: 01fc036d9cbe5a20b0ca17c3d09db60986f92c4759ce2b20212e0b34d9a57535
4
- data.tar.gz: 16f9392fddd572bf0d5e58c35d2018a423ee20858038af6bc0d49aa5cdd55626
3
+ metadata.gz: 3856e8d0d5224634cad3eb9d43ecf3e87cc504ee881474f7698a14eb90e15088
4
+ data.tar.gz: 7830af2c8acab4e76176876a2aaac1363d9a8ff706a78422ec98d6d522772856
5
5
  SHA512:
6
- metadata.gz: e7ca0d1982af93db302d882654d42544dee4344ee9c9025c8ea857e2bf6fcb9f6dfdebd7b8eb78dd559e88d4597a6153d3acd04397eb708cc419ca0f782ed380
7
- data.tar.gz: 673c088d0f223b34daa9cf14a7598d80d0b5c7276e6478d54a93e64c12550235a05c10d39cba1d9d522a5b42fa654c113d943e618c1e4eea9cf45bae9ec81ae2
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.12" # 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.
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
- # s.add_dependency "ffi-libarchive", "~> 1.0", ">= 1.0.3" # archive_file resource
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.exists?(config[:client_key])
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.exists?(path) || (Dir.entries(path).size <= 2)
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
- ( cookbook_name, segment, file ) = md[1..3]
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
- if manifest_segment.select { |manifest_record| manifest_record["path"] == "#{segment}/#{file}" }.empty?
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)
@@ -474,7 +474,7 @@ class Chef
474
474
  end
475
475
 
476
476
  def reload_metadata!
477
- if File.exists?(metadata_json_file)
477
+ if File.exist?(metadata_json_file)
478
478
  metadata.from_json(IO.read(metadata_json_file))
479
479
  end
480
480
  end
@@ -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" ? store = "CurrentUser" : store = "LocalMachine"
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" ? store = "HKEY_CURRENT_USER" : store = "HKEY_LOCAL_MACHINE"
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.exists?(config[:ssl_client_cert])
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.exists?(config[:ssl_client_key])
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
- default_brew_path = "/usr/local/bin/brew"
64
- if ::File.exist?(default_brew_path)
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 in /usr/local/bin or anywhere on the path.'
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"
@@ -15,7 +15,7 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
- require "proxifier2"
18
+ require "proxifier"
19
19
  require "chef-config/mixin/fuzzy_hostname_matcher"
20
20
 
21
21
  class Chef
@@ -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) && !next_path.nil?
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
- require_relative "../powershell"
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
@@ -52,7 +52,7 @@ class Chef
52
52
  end
53
53
 
54
54
  action :delete, description: "Delete a launchd property list. This will unload a daemon or agent, if loaded." do
55
- if ::File.exists?(path)
55
+ if ::File.exist?(path)
56
56
  manage_service(:disable)
57
57
  end
58
58
  manage_plist(:delete)
@@ -39,7 +39,7 @@ class Chef
39
39
 
40
40
  def mounted?
41
41
  mounted = false
42
- real_mount_point = if ::File.exists? @new_resource.mount_point
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.exists?(device_real)
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.exists?(@new_resource.mount_point)
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.exists? @new_resource.mount_point
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 = [ "list", "-r", pkg ]
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.
@@ -113,7 +113,7 @@ class Chef
113
113
  end
114
114
 
115
115
  def last_modified_time_from(response)
116
- response["last_modified"] || response["date"]
116
+ response["last-modified"] || response["date"]
117
117
  end
118
118
 
119
119
  def etag_from(response)
@@ -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 "dnf" && new_resource.makecache_fast
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
- options = []
400
- options << "arch=#{arch}" if arch
401
- options << "trusted=yes" if trusted
402
- optstr = unless options.empty?
403
- "[" + options.join(" ") + "]"
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 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 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