chef 18.2.7 → 18.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/chef-universal-mingw-ucrt.gemspec +1 -1
  4. data/chef.gemspec +3 -3
  5. data/lib/chef/application/base.rb +2 -0
  6. data/lib/chef/chef_fs/file_pattern.rb +1 -1
  7. data/lib/chef/chef_fs/path_utils.rb +7 -9
  8. data/lib/chef/client.rb +2 -2
  9. data/lib/chef/cookbook/synchronizer.rb +19 -2
  10. data/lib/chef/cookbook_version.rb +1 -1
  11. data/lib/chef/delayed_evaluator.rb +4 -0
  12. data/lib/chef/file_access_control/windows.rb +4 -1
  13. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +2 -0
  14. data/lib/chef/http/ssl_policies.rb +2 -2
  15. data/lib/chef/mixin/homebrew_user.rb +15 -5
  16. data/lib/chef/monkey_patches/net-http.rb +127 -0
  17. data/lib/chef/node/attribute_collections.rb +10 -1
  18. data/lib/chef/node/immutable_collections.rb +7 -3
  19. data/lib/chef/node/mixin/state_tracking.rb +1 -1
  20. data/lib/chef/node/mixin/state_tracking_array.rb +41 -0
  21. data/lib/chef/node.rb +22 -0
  22. data/lib/chef/provider/launchd.rb +1 -1
  23. data/lib/chef/provider/mount/linux.rb +1 -1
  24. data/lib/chef/provider/mount/mount.rb +5 -5
  25. data/lib/chef/provider/package/apt.rb +11 -2
  26. data/lib/chef/provider/package/chocolatey.rb +239 -18
  27. data/lib/chef/provider/package/zypper.rb +6 -0
  28. data/lib/chef/provider/powershell_script.rb +96 -6
  29. data/lib/chef/provider/remote_file/http.rb +1 -1
  30. data/lib/chef/provider/service/systemd.rb +23 -8
  31. data/lib/chef/provider/service/windows.rb +1 -0
  32. data/lib/chef/provider/service.rb +14 -0
  33. data/lib/chef/provider/user.rb +5 -1
  34. data/lib/chef/provider/yum_repository.rb +1 -1
  35. data/lib/chef/recipe.rb +3 -11
  36. data/lib/chef/resource/_rest_resource.rb +1 -1
  37. data/lib/chef/resource/apt_package.rb +19 -0
  38. data/lib/chef/resource/apt_repository.rb +26 -6
  39. data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
  40. data/lib/chef/resource/chocolatey_installer.rb +207 -0
  41. data/lib/chef/resource/chocolatey_package.rb +8 -0
  42. data/lib/chef/resource/homebrew_cask.rb +6 -7
  43. data/lib/chef/resource/homebrew_package.rb +1 -1
  44. data/lib/chef/resource/homebrew_tap.rb +5 -5
  45. data/lib/chef/resource/launchd.rb +5 -1
  46. data/lib/chef/resource/locale.rb +5 -2
  47. data/lib/chef/resource/macos_pkg.rb +111 -0
  48. data/lib/chef/resource/powershell_script.rb +5 -1
  49. data/lib/chef/resource/service.rb +3 -0
  50. data/lib/chef/resource/sudo.rb +37 -2
  51. data/lib/chef/resource/support/ulimit.erb +40 -0
  52. data/lib/chef/resource/user_ulimit.rb +38 -0
  53. data/lib/chef/resource/windows_certificate.rb +1 -1
  54. data/lib/chef/resource/windows_security_policy.rb +2 -2
  55. data/lib/chef/resource.rb +11 -1
  56. data/lib/chef/resources.rb +2 -0
  57. data/lib/chef/version.rb +1 -1
  58. data/lib/chef/win32/security.rb +7 -1
  59. data/spec/data/trusted_certs/example.crt +29 -20
  60. data/spec/data/trusted_certs/example_no_cn.crt +30 -34
  61. data/spec/functional/resource/chocolatey_package_spec.rb +32 -20
  62. data/spec/functional/resource/execute_spec.rb +1 -1
  63. data/spec/functional/resource/windows_certificate_spec.rb +25 -0
  64. data/spec/functional/resource/zypper_package_spec.rb +10 -0
  65. data/spec/unit/client_spec.rb +2 -2
  66. data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +1 -1
  67. data/spec/unit/delayed_evaluator_spec.rb +35 -0
  68. data/spec/unit/mixin/homebrew_user_spec.rb +30 -7
  69. data/spec/unit/node/vivid_mash_spec.rb +42 -0
  70. data/spec/unit/node_spec.rb +6 -0
  71. data/spec/unit/provider/apt_repository_spec.rb +17 -7
  72. data/spec/unit/provider/launchd_spec.rb +2 -2
  73. data/spec/unit/provider/mount/aix_spec.rb +2 -2
  74. data/spec/unit/provider/mount/linux_spec.rb +6 -5
  75. data/spec/unit/provider/mount/mount_spec.rb +8 -8
  76. data/spec/unit/provider/package/apt_spec.rb +18 -13
  77. data/spec/unit/provider/package/chocolatey_spec.rb +53 -9
  78. data/spec/unit/provider/package/rpm_spec.rb +2 -2
  79. data/spec/unit/provider/package/zypper_spec.rb +10 -0
  80. data/spec/unit/provider/powershell_script_spec.rb +100 -4
  81. data/spec/unit/provider/remote_file/http_spec.rb +4 -4
  82. data/spec/unit/provider/service/systemd_service_spec.rb +1 -0
  83. data/spec/unit/provider/user/linux_spec.rb +10 -0
  84. data/spec/unit/resource/apt_repository_spec.rb +5 -0
  85. data/spec/unit/resource/chef_client_systemd_timer_spec.rb +1 -1
  86. data/spec/unit/resource/chocolatey_installer_spec.rb +151 -0
  87. data/spec/unit/resource/macos_pkg_spec.rb +38 -0
  88. data/spec/unit/resource/powershell_script_spec.rb +2 -2
  89. data/spec/unit/resource_spec.rb +86 -0
  90. metadata +29 -16
  91. /data/spec/functional/assets/chocolatey_feed/{test-A.1.0.nupkg → test-A.1.0.0.nupkg} +0 -0
  92. /data/spec/functional/assets/chocolatey_feed/{test-A.1.5.nupkg → test-A.1.5.0.nupkg} +0 -0
  93. /data/spec/functional/assets/chocolatey_feed/{test-A.2.0.nupkg → test-A.2.0.0.nupkg} +0 -0
  94. /data/spec/functional/assets/chocolatey_feed/{test-B.1.0.nupkg → test-B.1.0.0.nupkg} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae48a568217d00b159123bf621bdaee21412909ef553f400719f251559c8a4d4
