chef 16.14.1-universal-mingw32 → 16.15.22-universal-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/chef/cookbook_version.rb +26 -4
- data/lib/chef/data_collector/run_end_message.rb +1 -1
- data/lib/chef/deprecated.rb +14 -4
- data/lib/chef/exceptions.rb +3 -0
- data/lib/chef/formatters/error_mapper.rb +2 -2
- data/lib/chef/http.rb +5 -5
- data/lib/chef/node.rb +20 -19
- data/lib/chef/policy_builder/policyfile.rb +5 -0
- data/lib/chef/provider/group/dscl.rb +1 -1
- data/lib/chef/provider/package/powershell.rb +5 -0
- data/lib/chef/provider/template/content.rb +1 -1
- data/lib/chef/resource/homebrew_cask.rb +13 -7
- data/lib/chef/resource/mount.rb +1 -1
- data/lib/chef/resource/rhsm_subscription.rb +5 -5
- data/lib/chef/resource/support/client.erb +6 -0
- data/lib/chef/resource/systemd_unit.rb +1 -1
- data/lib/chef/resource/user_ulimit.rb +1 -0
- data/lib/chef/resource/windows_security_policy.rb +55 -39
- data/lib/chef/resource/windows_uac.rb +3 -1
- data/lib/chef/resource/windows_user_privilege.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api.rb +9 -2
- data/spec/functional/resource/group_spec.rb +5 -1
- data/spec/functional/resource/link_spec.rb +8 -0
- data/spec/unit/cookbook_version_spec.rb +52 -0
- data/spec/unit/data_collector_spec.rb +47 -1
- data/spec/unit/policy_builder/policyfile_spec.rb +11 -1
- data/spec/unit/provider/package/powershell_spec.rb +74 -12
- data/spec/unit/resource/homebrew_cask_spec.rb +29 -11
- data/spec/unit/resource/mount_spec.rb +10 -0
- data/spec/unit/resource/rhsm_subscription_spec.rb +50 -3
- data/spec/unit/resource/systemd_unit_spec.rb +1 -1
- data/spec/unit/resource/user_ulimit_spec.rb +14 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfc8ab5b9b0d6235dcf7650279f07ea9e9401ed1d8d33d909f0829f8e8229a4a
|
4
|
+
data.tar.gz: 952889a6af08c46e9c529b1f153452b5f1bd4684be539d5c9cdef21cf8ff439f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 849ea98620560e7691c7917f371f556dd3d091cb8f95d7362c21026479cc4caaef009c75f153830418a2692ba6a6eb88d6644e3d1cb35e870cdd131d90c4b6d0
|
7
|
+
data.tar.gz: baee8a45aa533a43fcb5f705f9348d15faa0a754dc1a4ea4e41e843586313f09b904cc5b80e50738369d666ec736b8ef48dbb35e7338a3863915d6fac77eef79
|
@@ -138,11 +138,14 @@ class Chef
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def recipe_yml_filenames_by_name
|
141
|
-
@
|
141
|
+
@recipe_yml_filenames_by_name ||= begin
|
142
142
|
name_map = yml_filenames_by_name(files_for("recipes"))
|
143
|
-
root_alias = cookbook_manifest.root_files.find { |record|
|
143
|
+
root_alias = cookbook_manifest.root_files.find { |record|
|
144
|
+
record[:name] == "root_files/recipe.yml" ||
|
145
|
+
record[:name] == "root_files/recipe.yaml"
|
146
|
+
}
|
144
147
|
if root_alias
|
145
|
-
Chef::Log.error("Cookbook #{name} contains both recipe.yml and
|
148
|
+
Chef::Log.error("Cookbook #{name} contains both recipe.yml and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"]
|
146
149
|
name_map["default"] = root_alias[:full_path]
|
147
150
|
end
|
148
151
|
name_map
|
@@ -582,8 +585,27 @@ class Chef
|
|
582
585
|
records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo }
|
583
586
|
end
|
584
587
|
|
588
|
+
# Filters YAML files from the superset of provided files.
|
589
|
+
# Checks for duplicate basenames with differing extensions (eg yaml v yml)
|
590
|
+
# and raises error if any are detected.
|
591
|
+
# This prevents us from arbitrarily the ".yaml" or ".yml" version when both are present,
|
592
|
+
# because we don't know which is correct.
|
593
|
+
# This method runs in O(n^2) where N = number of yml files present. This number should be consistently
|
594
|
+
# low enough that there's no noticeable perf impact.
|
585
595
|
def yml_filenames_by_name(records)
|
586
|
-
records.select { |record| record[:name] =~ /\.
|
596
|
+
yml_files = records.select { |record| record[:name] =~ /\.(y[a]?ml)$/ }
|
597
|
+
result = yml_files.inject({}) do |acc, record|
|
598
|
+
filename = record[:name]
|
599
|
+
base_dup_name = File.join(File.dirname(filename), File.basename(filename, File.extname(filename)))
|
600
|
+
yml_files.each do |other|
|
601
|
+
if other[:name] =~ /#{(File.extname(filename) == ".yml") ? "#{base_dup_name}.yaml" : "#{base_dup_name}.yml"}$/
|
602
|
+
raise Chef::Exceptions::AmbiguousYAMLFile.new("Cookbook #{name}@#{version} contains ambiguous files: #{filename} and #{other[:name]}. Please update the cookbook to remove the incorrect file.")
|
603
|
+
end
|
604
|
+
end
|
605
|
+
acc[File.basename(record[:name], File.extname(record[:name]))] = record[:full_path]
|
606
|
+
acc
|
607
|
+
end
|
608
|
+
result
|
587
609
|
end
|
588
610
|
|
589
611
|
def file_vendor
|
@@ -51,7 +51,7 @@ class Chef
|
|
51
51
|
"id" => run_status&.run_id,
|
52
52
|
"message_version" => "1.1.0",
|
53
53
|
"message_type" => "run_converge",
|
54
|
-
"node" => node || {},
|
54
|
+
"node" => node&.data_for_save || {},
|
55
55
|
"node_name" => node&.name || data_collector.node_name,
|
56
56
|
"organization_name" => organization,
|
57
57
|
"resources" => all_action_records(action_collection),
|
data/lib/chef/deprecated.rb
CHANGED
@@ -79,10 +79,12 @@ class Chef
|
|
79
79
|
return true if location =~ /^(.*?):(\d+):in/ && begin
|
80
80
|
# Don't buffer the whole file in memory, so read it one line at a time.
|
81
81
|
line_no = $2.to_i
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
if File.exist?($1) # some stacktraces come from `eval` and not a file
|
83
|
+
location_file = ::File.open($1)
|
84
|
+
(line_no - 1).times { location_file.readline } # Read all the lines we don't care about.
|
85
|
+
relevant_line = location_file.readline
|
86
|
+
relevant_line.match?(/#.*chef:silence_deprecation($|[^:]|:#{self.class.deprecation_key})/)
|
87
|
+
end
|
86
88
|
end
|
87
89
|
|
88
90
|
false
|
@@ -249,6 +251,14 @@ class Chef
|
|
249
251
|
target 32
|
250
252
|
end
|
251
253
|
|
254
|
+
class PolicyfileCompatMode < Base
|
255
|
+
target 35
|
256
|
+
end
|
257
|
+
|
258
|
+
class AttributeWhitelistConfiguration < Base
|
259
|
+
target 34
|
260
|
+
end
|
261
|
+
|
252
262
|
class Generic < Base
|
253
263
|
def url
|
254
264
|
"https://docs.chef.io/chef_deprecations_client/"
|
data/lib/chef/exceptions.rb
CHANGED
@@ -174,6 +174,9 @@ class Chef
|
|
174
174
|
class CannotDetermineWindowsInstallerType < Package; end
|
175
175
|
class NoWindowsPackageSource < Package; end
|
176
176
|
|
177
|
+
# for example, if both recipes/default.yml, recipes/default.yaml are present
|
178
|
+
class AmbiguousYAMLFile < RuntimeError; end
|
179
|
+
|
177
180
|
# Can not create staging file during file deployment
|
178
181
|
class FileContentStagingError < RuntimeError
|
179
182
|
def initialize(errors)
|
@@ -27,7 +27,7 @@ class Chef
|
|
27
27
|
# Failed to register this client with the server.
|
28
28
|
def self.registration_failed(node_name, exception, config)
|
29
29
|
error_inspector = ErrorInspectors::RegistrationErrorInspector.new(node_name, exception, config)
|
30
|
-
headline = "Chef encountered an error attempting to create the client \"#{node_name}\""
|
30
|
+
headline = "Chef Infra Client encountered an error attempting to create the client \"#{node_name}\""
|
31
31
|
description = ErrorDescription.new(headline)
|
32
32
|
error_inspector.add_explanation(description)
|
33
33
|
description
|
@@ -35,7 +35,7 @@ class Chef
|
|
35
35
|
|
36
36
|
def self.node_load_failed(node_name, exception, config)
|
37
37
|
error_inspector = ErrorInspectors::NodeLoadErrorInspector.new(node_name, exception, config)
|
38
|
-
headline = "Chef encountered an error attempting to load the node data for \"#{node_name}\""
|
38
|
+
headline = "Chef Infra Client encountered an error attempting to load the node data for \"#{node_name}\""
|
39
39
|
description = ErrorDescription.new(headline)
|
40
40
|
error_inspector.add_explanation(description)
|
41
41
|
description
|
data/lib/chef/http.rb
CHANGED
@@ -423,7 +423,7 @@ class Chef
|
|
423
423
|
if response.is_a?(Net::HTTPServerError) && !Chef::Config.local_mode
|
424
424
|
if http_retry_count - http_attempts >= 0
|
425
425
|
sleep_time = 1 + (2**http_attempts) + rand(2**http_attempts)
|
426
|
-
Chef::Log.
|
426
|
+
Chef::Log.warn("Server returned error #{response.code} for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s") # Updated from error to warn
|
427
427
|
sleep(sleep_time)
|
428
428
|
redo
|
429
429
|
end
|
@@ -432,7 +432,7 @@ class Chef
|
|
432
432
|
end
|
433
433
|
rescue SocketError, Errno::ETIMEDOUT, Errno::ECONNRESET => e
|
434
434
|
if http_retry_count - http_attempts >= 0
|
435
|
-
Chef::Log.
|
435
|
+
Chef::Log.warn("Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
|
436
436
|
sleep(http_retry_delay)
|
437
437
|
retry
|
438
438
|
end
|
@@ -440,21 +440,21 @@ class Chef
|
|
440
440
|
raise e
|
441
441
|
rescue Errno::ECONNREFUSED
|
442
442
|
if http_retry_count - http_attempts >= 0
|
443
|
-
Chef::Log.
|
443
|
+
Chef::Log.warn("Connection refused connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
|
444
444
|
sleep(http_retry_delay)
|
445
445
|
retry
|
446
446
|
end
|
447
447
|
raise Errno::ECONNREFUSED, "Connection refused connecting to #{url}, giving up"
|
448
448
|
rescue Timeout::Error
|
449
449
|
if http_retry_count - http_attempts >= 0
|
450
|
-
Chef::Log.
|
450
|
+
Chef::Log.warn("Timeout connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
|
451
451
|
sleep(http_retry_delay)
|
452
452
|
retry
|
453
453
|
end
|
454
454
|
raise Timeout::Error, "Timeout connecting to #{url}, giving up"
|
455
455
|
rescue OpenSSL::SSL::SSLError => e
|
456
456
|
if (http_retry_count - http_attempts >= 0) && !e.message.include?("certificate verify failed")
|
457
|
-
Chef::Log.
|
457
|
+
Chef::Log.warn("SSL Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
|
458
458
|
sleep(http_retry_delay)
|
459
459
|
retry
|
460
460
|
end
|
data/lib/chef/node.rb
CHANGED
@@ -687,6 +687,25 @@ class Chef
|
|
687
687
|
name <=> other.name
|
688
688
|
end
|
689
689
|
|
690
|
+
# Returns hash of node data with attributes based on whitelist/blacklist rules.
|
691
|
+
def data_for_save
|
692
|
+
data = for_json
|
693
|
+
%w{automatic default normal override}.each do |level|
|
694
|
+
allowlist = allowlist_or_whitelist_config(level)
|
695
|
+
unless allowlist.nil? # nil => save everything
|
696
|
+
logger.info("Allowing #{level} node attributes for save.")
|
697
|
+
data[level] = Chef::AttributeAllowlist.filter(data[level], allowlist)
|
698
|
+
end
|
699
|
+
|
700
|
+
blocklist = blocklist_or_blacklist_config(level)
|
701
|
+
unless blocklist.nil? # nil => remove nothing
|
702
|
+
logger.info("Blocking #{level} node attributes for save")
|
703
|
+
data[level] = Chef::AttributeBlocklist.filter(data[level], blocklist)
|
704
|
+
end
|
705
|
+
end
|
706
|
+
data
|
707
|
+
end
|
708
|
+
|
690
709
|
private
|
691
710
|
|
692
711
|
def save_without_policyfile_attrs
|
@@ -712,7 +731,7 @@ class Chef
|
|
712
731
|
# @param [String] level the attribute level
|
713
732
|
def allowlist_or_whitelist_config(level)
|
714
733
|
if Chef::Config["#{level}_attribute_whitelist".to_sym]
|
715
|
-
Chef.deprecated(:
|
734
|
+
Chef.deprecated(:attribute_whitelist_configuration, "Attribute whitelist configurations have been deprecated. Use the allowed_LEVEL_attribute configs instead")
|
716
735
|
Chef::Config["#{level}_attribute_whitelist".to_sym]
|
717
736
|
else
|
718
737
|
Chef::Config["allowed_#{level}_attributes".to_sym]
|
@@ -732,24 +751,6 @@ class Chef
|
|
732
751
|
end
|
733
752
|
end
|
734
753
|
|
735
|
-
def data_for_save
|
736
|
-
data = for_json
|
737
|
-
%w{automatic default normal override}.each do |level|
|
738
|
-
allowlist = allowlist_or_whitelist_config(level)
|
739
|
-
unless allowlist.nil? # nil => save everything
|
740
|
-
logger.info("Allowing #{level} node attributes for save.")
|
741
|
-
data[level] = Chef::AttributeAllowlist.filter(data[level], allowlist)
|
742
|
-
end
|
743
|
-
|
744
|
-
blocklist = blocklist_or_blacklist_config(level)
|
745
|
-
unless blocklist.nil? # nil => remove nothing
|
746
|
-
logger.info("Blocking #{level} node attributes for save")
|
747
|
-
data[level] = Chef::AttributeBlocklist.filter(data[level], blocklist)
|
748
|
-
end
|
749
|
-
end
|
750
|
-
data
|
751
|
-
end
|
752
|
-
|
753
754
|
# Returns a UUID that uniquely identifies this node for reporting reasons.
|
754
755
|
#
|
755
756
|
# The node is read in from disk if it exists, or it's generated if it does
|
@@ -148,6 +148,11 @@ class Chef
|
|
148
148
|
# consume_external_attrs may add items to the run_list. Save the
|
149
149
|
# expanded run_list, which we will pass to the server later to
|
150
150
|
# determine which versions of cookbooks to use.
|
151
|
+
|
152
|
+
unless Chef::Config[:policy_document_native_api]
|
153
|
+
Chef.deprecated(:policyfile_compat_mode, "The chef-server 11 policyfile compat mode is deprecated, please set policy_document_native_api to true in your config")
|
154
|
+
end
|
155
|
+
|
151
156
|
node.reset_defaults_and_overrides
|
152
157
|
|
153
158
|
node.consume_external_attrs(ohai_data, json_attribs)
|
@@ -158,7 +158,7 @@ class Chef
|
|
158
158
|
if new_resource.group_name && (current_resource.group_name != new_resource.group_name)
|
159
159
|
dscl_create_group
|
160
160
|
end
|
161
|
-
if new_resource.gid && (current_resource.gid != new_resource.gid)
|
161
|
+
if new_resource.gid && (current_resource.gid != new_resource.gid.to_s)
|
162
162
|
set_gid
|
163
163
|
end
|
164
164
|
if new_resource.members || new_resource.excluded_members
|
@@ -124,6 +124,11 @@ class Chef
|
|
124
124
|
command.push("-RequiredVersion #{version}") if version
|
125
125
|
command.push("-Source #{new_resource.source}") if new_resource.source && cmdlet_name =~ Regexp.union(/Install-Package/, /Find-Package/)
|
126
126
|
command.push("-SkipPublisherCheck") if new_resource.skip_publisher_check && cmdlet_name !~ /Find-Package/
|
127
|
+
if new_resource.options && cmdlet_name !~ Regexp.union(/Get-Package/, /Find-Package/)
|
128
|
+
new_resource.options.each do |arg|
|
129
|
+
command.push(arg) unless command.include?(arg)
|
130
|
+
end
|
131
|
+
end
|
127
132
|
command.push(").Version")
|
128
133
|
command.join(" ")
|
129
134
|
end
|
@@ -65,7 +65,7 @@ class Chef
|
|
65
65
|
context[:template_finder] = template_finder
|
66
66
|
|
67
67
|
# helper variables
|
68
|
-
context[:cookbook_name] = new_resource.cookbook_name unless context.keys.include?(:
|
68
|
+
context[:cookbook_name] = new_resource.cookbook_name unless context.keys.include?(:cookbook_name)
|
69
69
|
context[:recipe_name] = new_resource.recipe_name unless context.keys.include?(:recipe_name)
|
70
70
|
context[:recipe_line_string] = new_resource.source_line unless context.keys.include?(:recipe_line_string)
|
71
71
|
context[:recipe_path] = new_resource.source_line_file unless context.keys.include?(:recipe_path)
|
@@ -34,7 +34,7 @@ class Chef
|
|
34
34
|
|
35
35
|
property :cask_name, String,
|
36
36
|
description: "An optional property to set the cask name if it differs from the resource block's name.",
|
37
|
-
regex: %r{^[\w
|
37
|
+
regex: %r{^[\w/\-@]+$},
|
38
38
|
validation_message: "The provided Homebrew cask name is not valid. Cask names can contain alphanumeric characters, _, -, or / only!",
|
39
39
|
name_property: true
|
40
40
|
|
@@ -54,9 +54,12 @@ class Chef
|
|
54
54
|
default: lazy { find_homebrew_username }
|
55
55
|
|
56
56
|
action :install do
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
if new_resource.install_cask
|
58
|
+
homebrew_tap "homebrew/cask" do
|
59
|
+
homebrew_path new_resource.homebrew_path
|
60
|
+
owner new_resource.owner
|
61
|
+
end
|
62
|
+
end
|
60
63
|
|
61
64
|
unless casked?
|
62
65
|
converge_by("install cask #{new_resource.cask_name} #{new_resource.options}") do
|
@@ -69,9 +72,12 @@ class Chef
|
|
69
72
|
end
|
70
73
|
|
71
74
|
action :remove do
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
+
if new_resource.install_cask
|
76
|
+
homebrew_tap "homebrew/cask" do
|
77
|
+
homebrew_path new_resource.homebrew_path
|
78
|
+
owner new_resource.owner
|
79
|
+
end
|
80
|
+
end
|
75
81
|
|
76
82
|
if casked?
|
77
83
|
converge_by("uninstall cask #{new_resource.cask_name}") do
|
data/lib/chef/resource/mount.rb
CHANGED
@@ -41,7 +41,7 @@ class Chef
|
|
41
41
|
sensitive: true
|
42
42
|
|
43
43
|
property :mount_point, String, name_property: true,
|
44
|
-
coerce: proc { |arg| arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
|
44
|
+
coerce: proc { |arg| (arg == "/" || arg.match?(":/$")) ? arg : arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
|
45
45
|
description: "The directory (or path) in which the device is to be mounted. Defaults to the name of the resource block if not provided."
|
46
46
|
|
47
47
|
property :device, String, identity: true,
|
@@ -34,11 +34,11 @@ class Chef
|
|
34
34
|
action :attach do
|
35
35
|
description "Attach the node to a subscription pool."
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
unless subscription_attached?(new_resource.pool_id)
|
38
|
+
converge_by("attach subscription pool #{new_resource.pool_id}") do
|
39
|
+
shell_out!("subscription-manager attach --pool=#{new_resource.pool_id}")
|
40
|
+
build_resource(:package, "rhsm_subscription-#{new_resource.pool_id}-flush_cache").run_action(:flush_cache)
|
41
|
+
end
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -22,6 +22,12 @@
|
|
22
22
|
<% next if instance_variable_get(prop).nil? || instance_variable_get(prop).empty? -%>
|
23
23
|
<%=prop.delete_prefix("@") %> <%= instance_variable_get(prop).inspect %>
|
24
24
|
<% end -%>
|
25
|
+
<%# ohai_disabled_plugins and ohai_optional_plugins properties don't match the config value perfectly-%>
|
26
|
+
<% %w(@ohai_disabled_plugins
|
27
|
+
@ohai_optional_plugins).each do |prop| -%>
|
28
|
+
<% next if instance_variable_get(prop).nil? || instance_variable_get(prop).empty? -%>
|
29
|
+
<%=prop.gsub("@ohai_", "ohai.") %> <%= instance_variable_get(prop).inspect %>
|
30
|
+
<% end -%>
|
25
31
|
<%# log_location is special due to STDOUT/STDERR from String -> IO Object -%>
|
26
32
|
<% unless @log_location.nil? %>
|
27
33
|
<% if @log_location.is_a?(String) && %w(STDOUT STDERR).include?(@log_location) -%>
|
@@ -113,7 +113,7 @@ class Chef
|
|
113
113
|
when Hash
|
114
114
|
IniParse.gen do |doc|
|
115
115
|
content.each_pair do |sect, opts|
|
116
|
-
doc.section(sect) do |section|
|
116
|
+
doc.section(sect, { option_sep: "=" }) do |section|
|
117
117
|
opts.each_pair do |opt, val|
|
118
118
|
[val].flatten.each do |v|
|
119
119
|
section.option(opt, v)
|
@@ -17,6 +17,7 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
|
19
19
|
require_relative "../resource"
|
20
|
+
require "tempfile" unless defined?(Tempfile)
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Resource
|
@@ -27,6 +28,7 @@ class Chef
|
|
27
28
|
|
28
29
|
# The valid policy_names options found here
|
29
30
|
# https://github.com/ChrisAWalker/cSecurityOptions under 'AccountSettings'
|
31
|
+
# This needs to be revisited - the list at the link above is non-exhaustive and is missing a couple of items
|
30
32
|
policy_names = %w{LockoutDuration
|
31
33
|
MaximumPasswordAge
|
32
34
|
MinimumPasswordAge
|
@@ -35,6 +37,8 @@ class Chef
|
|
35
37
|
PasswordHistorySize
|
36
38
|
LockoutBadCount
|
37
39
|
ResetLockoutCount
|
40
|
+
AuditPolicyChange
|
41
|
+
LockoutDuration
|
38
42
|
RequireLogonToChangePassword
|
39
43
|
ForceLogoffWhenHourExpire
|
40
44
|
NewAdministratorName
|
@@ -43,7 +47,7 @@ class Chef
|
|
43
47
|
LSAAnonymousNameLookup
|
44
48
|
EnableAdminAccount
|
45
49
|
EnableGuestAccount
|
46
|
-
|
50
|
+
}
|
47
51
|
description "Use the **windows_security_policy** resource to set a security policy on the Microsoft Windows platform."
|
48
52
|
introduced "16.0"
|
49
53
|
|
@@ -83,6 +87,55 @@ class Chef
|
|
83
87
|
description: "Policy value to be set for policy name."
|
84
88
|
|
85
89
|
load_current_value do |desired|
|
90
|
+
current_state = load_security_options
|
91
|
+
|
92
|
+
if desired.secoption == "ResetLockoutCount"
|
93
|
+
if desired.secvalue.to_i > 30
|
94
|
+
raise Chef::Exceptions::ValidationFailed, "The \"ResetLockoutCount\" value cannot be greater than 30 minutes"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
if (desired.secoption == "ResetLockoutCount" || desired.secoption == "LockoutDuration") && current_state["LockoutBadCount"] == "0"
|
98
|
+
raise Chef::Exceptions::ValidationFailed, "#{desired.secoption} cannot be set unless the \"LockoutBadCount\" security policy has been set to a non-zero value"
|
99
|
+
end
|
100
|
+
|
101
|
+
secvalue current_state[desired.secoption.to_s]
|
102
|
+
end
|
103
|
+
|
104
|
+
action :set do
|
105
|
+
converge_if_changed :secvalue do
|
106
|
+
security_option = new_resource.secoption
|
107
|
+
security_value = new_resource.secvalue
|
108
|
+
|
109
|
+
file = Tempfile.new(["#{security_option}", ".inf"])
|
110
|
+
case security_option
|
111
|
+
when "LockoutBadCount"
|
112
|
+
cmd = "net accounts /LockoutThreshold:#{security_value}"
|
113
|
+
when "ResetLockoutCount"
|
114
|
+
cmd = "net accounts /LockoutWindow:#{security_value}"
|
115
|
+
when "LockoutDuration"
|
116
|
+
cmd = "net accounts /LockoutDuration:#{security_value}"
|
117
|
+
when "NewAdministratorName", "NewGuestName"
|
118
|
+
policy_line = "#{security_option} = \"#{security_value}\""
|
119
|
+
file.write("[Unicode]\r\nUnicode=yes\r\n[System Access]\r\n#{policy_line}\r\n[Version]\r\nsignature=\"$CHICAGO$\"\r\nRevision=1\r\n")
|
120
|
+
file.close
|
121
|
+
file_path = file.path.gsub("/", '\\')
|
122
|
+
cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg #{file_path} /areas SECURITYPOLICY"
|
123
|
+
else
|
124
|
+
policy_line = "#{security_option} = #{security_value}"
|
125
|
+
file.write("[Unicode]\r\nUnicode=yes\r\n[System Access]\r\n#{policy_line}\r\n[Version]\r\nsignature=\"$CHICAGO$\"\r\nRevision=1\r\n")
|
126
|
+
file.close
|
127
|
+
file_path = file.path.gsub("/", '\\')
|
128
|
+
cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg #{file_path} /areas SECURITYPOLICY"
|
129
|
+
end
|
130
|
+
shell_out!(cmd)
|
131
|
+
file.unlink
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
# Loads powershell to get current state on security options
|
138
|
+
def load_security_options
|
86
139
|
powershell_code = <<-CODE
|
87
140
|
C:\\Windows\\System32\\secedit /export /cfg $env:TEMP\\secopts_export.inf | Out-Null
|
88
141
|
# cspell:disable-next-line
|
@@ -108,44 +161,7 @@ class Chef
|
|
108
161
|
LockoutBadCount = $security_options_hash.LockoutBadCount
|
109
162
|
})
|
110
163
|
CODE
|
111
|
-
|
112
|
-
current_value_does_not_exist! if output.result.empty?
|
113
|
-
state = output.result
|
114
|
-
|
115
|
-
if desired.secoption == "ResetLockoutCount" || desired.secoption == "LockoutDuration"
|
116
|
-
if state["LockoutBadCount"] == "0"
|
117
|
-
raise Chef::Exceptions::ValidationFailed.new "#{desired.secoption} cannot be set unless the \"LockoutBadCount\" security policy has been set to a non-zero value"
|
118
|
-
else
|
119
|
-
secvalue state[desired.secoption.to_s]
|
120
|
-
end
|
121
|
-
else
|
122
|
-
secvalue state[desired.secoption.to_s]
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
action :set do
|
127
|
-
converge_if_changed :secvalue do
|
128
|
-
security_option = new_resource.secoption
|
129
|
-
security_value = new_resource.secvalue
|
130
|
-
|
131
|
-
cmd = <<-EOH
|
132
|
-
$security_option = "#{security_option}"
|
133
|
-
C:\\Windows\\System32\\secedit /export /cfg $env:TEMP\\#{security_option}_Export.inf
|
134
|
-
if ( ($security_option -match "NewGuestName") -Or ($security_option -match "NewAdministratorName") )
|
135
|
-
{
|
136
|
-
$#{security_option}_Remediation = (Get-Content $env:TEMP\\#{security_option}_Export.inf) | Foreach-Object { $_ -replace '#{security_option}\\s*=\\s*\\"\\w*\\"', '#{security_option} = "#{security_value}"' } | Set-Content $env:TEMP\\#{security_option}_Export.inf
|
137
|
-
C:\\Windows\\System32\\secedit /configure /db $env:windir\\security\\new.sdb /cfg $env:TEMP\\#{security_option}_Export.inf /areas SECURITYPOLICY
|
138
|
-
}
|
139
|
-
else
|
140
|
-
{
|
141
|
-
$#{security_option}_Remediation = (Get-Content $env:TEMP\\#{security_option}_Export.inf) | Foreach-Object { $_ -replace "#{security_option}\\s*=\\s*\\d*", "#{security_option} = #{security_value}" } | Set-Content $env:TEMP\\#{security_option}_Export.inf
|
142
|
-
C:\\Windows\\System32\\secedit /configure /db $env:windir\\security\\new.sdb /cfg $env:TEMP\\#{security_option}_Export.inf /areas SECURITYPOLICY
|
143
|
-
}
|
144
|
-
Remove-Item $env:TEMP\\#{security_option}_Export.inf -force
|
145
|
-
EOH
|
146
|
-
|
147
|
-
powershell_exec!(cmd)
|
148
|
-
end
|
164
|
+
powershell_exec(powershell_code).result
|
149
165
|
end
|
150
166
|
end
|
151
167
|
end
|
@@ -106,7 +106,9 @@ class Chef
|
|
106
106
|
#
|
107
107
|
# @return [Integer]
|
108
108
|
def consent_behavior_users_symbol_to_reg(sym)
|
109
|
-
|
109
|
+
# Since 2 isn't a valid value for ConsentPromptBehaviorUser, assign the value at index as nil.
|
110
|
+
# https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/user-account-control-group-policy-and-registry-key-settings#registry-key-settings
|
111
|
+
[:auto_deny, :secure_prompt_for_creds, nil, :prompt_for_creds].index(sym)
|
110
112
|
end
|
111
113
|
end
|
112
114
|
end
|
@@ -139,7 +139,7 @@ class Chef
|
|
139
139
|
coerce: proc { |v| Array(v) },
|
140
140
|
callbacks: {
|
141
141
|
"Privilege property restricted to the following values: #{PRIVILEGE_OPTS}" => lambda { |n| (n - PRIVILEGE_OPTS).empty? },
|
142
|
-
}
|
142
|
+
}, identity: true
|
143
143
|
|
144
144
|
load_current_value do |new_resource|
|
145
145
|
if new_resource.principal && (new_resource.action.include?(:add) || new_resource.action.include?(:remove))
|
data/lib/chef/version.rb
CHANGED
data/lib/chef/win32/api.rb
CHANGED
@@ -43,6 +43,8 @@ class Chef
|
|
43
43
|
|
44
44
|
host.ffi_convention :stdcall
|
45
45
|
|
46
|
+
win64 = ENV["PROCESSOR_ARCHITECTURE"] == "AMD64" || ENV["PROCESSOR_ARCHITEW6432"] == "AMD64"
|
47
|
+
|
46
48
|
# Windows-specific type defs (ms-help://MS.MSDNQTR.v90.en/winprog/winprog/windows_data_types.htm):
|
47
49
|
host.typedef :ushort, :ATOM # Atom ~= Symbol: Atom table stores strings and corresponding identifiers. Application
|
48
50
|
# places a string in an atom table and receives a 16-bit integer, called an atom, that
|
@@ -120,10 +122,15 @@ class Chef
|
|
120
122
|
host.typedef :int32, :LONG32 # 32-bit signed integer. The range is -2,147,483,648 through +...647 decimal.
|
121
123
|
host.typedef :int64, :LONG64 # 64-bit signed integer. The range is –9,223,372,036,854,775,808 through +...807
|
122
124
|
host.typedef :int64, :LONGLONG # 64-bit signed integer. The range is –9,223,372,036,854,775,808 through +...807
|
123
|
-
host.typedef :long, :LONG_PTR # Signed long type for pointer precision. Use when casting a pointer to a long to
|
124
125
|
# perform pointer arithmetic. BaseTsd.h:
|
125
126
|
# if defined(_WIN64) host.typedef __int64 LONG_PTR; #else host.typedef long LONG_PTR;
|
126
|
-
|
127
|
+
if win64
|
128
|
+
host.typedef :int64, :LONG_PTR # Signed long type for pointer precision. Use when casting a pointer to a long to
|
129
|
+
host.typedef :int64, :LPARAM # Message parameter. WinDef.h as follows: #host.typedef LONG_PTR LPARAM;
|
130
|
+
else
|
131
|
+
host.typedef :long, :LONG_PTR # Signed long type for pointer precision. Use when casting a pointer to a long to
|
132
|
+
host.typedef :long, :LPARAM # Message parameter. WinDef.h as follows: #host.typedef LONG_PTR LPARAM;
|
133
|
+
end
|
127
134
|
host.typedef :pointer, :LPBOOL # Pointer to a BOOL. WinDef.h as follows: #host.typedef BOOL far *LPBOOL;
|
128
135
|
host.typedef :pointer, :LPBYTE # Pointer to a BYTE. WinDef.h as follows: #host.typedef BYTE far *LPBYTE;
|
129
136
|
host.typedef :pointer, :LPCOLORREF # Pointer to a COLORREF value. WinDef.h as follows: #host.typedef DWORD *LPCOLORREF;
|
@@ -44,6 +44,10 @@ describe Chef::Resource::Group, :requires_root_or_running_windows do
|
|
44
44
|
members.shift # Get rid of GroupMembership: string
|
45
45
|
members.include?(user)
|
46
46
|
else
|
47
|
+
# TODO For some reason our temporary AIX 7.2 system does not correctly report group membership immediately after changes have been made.
|
48
|
+
# Adding a 2 second delay for this platform is enough to get correct results.
|
49
|
+
# We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
|
50
|
+
sleep 2 if aix? && (ohai[:platform_version] == "7.2")
|
47
51
|
Etc.getgrnam(group_name).mem.include?(user)
|
48
52
|
end
|
49
53
|
end
|
@@ -181,7 +185,7 @@ describe Chef::Resource::Group, :requires_root_or_running_windows do
|
|
181
185
|
|
182
186
|
describe "when the users exist" do
|
183
187
|
before do
|
184
|
-
high_uid =
|
188
|
+
high_uid = 40000
|
185
189
|
(spec_members).each do |member|
|
186
190
|
remove_user(member)
|
187
191
|
create_user(member, high_uid)
|
@@ -345,9 +345,17 @@ describe Chef::Resource::Link do
|
|
345
345
|
let(:test_user) { "test-link-user" }
|
346
346
|
before do
|
347
347
|
user(test_user).run_action(:create)
|
348
|
+
# TODO For some reason our temporary AIX 7.2 system does not correctly report user existence immediately after changes have been made.
|
349
|
+
# Adding a 2 second delay for this platform is enough to get correct results.
|
350
|
+
# We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
|
351
|
+
sleep 2 if aix? && (ohai[:platform_version] == "7.2")
|
348
352
|
end
|
349
353
|
after do
|
350
354
|
user(test_user).run_action(:remove)
|
355
|
+
# TODO For some reason our temporary AIX 7.2 system does not correctly report user existence immediately after changes have been made.
|
356
|
+
# Adding a 2 second delay for this platform is enough to get correct results.
|
357
|
+
# We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
|
358
|
+
sleep 2 if aix? && (ohai[:platform_version] == "7.2")
|
351
359
|
end
|
352
360
|
before(:each) do
|
353
361
|
resource.owner(test_user)
|
@@ -41,7 +41,59 @@ describe Chef::CookbookVersion do
|
|
41
41
|
it "has empty metadata" do
|
42
42
|
expect(cookbook_version.metadata).to eq(Chef::Cookbook::Metadata.new)
|
43
43
|
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#recipe_yml_filenames_by_name" do
|
47
|
+
let(:cookbook_version) { Chef::CookbookVersion.new("mycb", "/tmp/mycb") }
|
48
|
+
|
49
|
+
def files_for_recipe(extension)
|
50
|
+
[
|
51
|
+
{ name: "recipes/default.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipes/default.#{extension}" },
|
52
|
+
{ name: "recipes/other.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipes/other.#{extension}" },
|
53
|
+
]
|
54
|
+
end
|
55
|
+
context "and YAML files present include both a recipes/default.yml and a recipes/default.yaml" do
|
56
|
+
before(:each) do
|
57
|
+
allow(cookbook_version).to receive(:files_for).with("recipes").and_return(
|
58
|
+
[
|
59
|
+
{ name: "recipes/default.yml", full_path: "/home/user/repo/cookbooks/test/recipes/default.yml" },
|
60
|
+
{ name: "recipes/default.yaml", full_path: "/home/user/repo/cookbooks/test/recipes/default.yaml" },
|
61
|
+
]
|
62
|
+
)
|
63
|
+
end
|
64
|
+
it "because both are valid and we can't pick, it raises an error that contains the info needed to fix the problem" do
|
65
|
+
expect { cookbook_version.recipe_yml_filenames_by_name }
|
66
|
+
.to raise_error(Chef::Exceptions::AmbiguousYAMLFile, /.*default.yml.*default.yaml.*update the cookbook to remove/)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
%w{yml yaml}.each do |extension|
|
71
|
+
|
72
|
+
context "and YAML files are present including a recipes/default.#{extension}" do
|
73
|
+
before(:each) do
|
74
|
+
allow(cookbook_version).to receive(:files_for).with("recipes").and_return(files_for_recipe(extension))
|
75
|
+
end
|
76
|
+
|
77
|
+
context "and manifest does not include a root_files/recipe.#{extension}" do
|
78
|
+
it "returns all YAML recipes with a correct default of default.#{extension}" do
|
79
|
+
expect(cookbook_version.recipe_yml_filenames_by_name).to eq({ "default" => "/home/user/repo/cookbooks/test/recipes/default.#{extension}",
|
80
|
+
"other" => "/home/user/repo/cookbooks/test/recipes/other.#{extension}" })
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "and manifest also includes a root_files/recipe.#{extension}" do
|
85
|
+
let(:root_files) { [{ name: "root_files/recipe.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipe.#{extension}" } ] }
|
86
|
+
before(:each) do
|
87
|
+
allow(cookbook_version.cookbook_manifest).to receive(:root_files).and_return(root_files)
|
88
|
+
end
|
44
89
|
|
90
|
+
it "returns all YAML recipes with a correct default of recipe.#{extension}" do
|
91
|
+
expect(cookbook_version.recipe_yml_filenames_by_name).to eq({ "default" => "/home/user/repo/cookbooks/test/recipe.#{extension}",
|
92
|
+
"other" => "/home/user/repo/cookbooks/test/recipes/other.#{extension}" })
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
45
97
|
end
|
46
98
|
|
47
99
|
describe "with a cookbook directory named tatft" do
|
@@ -142,11 +142,17 @@ describe Chef::DataCollector do
|
|
142
142
|
def expect_converge_message(keys)
|
143
143
|
keys["message_type"] = "run_converge"
|
144
144
|
keys["message_version"] = "1.1.0"
|
145
|
+
# if (keys.key?("node") && !keys["node"].empty?)
|
146
|
+
# expect(rest_client).to receive(:post) do |_a, hash, _b|
|
147
|
+
# require 'pry'; binding.pry
|
148
|
+
# end
|
149
|
+
# else
|
145
150
|
expect(rest_client).to receive(:post).with(
|
146
151
|
nil,
|
147
152
|
hash_including(keys),
|
148
153
|
{ "Content-Type" => "application/json" }
|
149
154
|
)
|
155
|
+
# end
|
150
156
|
end
|
151
157
|
|
152
158
|
def resource_has_diff(new_resource, status)
|
@@ -202,7 +208,7 @@ describe Chef::DataCollector do
|
|
202
208
|
end
|
203
209
|
|
204
210
|
it "has a node" do
|
205
|
-
expect_converge_message("node" => expected_node)
|
211
|
+
expect_converge_message("node" => expected_node.is_a?(Chef::Node) ? expected_node.data_for_save : expected_node)
|
206
212
|
send_run_failed_or_completed_event
|
207
213
|
end
|
208
214
|
|
@@ -808,6 +814,46 @@ describe Chef::DataCollector do
|
|
808
814
|
it_behaves_like "sends a converge message"
|
809
815
|
end
|
810
816
|
|
817
|
+
context "when node attributes are block-listed" do
|
818
|
+
let(:status) { "success" }
|
819
|
+
before do
|
820
|
+
Chef::Config[:blocked_default_attributes] = [
|
821
|
+
%w{secret key_to_the_kingdom},
|
822
|
+
]
|
823
|
+
node.default = {
|
824
|
+
"secret" => { "key_to_the_kingdom" => "under the flower pot to the left of the drawbridge" },
|
825
|
+
"publicinfo" => { "num_flower_pots" => 18 },
|
826
|
+
}
|
827
|
+
end
|
828
|
+
|
829
|
+
it "payload should exclude blocked attributes" do
|
830
|
+
expect(rest_client).to receive(:post) do |_addr, hash, _headers|
|
831
|
+
expect(hash["node"]["default"]).to eq({ "secret" => {}, "publicinfo" => { "num_flower_pots" => 18 } })
|
832
|
+
end
|
833
|
+
send_run_failed_or_completed_event
|
834
|
+
end
|
835
|
+
end
|
836
|
+
|
837
|
+
context "when node attributes are allow-listed" do
|
838
|
+
let(:status) { "success" }
|
839
|
+
before do
|
840
|
+
Chef::Config[:allowed_default_attributes] = [
|
841
|
+
%w{public entrance},
|
842
|
+
]
|
843
|
+
node.default = {
|
844
|
+
"public" => { "entrance" => "is the drawbridge" },
|
845
|
+
"secret" => { "entrance" => "is the tunnel" },
|
846
|
+
}
|
847
|
+
end
|
848
|
+
|
849
|
+
it "payload should include only allowed attributes" do
|
850
|
+
expect(rest_client).to receive(:post) do |_addr, hash, _headers|
|
851
|
+
expect(hash["node"]["default"]).to eq({ "public" => { "entrance" => "is the drawbridge" } })
|
852
|
+
end
|
853
|
+
send_run_failed_or_completed_event
|
854
|
+
end
|
855
|
+
end
|
856
|
+
|
811
857
|
end
|
812
858
|
end
|
813
859
|
|
@@ -206,7 +206,7 @@ describe Chef::PolicyBuilder::Policyfile do
|
|
206
206
|
end
|
207
207
|
|
208
208
|
before do
|
209
|
-
Chef::Config[:policy_document_native_api] =
|
209
|
+
Chef::Config[:policy_document_native_api] = true
|
210
210
|
Chef::Config[:deployment_group] = "example-policy-stage"
|
211
211
|
allow(policy_builder).to receive(:api_service).and_return(api_service)
|
212
212
|
end
|
@@ -214,6 +214,8 @@ describe Chef::PolicyBuilder::Policyfile do
|
|
214
214
|
describe "when using compatibility mode (policy_document_native_api == false)" do
|
215
215
|
|
216
216
|
before do
|
217
|
+
Chef::Config[:policy_document_native_api] = false
|
218
|
+
Chef::Config[:treat_deprecation_warnings_as_errors] = false
|
217
219
|
Chef::Config[:deployment_group] = "example-policy-stage"
|
218
220
|
end
|
219
221
|
|
@@ -339,6 +341,10 @@ describe Chef::PolicyBuilder::Policyfile do
|
|
339
341
|
end
|
340
342
|
|
341
343
|
describe "validating the Policyfile.lock" do
|
344
|
+
before do
|
345
|
+
Chef::Config[:policy_group] = "policy-stage"
|
346
|
+
Chef::Config[:policy_name] = "example"
|
347
|
+
end
|
342
348
|
|
343
349
|
it "errors if the policyfile json contains any non-recipe items" do
|
344
350
|
parsed_policyfile_json["run_list"] = ["role[foo]"]
|
@@ -806,6 +812,10 @@ describe Chef::PolicyBuilder::Policyfile do
|
|
806
812
|
context "when using compatibility mode (policy_document_native_api == false)" do
|
807
813
|
let(:cookbook1_url) { "cookbooks/example1/#{example1_xyz_version}" }
|
808
814
|
let(:cookbook2_url) { "cookbooks/example2/#{example2_xyz_version}" }
|
815
|
+
before do
|
816
|
+
Chef::Config[:policy_document_native_api] = false
|
817
|
+
Chef::Config[:treat_deprecation_warnings_as_errors] = false
|
818
|
+
end
|
809
819
|
|
810
820
|
context "when the cookbooks don't exist on the server" do
|
811
821
|
include_examples "fetching cookbooks when they don't exist"
|
@@ -105,6 +105,10 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
|
|
105
105
|
let(:generated_install_cmdlet) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version" }
|
106
106
|
let(:generated_install_cmdlet_with_version) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 ).Version" }
|
107
107
|
let(:generated_install_cmdlet_with_source) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -Source MyGallery ).Version" }
|
108
|
+
let(:generated_install_cmdlet_with_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -AcceptLicense -Verbose ).Version" }
|
109
|
+
let(:generated_install_cmdlet_with_version_and_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 -AcceptLicense -Verbose ).Version" }
|
110
|
+
let(:generated_install_cmdlet_with_source_and_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -Source MyGallery -AcceptLicense -Verbose ).Version" }
|
111
|
+
let(:generated_install_cmdlet_with_source_and_version_and_options) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 -Source MyGallery -AcceptLicense -Verbose ).Version" }
|
108
112
|
let(:generated_install_cmdlet_with_source_and_version) { "#{tls_set_command} ( Install-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 -Source MyGallery ).Version" }
|
109
113
|
let(:generated_uninstall_cmdlet) { "#{tls_set_command} ( Uninstall-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version" }
|
110
114
|
let(:generated_uninstall_cmdlet_with_version) { "#{tls_set_command} ( Uninstall-Package xNetworking -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 1.0.0.0 ).Version" }
|
@@ -204,11 +208,11 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
|
|
204
208
|
end
|
205
209
|
|
206
210
|
context "when source is nil" do
|
207
|
-
it "
|
211
|
+
it "builds get commands correctly" do
|
208
212
|
expect(provider.build_powershell_package_command("Get-Package xNetworking")).to eql(generated_get_cmdlet)
|
209
213
|
end
|
210
214
|
|
211
|
-
it "
|
215
|
+
it "builds get commands correctly when a version is passed" do
|
212
216
|
expect(provider.build_powershell_package_command("Get-Package xNetworking", "1.0.0.0")).to eql(generated_get_cmdlet_with_version)
|
213
217
|
end
|
214
218
|
|
@@ -220,30 +224,45 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
|
|
220
224
|
expect(provider.build_powershell_package_command("Find-Package xNetworking", "1.0.0.0")).to eql(generated_find_cmdlet_with_version)
|
221
225
|
end
|
222
226
|
|
223
|
-
it "
|
227
|
+
it "builds install commands correctly" do
|
224
228
|
expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet)
|
225
229
|
end
|
226
230
|
|
227
|
-
it "
|
231
|
+
it "builds install commands correctly when a version is passed" do
|
228
232
|
expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_version)
|
229
233
|
end
|
230
234
|
|
231
|
-
it "
|
235
|
+
it "builds install commands correctly when options are passed" do
|
236
|
+
new_resource.options("-AcceptLicense -Verbose")
|
237
|
+
expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_options)
|
238
|
+
end
|
239
|
+
|
240
|
+
it "builds install commands correctly when duplicate options are passed" do
|
241
|
+
new_resource.options("-WarningAction SilentlyContinue")
|
242
|
+
expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "builds install commands correctly when a version and options are passed" do
|
246
|
+
new_resource.options("-AcceptLicense -Verbose")
|
247
|
+
expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_version_and_options)
|
248
|
+
end
|
249
|
+
|
250
|
+
it "builds install commands correctly" do
|
232
251
|
expect(provider.build_powershell_package_command("Uninstall-Package xNetworking")).to eql(generated_uninstall_cmdlet)
|
233
252
|
end
|
234
253
|
|
235
|
-
it "
|
254
|
+
it "builds install commands correctly when a version is passed" do
|
236
255
|
expect(provider.build_powershell_package_command("Uninstall-Package xNetworking", "1.0.0.0")).to eql(generated_uninstall_cmdlet_with_version)
|
237
256
|
end
|
238
257
|
end
|
239
258
|
|
240
259
|
context "when source is set" do
|
241
|
-
it "
|
260
|
+
it "builds get commands correctly" do
|
242
261
|
new_resource.source("MyGallery")
|
243
262
|
expect(provider.build_powershell_package_command("Get-Package xNetworking")).to eql(generated_get_cmdlet)
|
244
263
|
end
|
245
264
|
|
246
|
-
it "
|
265
|
+
it "builds get commands correctly when a version is passed" do
|
247
266
|
new_resource.source("MyGallery")
|
248
267
|
expect(provider.build_powershell_package_command("Get-Package xNetworking", "1.0.0.0")).to eql(generated_get_cmdlet_with_version)
|
249
268
|
end
|
@@ -258,22 +277,40 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
|
|
258
277
|
expect(provider.build_powershell_package_command("Find-Package xNetworking", "1.0.0.0")).to eql(generated_find_cmdlet_with_source_and_version)
|
259
278
|
end
|
260
279
|
|
261
|
-
it "
|
280
|
+
it "builds install commands correctly" do
|
262
281
|
new_resource.source("MyGallery")
|
263
282
|
expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_source)
|
264
283
|
end
|
265
284
|
|
266
|
-
it "
|
285
|
+
it "builds install commands correctly when a version is passed" do
|
267
286
|
new_resource.source("MyGallery")
|
268
287
|
expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_source_and_version)
|
269
288
|
end
|
270
289
|
|
271
|
-
it "
|
290
|
+
it "builds install commands correctly when options are passed" do
|
291
|
+
new_resource.source("MyGallery")
|
292
|
+
new_resource.options("-AcceptLicense -Verbose")
|
293
|
+
expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_source_and_options)
|
294
|
+
end
|
295
|
+
|
296
|
+
it "builds install commands correctly when duplicate options are passed" do
|
297
|
+
new_resource.source("MyGallery")
|
298
|
+
new_resource.options("-Force -ForceBootstrap")
|
299
|
+
expect(provider.build_powershell_package_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_source)
|
300
|
+
end
|
301
|
+
|
302
|
+
it "builds install commands correctly when a version and options are passed" do
|
303
|
+
new_resource.source("MyGallery")
|
304
|
+
new_resource.options("-AcceptLicense -Verbose")
|
305
|
+
expect(provider.build_powershell_package_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_source_and_version_and_options)
|
306
|
+
end
|
307
|
+
|
308
|
+
it "builds install commands correctly" do
|
272
309
|
new_resource.source("MyGallery")
|
273
310
|
expect(provider.build_powershell_package_command("Uninstall-Package xNetworking")).to eql(generated_uninstall_cmdlet)
|
274
311
|
end
|
275
312
|
|
276
|
-
it "
|
313
|
+
it "builds install commands correctly when a version is passed" do
|
277
314
|
new_resource.source("MyGallery")
|
278
315
|
expect(provider.build_powershell_package_command("Uninstall-Package xNetworking", "1.0.0.0")).to eql(generated_uninstall_cmdlet_with_version)
|
279
316
|
end
|
@@ -434,6 +471,19 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
|
|
434
471
|
provider.run_action(:install)
|
435
472
|
expect(new_resource).to be_updated_by_last_action
|
436
473
|
end
|
474
|
+
|
475
|
+
it "should install a package using provided options" do
|
476
|
+
provider.load_current_resource
|
477
|
+
new_resource.package_name(["xCertificate"])
|
478
|
+
new_resource.version(nil)
|
479
|
+
new_resource.options(%w{-AcceptLicense -Verbose})
|
480
|
+
allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Find-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_available)
|
481
|
+
allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Get-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_not_available)
|
482
|
+
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
|
483
|
+
expect(provider).to receive(:powershell_out).with("#{tls_set_command} ( Install-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue -RequiredVersion 2.1.0.0 -AcceptLicense -Verbose ).Version", { timeout: new_resource.timeout })
|
484
|
+
provider.run_action(:install)
|
485
|
+
expect(new_resource).to be_updated_by_last_action
|
486
|
+
end
|
437
487
|
end
|
438
488
|
|
439
489
|
describe "#action_remove" do
|
@@ -499,5 +549,17 @@ describe Chef::Provider::Package::Powershell, :windows_only, :windows_gte_10 do
|
|
499
549
|
provider.run_action(:remove)
|
500
550
|
expect(new_resource).to be_updated_by_last_action
|
501
551
|
end
|
552
|
+
|
553
|
+
it "should remove a package using provided options" do
|
554
|
+
new_resource.package_name(["xCertificate"])
|
555
|
+
new_resource.options(%w{-AllVersions})
|
556
|
+
allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Find-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_available)
|
557
|
+
allow(provider).to receive(:powershell_out).with("#{tls_set_command} ( Get-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_available)
|
558
|
+
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
|
559
|
+
provider.load_current_resource
|
560
|
+
expect(provider).to receive(:powershell_out).with("#{tls_set_command} ( Uninstall-Package 'xCertificate' -Force -ForceBootstrap -WarningAction SilentlyContinue -AllVersions ).Version", { timeout: new_resource.timeout }).and_return(package_xcertificate_not_available)
|
561
|
+
provider.run_action(:remove)
|
562
|
+
expect(new_resource).to be_updated_by_last_action
|
563
|
+
end
|
502
564
|
end
|
503
565
|
end
|
@@ -19,22 +19,40 @@ require "spec_helper"
|
|
19
19
|
|
20
20
|
describe Chef::Resource::HomebrewCask do
|
21
21
|
|
22
|
-
|
22
|
+
context "name with under bar" do
|
23
|
+
let(:resource) { Chef::Resource::HomebrewCask.new("fakey_fakerton") }
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
it "has a resource name of :homebrew_cask" do
|
26
|
+
expect(resource.resource_name).to eql(:homebrew_cask)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "the cask_name property is the name_property" do
|
30
|
+
expect(resource.cask_name).to eql("fakey_fakerton")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "sets the default action as :install" do
|
34
|
+
expect(resource.action).to eql([:install])
|
35
|
+
end
|
27
36
|
|
28
|
-
|
29
|
-
|
37
|
+
it "supports :install, :remove actions" do
|
38
|
+
expect { resource.action :install }.not_to raise_error
|
39
|
+
expect { resource.action :remove }.not_to raise_error
|
40
|
+
end
|
30
41
|
end
|
31
42
|
|
32
|
-
|
33
|
-
|
43
|
+
context "name with high fun" do
|
44
|
+
let(:resource) { Chef::Resource::HomebrewCask.new("fakey-fakerton") }
|
45
|
+
|
46
|
+
it "the cask_name property is the name_property" do
|
47
|
+
expect(resource.cask_name).to eql("fakey-fakerton")
|
48
|
+
end
|
34
49
|
end
|
35
50
|
|
36
|
-
|
37
|
-
|
38
|
-
|
51
|
+
context "name with at mark" do
|
52
|
+
let(:resource) { Chef::Resource::HomebrewCask.new("fakey-fakerton@10") }
|
53
|
+
|
54
|
+
it "the cask_name property is the name_property" do
|
55
|
+
expect(resource.cask_name).to eql("fakey-fakerton@10")
|
56
|
+
end
|
39
57
|
end
|
40
58
|
end
|
@@ -59,6 +59,16 @@ describe Chef::Resource::Mount do
|
|
59
59
|
expect(resource.mount_point).to eql("//192.168.11.102/Share/backup")
|
60
60
|
end
|
61
61
|
|
62
|
+
it "does not strip slash when mount_point is root directory" do
|
63
|
+
resource.mount_point "/"
|
64
|
+
expect(resource.mount_point).to eql("/")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "does not strip slash when mount_point is root of network mount" do
|
68
|
+
resource.mount_point "127.0.0.1:/"
|
69
|
+
expect(resource.mount_point).to eql("127.0.0.1:/")
|
70
|
+
end
|
71
|
+
|
62
72
|
it "raises error when mount_point property is not set" do
|
63
73
|
expect { resource.mount_point nil }.to raise_error(Chef::Exceptions::ValidationFailed, "Property mount_point must be one of: String! You passed nil.")
|
64
74
|
end
|
@@ -18,15 +18,24 @@
|
|
18
18
|
require "spec_helper"
|
19
19
|
|
20
20
|
describe Chef::Resource::RhsmSubscription do
|
21
|
-
let(:
|
22
|
-
let(:
|
21
|
+
let(:event_dispatch) { Chef::EventDispatch::Dispatcher.new }
|
22
|
+
let(:node) { Chef::Node.new }
|
23
|
+
let(:run_context) { Chef::RunContext.new(node, {}, event_dispatch) }
|
24
|
+
|
25
|
+
let(:pool_id) { "8a8dd78c766232550226b46e59404aba" }
|
26
|
+
let(:resource) { Chef::Resource::RhsmSubscription.new(pool_id, run_context) }
|
27
|
+
let(:provider) { resource.provider_for_action(Array(resource.action).first) }
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow(resource).to receive(:provider_for_action).with(:attach).and_return(provider)
|
31
|
+
end
|
23
32
|
|
24
33
|
it "has a resource name of :rhsm_subscription" do
|
25
34
|
expect(resource.resource_name).to eql(:rhsm_subscription)
|
26
35
|
end
|
27
36
|
|
28
37
|
it "the pool_id property is the name_property" do
|
29
|
-
expect(resource.pool_id).to eql(
|
38
|
+
expect(resource.pool_id).to eql(pool_id)
|
30
39
|
end
|
31
40
|
|
32
41
|
it "sets the default action as :attach" do
|
@@ -38,6 +47,44 @@ describe Chef::Resource::RhsmSubscription do
|
|
38
47
|
expect { resource.action :remove }.not_to raise_error
|
39
48
|
end
|
40
49
|
|
50
|
+
describe "#action_attach" do
|
51
|
+
let(:yum_package_double) { instance_double("Chef::Resource::YumPackage") }
|
52
|
+
let(:so_double) { instance_double("Mixlib::ShellOut", stdout: "Successfully attached a subscription for: My Subscription", exitstatus: 0, error?: false) }
|
53
|
+
|
54
|
+
before do
|
55
|
+
allow(provider).to receive(:shell_out!).with("subscription-manager attach --pool=#{resource.pool_id}").and_return(so_double)
|
56
|
+
allow(provider).to receive(:build_resource).with(:package, "rhsm_subscription-#{pool_id}-flush_cache").and_return(yum_package_double)
|
57
|
+
allow(yum_package_double).to receive(:run_action).with(:flush_cache)
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when already attached to pool" do
|
61
|
+
before do
|
62
|
+
allow(provider).to receive(:subscription_attached?).with(resource.pool_id).and_return(true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "does not attach to pool" do
|
66
|
+
expect(provider).not_to receive(:shell_out!)
|
67
|
+
resource.run_action(:attach)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when not attached to pool" do
|
72
|
+
before do
|
73
|
+
allow(provider).to receive(:subscription_attached?).with(resource.pool_id).and_return(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "attaches to pool" do
|
77
|
+
expect(provider).to receive(:shell_out!).with("subscription-manager attach --pool=#{resource.pool_id}")
|
78
|
+
resource.run_action(:attach)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "flushes package provider cache" do
|
82
|
+
expect(yum_package_double).to receive(:run_action).with(:flush_cache)
|
83
|
+
resource.run_action(:attach)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
41
88
|
describe "#subscription_attached?" do
|
42
89
|
let(:cmd) { double("cmd") }
|
43
90
|
let(:output) { "Pool ID: pool123" }
|
@@ -20,7 +20,7 @@ require "spec_helper"
|
|
20
20
|
|
21
21
|
describe Chef::Resource::SystemdUnit do
|
22
22
|
let(:resource) { Chef::Resource::SystemdUnit.new("sysstat-collect.timer") }
|
23
|
-
let(:unit_content_string) { "[Unit]\nDescription
|
23
|
+
let(:unit_content_string) { "[Unit]\nDescription=Run system activity accounting tool every 10 minutes\nDocumentation=foo\nDocumentation=bar\n\n[Timer]\nOnCalendar=*:00/10\n\n[Install]\nWantedBy=sysstat.service\n" }
|
24
24
|
let(:unit_content_hash) do
|
25
25
|
{
|
26
26
|
"Unit" => {
|
@@ -17,7 +17,6 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require "spec_helper"
|
20
|
-
|
21
20
|
describe Chef::Resource::UserUlimit do
|
22
21
|
let(:node) { Chef::Node.new }
|
23
22
|
let(:events) { Chef::EventDispatch::Dispatcher.new }
|
@@ -50,4 +49,18 @@ describe Chef::Resource::UserUlimit do
|
|
50
49
|
expect { resource.action :create }.not_to raise_error
|
51
50
|
expect { resource.action :delete }.not_to raise_error
|
52
51
|
end
|
52
|
+
|
53
|
+
describe "sensitive attribute" do
|
54
|
+
context "should be insensitive by default" do
|
55
|
+
it { expect(resource.sensitive).to(be_falsey) }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when set" do
|
59
|
+
before { resource.sensitive(true) }
|
60
|
+
|
61
|
+
it "should be set on the resource" do
|
62
|
+
expect(resource.sensitive).to(be_truthy)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
53
66
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 16.
|
4
|
+
version: 16.15.22
|
5
5
|
platform: universal-mingw32
|
6
6
|
authors:
|
7
7
|
- Adam Jacob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-config
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 16.
|
19
|
+
version: 16.15.22
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 16.
|
26
|
+
version: 16.15.22
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: chef-utils
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 16.
|
33
|
+
version: 16.15.22
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 16.
|
40
|
+
version: 16.15.22
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: train-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|