chef 18.3.0 → 18.4.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/chef.gemspec +2 -2
  4. data/lib/chef/chef_fs/file_pattern.rb +1 -1
  5. data/lib/chef/chef_fs/path_utils.rb +7 -9
  6. data/lib/chef/cookbook/synchronizer.rb +2 -3
  7. data/lib/chef/delayed_evaluator.rb +4 -0
  8. data/lib/chef/file_access_control/windows.rb +4 -1
  9. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +2 -0
  10. data/lib/chef/mixin/homebrew_user.rb +6 -3
  11. data/lib/chef/monkey_patches/net-http.rb +5 -5
  12. data/lib/chef/node/attribute_collections.rb +2 -1
  13. data/lib/chef/node/immutable_collections.rb +2 -1
  14. data/lib/chef/node/mixin/state_tracking_array.rb +41 -0
  15. data/lib/chef/node.rb +23 -1
  16. data/lib/chef/provider/package/apt.rb +11 -2
  17. data/lib/chef/provider/package/chocolatey.rb +228 -24
  18. data/lib/chef/provider/package/zypper.rb +5 -0
  19. data/lib/chef/provider/powershell_script.rb +96 -6
  20. data/lib/chef/provider/service/systemd.rb +23 -8
  21. data/lib/chef/provider/service/windows.rb +1 -0
  22. data/lib/chef/provider/service.rb +14 -0
  23. data/lib/chef/provider/user.rb +5 -1
  24. data/lib/chef/recipe.rb +3 -11
  25. data/lib/chef/resource/_rest_resource.rb +1 -1
  26. data/lib/chef/resource/apt_package.rb +19 -0
  27. data/lib/chef/resource/apt_repository.rb +2 -1
  28. data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
  29. data/lib/chef/resource/chocolatey_installer.rb +207 -0
  30. data/lib/chef/resource/chocolatey_package.rb +8 -0
  31. data/lib/chef/resource/homebrew_package.rb +1 -1
  32. data/lib/chef/resource/locale.rb +5 -2
  33. data/lib/chef/resource/macos_pkg.rb +111 -0
  34. data/lib/chef/resource/powershell_script.rb +5 -1
  35. data/lib/chef/resource/service.rb +3 -0
  36. data/lib/chef/resource/sudo.rb +37 -2
  37. data/lib/chef/resource/support/ulimit.erb +40 -0
  38. data/lib/chef/resource/user_ulimit.rb +38 -0
  39. data/lib/chef/resources.rb +2 -0
  40. data/lib/chef/version.rb +1 -1
  41. data/spec/data/trusted_certs/example.crt +29 -20
  42. data/spec/data/trusted_certs/example_no_cn.crt +30 -34
  43. data/spec/functional/resource/chocolatey_package_spec.rb +2 -2
  44. data/spec/functional/resource/zypper_package_spec.rb +10 -0
  45. data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +1 -1
  46. data/spec/unit/delayed_evaluator_spec.rb +35 -0
  47. data/spec/unit/node_spec.rb +6 -0
  48. data/spec/unit/provider/package/apt_spec.rb +18 -13
  49. data/spec/unit/provider/package/chocolatey_spec.rb +40 -12
  50. data/spec/unit/provider/powershell_script_spec.rb +100 -4
  51. data/spec/unit/provider/service/systemd_service_spec.rb +1 -0
  52. data/spec/unit/provider/user/linux_spec.rb +10 -0
  53. data/spec/unit/resource/chef_client_systemd_timer_spec.rb +1 -1
  54. data/spec/unit/resource/chocolatey_installer_spec.rb +151 -0
  55. data/spec/unit/resource/macos_pkg_spec.rb +38 -0
  56. data/spec/unit/resource/powershell_script_spec.rb +2 -2
  57. metadata +22 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3856e8d0d5224634cad3eb9d43ecf3e87cc504ee881474f7698a14eb90e15088
4
- data.tar.gz: 7830af2c8acab4e76176876a2aaac1363d9a8ff706a78422ec98d6d522772856
3
+ metadata.gz: d054a5d4b494b34b37e06e230641502c973712e05466d2112b3bbd69be500d26
4
+ data.tar.gz: 8217503105a7dc435ad2928a1760ee6403102bdeba006d3d959f368bef3fa8bd
5
5
  SHA512:
6
- metadata.gz: 4503271efa5b5e0713e2753056c32f6c9fb044935802571d8ef3a4024788dd23f9b6ca7da74e1210d1eaedf03b2b44ecc6e7a0e28059078e815b78161ca4e502
7
- data.tar.gz: 150281399db54afc60e2f910b3dd4322b0d6f287f97d57b9c530fea39d705bbc4dd0b89cb43807f642674c0ae0ce20d40964bba5fe757a76d4af71fa6b7dc7d1
6
+ metadata.gz: fca7e74fe02c2070fd34f30a58c5206a56ed35fc11dc378a9d60cad12dd17cc5a3ef3f293f4ca4e218b54edc9b62ce186fb7328883786261995846a696e1e54f
7
+ data.tar.gz: 59dceca64109ceb153dee38a72b1865f0a582c1b48f257d14462c6450ae97a3d52febb946d37b15afba21d5bb9132c32fc1df751a081b977a883add135d1629e
data/Gemfile CHANGED
@@ -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
 