4
- data.tar.gz: 553c80d44e9babb553588b0d01beac0a413aec6b0d21fdbaaf754cc1b3fa0928
3
+ metadata.gz: 1b0abf8303fae83df7a99b7731d5e3eedd3dcb5f533cbc9c784527682b3daaa6
4
+ data.tar.gz: a0fa3f6ee5de4413da2bc2a8e7f41d6d50d320f7c7d2cc080cbda5c9c7bf4604
5
5
  SHA512:
6
- metadata.gz: 3b2df041625cd266ae86c1a899c69493190f09018714cf281486291958268a669d65103555b63f0104345b5e281248d9bf7a2157a2de3632d92f84b4ed72c99c
7
- data.tar.gz: 54b4391ec722faa770d54b7d5c6650285ab3dfdb933eed86938d579fb92b1501ad4bf3848e3f17950316eb5c8d9bc2bc99e044368246940321b10f3ddaaa1e97
6
+ metadata.gz: 961231927046fcc8965d79b9138e76d7659c666d3afaafe99b4cd1816169e888cb0f87cb57bb394c1d5a81e1f7d54f69f2dad7c9f51ff573c868429449aae808
7
+ data.tar.gz: '024394b552768952422587e0c0cd68bb617c51c1baa01ee7a5421952b3d1822ad6a553e0ad549047d53f3339c2483bb54f76f556a5a180d0999bb7fd1553a7ec'
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ gem "ohai", git: "https://github.com/chef/ohai.git", branch: "main"
7
7
  # Nwed to file a bug with rest-client. In the meantime, we can use this until they accept the update.
8
8
  gem "rest-client", git: "https://github.com/chef/rest-client", branch: "jfm/ucrt_update1"
9
9
 
