chef 18.3.0 → 18.4.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/chef.gemspec +2 -2
- data/lib/chef/chef_fs/file_pattern.rb +1 -1
- data/lib/chef/chef_fs/path_utils.rb +7 -9
- data/lib/chef/cookbook/synchronizer.rb +2 -3
- data/lib/chef/delayed_evaluator.rb +4 -0
- data/lib/chef/file_access_control/windows.rb +4 -1
- data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +2 -0
- data/lib/chef/mixin/homebrew_user.rb +6 -3
- data/lib/chef/monkey_patches/net-http.rb +5 -5
- data/lib/chef/node/attribute_collections.rb +2 -1
- data/lib/chef/node/immutable_collections.rb +2 -1
- data/lib/chef/node/mixin/state_tracking_array.rb +41 -0
- data/lib/chef/node.rb +23 -1
- data/lib/chef/provider/package/apt.rb +11 -2
- data/lib/chef/provider/package/chocolatey.rb +228 -24
- data/lib/chef/provider/package/zypper.rb +5 -0
- data/lib/chef/provider/powershell_script.rb +96 -6
- data/lib/chef/provider/service/systemd.rb +23 -8
- data/lib/chef/provider/service/windows.rb +1 -0
- data/lib/chef/provider/service.rb +14 -0
- data/lib/chef/provider/user.rb +5 -1
- data/lib/chef/recipe.rb +3 -11
- data/lib/chef/resource/_rest_resource.rb +1 -1
- data/lib/chef/resource/apt_package.rb +19 -0
- data/lib/chef/resource/apt_repository.rb +2 -1
- data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
- data/lib/chef/resource/chocolatey_installer.rb +207 -0
- data/lib/chef/resource/chocolatey_package.rb +8 -0
- data/lib/chef/resource/homebrew_package.rb +1 -1
- data/lib/chef/resource/locale.rb +5 -2
- data/lib/chef/resource/macos_pkg.rb +111 -0
- data/lib/chef/resource/powershell_script.rb +5 -1
- data/lib/chef/resource/service.rb +3 -0
- data/lib/chef/resource/sudo.rb +37 -2
- data/lib/chef/resource/support/ulimit.erb +40 -0
- data/lib/chef/resource/user_ulimit.rb +38 -0
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/version.rb +1 -1
- data/spec/data/trusted_certs/example.crt +29 -20
- data/spec/data/trusted_certs/example_no_cn.crt +30 -34
- data/spec/functional/resource/chocolatey_package_spec.rb +2 -2
- data/spec/functional/resource/zypper_package_spec.rb +10 -0
- data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +1 -1
- data/spec/unit/delayed_evaluator_spec.rb +35 -0
- data/spec/unit/node_spec.rb +6 -0
- data/spec/unit/provider/package/apt_spec.rb +18 -13
- data/spec/unit/provider/package/chocolatey_spec.rb +40 -12
- data/spec/unit/provider/powershell_script_spec.rb +100 -4
- data/spec/unit/provider/service/systemd_service_spec.rb +1 -0
- data/spec/unit/provider/user/linux_spec.rb +10 -0
- data/spec/unit/resource/chef_client_systemd_timer_spec.rb +1 -1
- data/spec/unit/resource/chocolatey_installer_spec.rb +151 -0
- data/spec/unit/resource/macos_pkg_spec.rb +38 -0
- data/spec/unit/resource/powershell_script_spec.rb +2 -2
- metadata +22 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d054a5d4b494b34b37e06e230641502c973712e05466d2112b3bbd69be500d26
|
4
|
+
data.tar.gz: 8217503105a7dc435ad2928a1760ee6403102bdeba006d3d959f368bef3fa8bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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", "
|
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
|
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] =~ /^#{
|
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(/^#{
|
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(
|
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 =~ /^#{
|
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
|
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"] }
|
244
|
-
to_be_removed = cache_file_hash[cookbook_name][segment].keys
|
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
|
|
@@ -324,7 +324,10 @@ class Chef
|
|
324
324
|
acls += mode_ace(SID.Everyone, (mode & 07))
|
325
325
|
end
|
326
326
|
|
327
|
-
acls.nil?
|
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
|
@@ -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
|
-
|
65
|
-
|
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
|
-
'
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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::
|
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::
|
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(
|
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",
|
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
|
-
|
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
|
|