@@ -52,6 +52,7 @@ group(:development, :test) do
52
52
  gem "rake"
53
53
  gem "rspec"
54
54
  gem "webmock"
55
+ gem "crack", "< 0.4.6" # due to https://github.com/jnunemaker/crack/pull/75
55
56
  gem "fauxhai-ng" # for chef-utils gem
56
57
  end
57
58
 
data/chef.gemspec CHANGED
@@ -41,7 +41,7 @@ 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
46
  s.add_dependency "ffi", ">= 1.15.5"
47
47
  s.add_dependency "ffi-yajl", "~> 2.2"
@@ -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"
@@ -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
@@ -18,7 +18,6 @@ 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)
22
21
 
23
22
  class Chef
24
23
 
@@ -240,8 +239,8 @@ class Chef
240
239
  @cookbooks_by_name.each_key do |cookbook_name|
241
240
  cache_file_hash[cookbook_name].each_key do |segment|
242
241
  manifest_segment = cookbook_segment(cookbook_name, segment)
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
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
245
244
  to_be_removed.each do |path|
246
245
  cache_file = cache_file_hash[cookbook_name][segment][path]
247
246
 
@@ -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
 
@@ -61,8 +61,11 @@ class Chef
61
61
  if brew_bin_path && ::File.exist?(brew_bin_path)
62
62
  brew_bin_path
63
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
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
66
69
  end
67
70
  end
68
71
 
@@ -75,7 +78,7 @@ class Chef
75
78
  owner = ::File.stat(brew_path).uid
76
79
  else
77
80
  raise Chef::Exceptions::CannotDetermineHomebrewOwner,
78
- 'Could not find the "brew" executable anywhere on the path.'
81
+ 'Couldn\'t find the "brew" executable anywhere on the path.'
79
82
  end
80
83
 
81
84
  Chef::Log.debug "Found Homebrew owner #{Etc.getpwuid(owner).name}; executing `brew` commands as them"
@@ -23,7 +23,7 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
23
23
  conn_port = port
24
24
  end
25
25
 
26
- puts "opening connection to #{conn_addr}:#{conn_port}..."
26
+ Chef::Log.debug("opening connection to #{conn_addr}:#{conn_port}...")
27
27
  s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
28
28
  begin
29
29
  TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
@@ -33,7 +33,7 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
33
33
  end
34
34
  }
35
35
  s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
36
- puts "opened"
36
+ Chef::Log.debug("opened")
37
37
  if use_ssl?
38
38
  if proxy?
39
39
  plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
@@ -92,7 +92,7 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
92
92
  ssl_host_address = @address
93
93
  end
94
94
 
95
- puts "starting SSL for #{conn_addr}:#{conn_port}..."
95
+ Chef::Log.debug("starting SSL for #{conn_addr}:#{conn_port}...")
96
96
  s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
97
97
  s.sync_close = true
98
98
  s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
@@ -105,7 +105,7 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
105
105
  if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
106
106
  s.post_connection_check(@address)
107
107
  end
108
- puts "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
108
+ Chef::Log.debug("SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}")
109
109
  end
110
110
  @socket = BufferedIO.new(s, read_timeout: @read_timeout,
111
111
  write_timeout: @write_timeout,
@@ -115,7 +115,7 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
115
115
  on_connect
116
116
  rescue => exception
117
117
  if s
118
- puts "Conn close because of connect error #{exception}"
118
+ Chef::Log.debug("Conn close because of connect error #{exception}")
119
119
  s.close
120
120
  end
121
121
  raise
@@ -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"
@@ -97,7 +98,7 @@ class Chef
97
98
  key
98
99
  end
99
100
 
100
- prepend Chef::Node::Mixin::StateTracking
101
+ prepend Chef::Node::Mixin::StateTrackingArray
101
102
  end
102
103
 
103
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"
@@ -119,7 +120,7 @@ class Chef
119
120
  value
120
121
  end
121
122
 
122
- prepend Chef::Node::Mixin::StateTracking
123
+ prepend Chef::Node::Mixin::StateTrackingArray
123
124
  prepend Chef::Node::Mixin::ImmutablizeArray
124
125
  end
125
126
 
@@ -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
@@ -285,7 +285,7 @@ class Chef
285
285
  def loaded_recipe(cookbook, recipe)
286
286
  fully_qualified_recipe = "#{cookbook}::#{recipe}"
287
287
 
288
- automatic_attrs[:recipes] << fully_qualified_recipe unless Array(self[:recipes]).include?(fully_qualified_recipe)
288
+ automatic_attrs[:recipes] << fully_qualified_recipe unless Array(automatic_attrs[:recipes]).include?(fully_qualified_recipe)
289
289
  end
290
290
 
291
291
  # Returns true if this Node expects a given role, false if not.
@@ -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 : {}
@@ -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