10
- gem "ffi", ">= 1.15.5"
10
+ gem "ffi", "~> 1.15.5"
11
11
  gem "chef-utils", path: File.expand_path("chef-utils", __dir__) if File.exist?(File.expand_path("chef-utils", __dir__))
12
12
  gem "chef-config", path: File.expand_path("chef-config", __dir__) if File.exist?(File.expand_path("chef-config", __dir__))
13
13
 
@@ -24,7 +24,7 @@ gem "cheffish", ">= 17"
24
24
  group(:omnibus_package) do
25
25
  gem "appbundler"
26
26
  gem "rb-readline"
27
- gem "inspec-core-bin", ">= 5" # need to provide the binaries for inspec
27
+ gem "inspec-core-bin", ">= 5", "< 6" # need to provide the binaries for inspec
28
28
  gem "chef-vault"
29
29
  end
30
30
 
@@ -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.0.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.
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}/**/*")
data/chef.gemspec CHANGED
@@ -41,9 +41,9 @@ Gem::Specification.new do |s|
41
41
  s.add_dependency "mixlib-shellout", ">= 3.1.1", "< 4.0"
42
42
  s.add_dependency "mixlib-archive", ">= 0.4", "< 2.0"
43
43
  s.add_dependency "ohai", "~> 18.0"
44
- s.add_dependency "inspec-core", ">= 5"
44
+ s.add_dependency "inspec-core", ">= 5", "< 6"
45
45
 
46
- s.add_dependency "ffi", ">= 1.15.5"
46
+ s.add_dependency "ffi", "~> 1.15.5"
47
47
  s.add_dependency "ffi-yajl", "~> 2.2"
48
48
  s.add_dependency "net-sftp", ">= 2.1.2", "< 5.0" # remote_file resource
49
49
  s.add_dependency "net-ftp" # remote_file resource
@@ -58,7 +58,7 @@ Gem::Specification.new do |s|
58
58
  s.add_dependency "addressable"
59
59
  s.add_dependency "syslog-logger", "~> 1.6"
60
60
  s.add_dependency "uuidtools", ">= 2.1.5", "< 3.0" # osx_profile resource
61
- s.add_dependency "unf_ext", ">= 0.0.8.2" # This is ruby31 compatible ucrt gem version
61
+ s.add_dependency "unf_ext", "~> 0.0.8.2" # older platforms
62
62
  s.add_dependency "corefoundation", "~> 0.3.4" # macos_userdefaults resource
63
63
 
64
64
  s.add_dependency "proxifier2", "~> 1.1"
@@ -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
@@ -238,7 +238,7 @@ class Chef
238
238
  end
239
239
  end
240
240
 
241
- @regexp = Regexp.new("^#{full_regexp_parts.join(Chef::ChefFS::PathUtils.regexp_path_separator)}$")
241
+ @regexp = Regexp.new("^#{full_regexp_parts.join(Chef::ChefFS::PathUtils::REGEXP_PATH_SEPARATOR)}$")
242
242
  @normalized_pattern = Chef::ChefFS::PathUtils.join(*normalized_parts)
243
243
  @normalized_pattern = Chef::ChefFS::PathUtils.join("", @normalized_pattern) if @is_absolute
244
244
  end
@@ -40,13 +40,15 @@ class Chef
40
40
  # path to discover the Chef-FS root path) are handled in accordance to the rules
41
41
  # of the local file-system and OS.
42
42
 
43
+ REGEXP_PATH_SEPARATOR = ChefUtils.windows? ? "[\\/\\\\]" : "/"
44
+
43
45
  def self.join(*parts)
44
46
  return "" if parts.length == 0
45
47
 
46
48
  # Determine if it started with a slash
47
- absolute = parts[0].length == 0 || parts[0].length > 0 && parts[0] =~ /^#{regexp_path_separator}/
49
+ absolute = parts[0].length == 0 || parts[0].length > 0 && parts[0] =~ /^#{REGEXP_PATH_SEPARATOR}/
48
50
  # Remove leading and trailing slashes from each part so that the join will work (and the slash at the end will go away)
49
- parts = parts.map { |part| part.gsub(/^#{regexp_path_separator}+|#{regexp_path_separator}+$/, "") }
51
+ parts = parts.map { |part| part.gsub(/^#{REGEXP_PATH_SEPARATOR}+|#{REGEXP_PATH_SEPARATOR}+$/, "") }
50
52
  # Don't join empty bits
51
53
  result = parts.select { |part| part != "" }.join("/")
52
54
  # Put the / back on
@@ -54,16 +56,12 @@ class Chef
54
56
  end
55
57
 
56
58
  def self.split(path)
57
- path.split(Regexp.new(regexp_path_separator))
58
- end
59
-
60
- def self.regexp_path_separator
61
- ChefUtils.windows? ? "[\\/\\\\]" : "/"
59
+ path.split(Regexp.new(REGEXP_PATH_SEPARATOR))
62
60
  end
63
61
 
64
62
  # Given a server path, determines if it is absolute.
65
63
  def self.is_absolute?(path)
66
- !!(path =~ /^#{regexp_path_separator}/)
64
+ !!(path =~ /^#{REGEXP_PATH_SEPARATOR}/)
67
65
  end
68
66
 
69
67
  # Given a path which may only be partly real (i.e. /x/y/z when only /x exists,
@@ -118,7 +116,7 @@ class Chef
118
116
 
119
117
  if ancestor.length == path.length
120
118
  ""
121
- elsif /#{PathUtils.regexp_path_separator}/.match?(path[ancestor.length, 1])
119
+ elsif /#{PathUtils::REGEXP_PATH_SEPARATOR}/.match?(path[ancestor.length, 1])
122
120
  path[ancestor.length + 1..-1]
123
121
  else
124
122
  nil
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)
@@ -219,14 +219,31 @@ class Chef
219
219
 
220
220
  # remove deleted files in cookbooks that are being used on the node
221
221
  def remove_deleted_files
222
+ cache_file_hash = {}
223
+ @cookbooks_by_name.each_key do |k|
224
+ cache_file_hash[k] = {}
225
+ end
226
+
227
+ # First populate files from cache
222
228
  cache.find(File.join(%w{cookbooks ** {*,.*}})).each do |cache_file|
223
229
  md = cache_file.match(%r{^cookbooks/([^/]+)/([^/]+)/(.*)})
224
230
  next unless md
225
231
 
226
- ( cookbook_name, segment, file ) = md[1..3]
232
+ (cookbook_name, segment, file) = md[1..3]
227
233
  if have_cookbook?(cookbook_name)
234
+ cache_file_hash[cookbook_name][segment] ||= {}
235
+ cache_file_hash[cookbook_name][segment]["#{segment}/#{file}"] = cache_file
236
+ end
237
+ end
238
+ # Determine which files don't match manifest
239
+ @cookbooks_by_name.each_key do |cookbook_name|
240
+ cache_file_hash[cookbook_name].each_key do |segment|
228
241
  manifest_segment = cookbook_segment(cookbook_name, segment)
229
- if manifest_segment.select { |manifest_record| manifest_record["path"] == "#{segment}/#{file}" }.empty?
242
+ manifest_record_paths = manifest_segment.map { |manifest_record| manifest_record["path"] }
243
+ to_be_removed = cache_file_hash[cookbook_name][segment].keys - manifest_record_paths
244
+ to_be_removed.each do |path|
245
+ cache_file = cache_file_hash[cookbook_name][segment][path]
246
+
230
247
  Chef::Log.info("Removing #{cache_file} from the cache; its is no longer in the cookbook manifest.")
231
248
  cache.delete(cache_file)
232
249
  @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
@@ -21,5 +21,9 @@ class Chef
21
21
  # super returns a "Proc" (which seems buggy) so re-wrap it
22
22
  self.class.new(&super) # rubocop:disable Layout/SpaceAroundKeyword
23
23
  end
24
+
25
+ def inspect
26
+ "lazy { (evaluates to) #{call.inspect} }"
27
+ end
24
28
  end
25
29
  end
@@ -324,7 +324,10 @@ class Chef
324
324
  acls += mode_ace(SID.Everyone, (mode & 07))
325
325
  end
326
326
 
327
- acls.nil? ? nil : Chef::ReservedNames::Win32::Security::ACL.create(acls)
327
+ # 'acls.nil?' is true if uninitialized, but false if the initial empty array value.
328
+ # 'acls.empty?' cannot be called if acls is nil but successfully guards against using the empty array value.
329
+ # either case should return nil from this method.
330
+ (acls.nil? || acls.empty?) ? nil : Chef::ReservedNames::Win32::Security::ACL.create(acls)
328
331
  end
329
332
 
330
333
  def target_group
@@ -77,6 +77,8 @@ class Chef
77
77
  @resource.updated
78
78
  rescue Mixlib::ShellOut::ShellCommandFailed
79
79
  nil
80
+ rescue ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed
81
+ nil
80
82
  end
81
83
  end
82
84
 
@@ -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,28 @@ 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
+ [which("brew"), "/opt/homebrew/bin/brew", "/usr/local/bin/brew", "/home/linuxbrew/.linuxbrew/bin/brew"].uniq.select do |x|
65
+ next if x == false
66
+
67
+ ::File.exist?(x) && ::File.executable?(x)
68
+ end.first || nil
69
+ end
70
+ end
71
+
60
72
  private
61
73
 
62
74
  def calculate_owner
63
- default_brew_path = "/usr/local/bin/brew"
64
- if ::File.exist?(default_brew_path)
75
+ brew_path = homebrew_bin_path
76
+ if brew_path
65
77
  # 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
78
  owner = ::File.stat(brew_path).uid
69
79
  else
70
80
  raise Chef::Exceptions::CannotDetermineHomebrewOwner,
71
- 'Could not find the "brew" executable in /usr/local/bin or anywhere on the path.'
81
+ 'Couldn\'t find the "brew" executable anywhere on the path.'
72
82
  end
73
83
 
74
84
  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
+ Chef::Log.debug("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
+ Chef::Log.debug("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
+ Chef::Log.debug("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
+ Chef::Log.debug("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
+ Chef::Log.debug("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
@@ -18,6 +18,7 @@
18
18
 
19
19
  require_relative "common_api"
20
20
  require_relative "mixin/state_tracking"
21
+ require_relative "mixin/state_tracking_array"
21
22
  require_relative "mixin/immutablize_array"
22
23
  require_relative "mixin/immutablize_hash"
23
24
  require_relative "mixin/mashy_array"
@@ -39,11 +40,19 @@ class Chef
39
40
  MUTATOR_METHODS.each do |mutator|
40
41
  define_method(mutator) do |*args, &block|
41
42
  ret = super(*args, &block)
43
+ # TODO: use `send_reset_cache(__path__)` for all mutator methods?
42
44
  send_reset_cache
43
45
  ret
44
46
  end
45
47
  end
46
48
 
49
+ def <<(obj)
50
+ ret = super(obj)
51
+ # NOTE: Expecting __path__ to be top-level attribute only
52
+ send_reset_cache(__path__)
53
+ ret
54
+ end
55
+
47
56
  def delete(key, &block)
48
57
  send_reset_cache(__path__, key)
49
58
  super
@@ -89,7 +98,7 @@ class Chef
89
98
  key
90
99
  end
91
100
 
92
- prepend Chef::Node::Mixin::StateTracking
101
+ prepend Chef::Node::Mixin::StateTrackingArray
93
102
  end
94
103
 
95
104
  # == VividMash
@@ -17,6 +17,7 @@
17
17
 
18
18
  require_relative "common_api"
19
19
  require_relative "mixin/state_tracking"
20
+ require_relative "mixin/state_tracking_array"
20
21
  require_relative "mixin/immutablize_array"
21
22
  require_relative "mixin/immutablize_hash"
22
23
  require_relative "../delayed_evaluator"
@@ -32,13 +33,16 @@ class Chef
32
33
  end
33
34
 
34
35
  def convert_value(value)
36
+ # The order in this case statement is *important*.
37
+ # ImmutableMash and ImmutableArray should be tested first,
38
+ # as this saves unnecessary creation of intermediate objects
35
39
  case value
40
+ when ImmutableMash, ImmutableArray
41
+ value
36
42
  when Hash
37
43
  ImmutableMash.new(value, __root__, __node__, __precedence__)
38
44
  when Array
39
45
  ImmutableArray.new(value, __root__, __node__, __precedence__)
40
- when ImmutableMash, ImmutableArray
41
- value
42
46
  else
43
47
  safe_dup(value).freeze
44
48
  end
@@ -116,7 +120,7 @@ class Chef
116
120
  value
117
121
  end
118
122
 
119
- prepend Chef::Node::Mixin::StateTracking
123
+ prepend Chef::Node::Mixin::StateTrackingArray
120
124
  prepend Chef::Node::Mixin::ImmutablizeArray
121
125
  end
122
126
 
@@ -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)
@@ -0,0 +1,41 @@
1
+ #--
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require_relative "immutablize_array"
19
+ require_relative "state_tracking"
20
+
21
+ class Chef
22
+ class Node
23
+ module Mixin
24
+ module StateTrackingArray
25
+ include ::Chef::Node::Mixin::StateTracking
26
+
27
+ MUTATOR_METHODS = Chef::Node::Mixin::ImmutablizeArray::DISALLOWED_MUTATOR_METHODS
28
+
29
+ # For all of the methods that may mutate an Array, we override them to
30
+ # also track the state and trigger attribute_changed event.
31
+ MUTATOR_METHODS.each do |mutator|
32
+ define_method(mutator) do |*args, &block|
33
+ ret = super(*args, &block)
34
+ send_attribute_changed_event(__path__, self)
35
+ ret
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/chef/node.rb CHANGED
@@ -401,6 +401,13 @@ class Chef
401
401
  normal[:tags]
402
402
  end
403
403
 
404
+ # Add the list of tags to the node.
405
+ #
406
+ # === Parameters
407
+ # tags<Array>:: A list of tags
408
+ #
409
+ # === Returns
410
+ # tags<Array>:: The current list of run_context.node.tags
404
411
  def tag(*args)
405
412
  args.each do |tag|
406
413
  tags.push(tag.to_s) unless tags.include? tag.to_s
@@ -409,6 +416,21 @@ class Chef
409
416
  tags
410
417
  end
411
418
 
419
+ # Removes the list of tags from the node.
420
+ #
421
+ # === Parameters
422
+ # tags<Array>:: A list of tags
423
+ #
424
+ # === Returns
425
+ # tags<Array>:: The current list of run_context.node.tags
426
+ def untag(*args)
427
+ args.each do |tag|
428
+ tags.delete(tag.to_s)
429
+ end
430
+
431
+ tags
432
+ end
433
+
412
434
  # Extracts the run list from +attrs+ and applies it. Returns the remaining attributes
413
435
  def consume_run_list(attrs)
414
436
  attrs = attrs ? attrs.dup : {}
@@ -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
@@ -124,6 +124,11 @@ class Chef
124
124
 
125
125
  private
126
126
 
127
+ # @return [String] package name with or without anchors attached to it.
128
+ def resolve_package(pkg)
129
+ new_resource.anchor_package_regex ? "^#{pkg}$" : pkg
130
+ end
131
+
127
132
  # @return [String] version of apt-get which is installed
128
133
  def apt_version
129
134
  @apt_version ||= shell_out("apt-get --version").stdout.match(/^apt (\S+)/)[1]
@@ -174,10 +179,12 @@ class Chef
174
179
  end
175
180
 
176
181
  def resolve_package_versions(pkg)
182
+ # apt-cache considers package names as regex by default. The anchor_package_regex flag will decide whether to match name exact string or not
183
+ pkg_name = resolve_package(pkg)
177
184
  current_version = nil
178
185
  candidate_version = nil
179
186
  all_versions = []
180
- run_noninteractive("apt-cache", default_release_options, "policy", pkg).stdout.each_line do |line|
187
+ run_noninteractive("apt-cache", default_release_options, "policy", pkg_name).stdout.each_line do |line|
181
188
  case line
182
189
  when /^\s{2}Installed: (.+)$/
183
190
  current_version = ( $1 != "(none)" ) ? $1 : nil
@@ -216,7 +223,9 @@ class Chef
216
223
  end
217
224
 
218
225
  def resolve_virtual_package_name(pkg)
219
- showpkg = run_noninteractive("apt-cache", "showpkg", pkg).stdout
226
+ # apt-cache considers package names as regex by default. The anchor_package_regex flag will decide whether to match name exact string or not
227
+ pkg_name = resolve_package(pkg)
228
+ showpkg = run_noninteractive("apt-cache", "showpkg", pkg_name).stdout
220
229
  partitions = showpkg.rpartition(/Reverse Provides: ?#{$/}/)
221
230
  return nil if partitions[0] == "" && partitions[1] == "" # not found in output
222
231