chef 16.11.7 → 16.15.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -2
- data/Rakefile +11 -0
- data/lib/chef/cookbook/gem_installer.rb +5 -1
- 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/knife/core/windows_bootstrap_context.rb +2 -3
- data/lib/chef/node.rb +20 -19
- data/lib/chef/policy_builder/policyfile.rb +5 -0
- data/lib/chef/provider/file.rb +1 -1
- data/lib/chef/provider/group/dscl.rb +1 -1
- data/lib/chef/provider/mount.rb +7 -2
- data/lib/chef/provider/package/powershell.rb +5 -0
- data/lib/chef/provider/package/rubygems.rb +2 -2
- data/lib/chef/provider/service/macosx.rb +3 -3
- data/lib/chef/provider/template/content.rb +1 -1
- data/lib/chef/resource/chef_client_launchd.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/cron_spec.rb +1 -1
- data/spec/functional/resource/group_spec.rb +5 -1
- data/spec/functional/resource/link_spec.rb +8 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/platform_helpers.rb +4 -0
- data/spec/support/shared/unit/provider/file.rb +14 -0
- data/spec/unit/cookbook_version_spec.rb +52 -0
- data/spec/unit/data_collector_spec.rb +47 -1
- data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +3 -3
- data/spec/unit/policy_builder/policyfile_spec.rb +11 -1
- data/spec/unit/provider/mount/mount_spec.rb +51 -0
- data/spec/unit/provider/package/powershell_spec.rb +74 -12
- data/spec/unit/provider/package/rubygems_spec.rb +3 -3
- data/spec/unit/provider/service/macosx_spec.rb +3 -3
- 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
- data/tasks/rspec.rb +1 -1
- metadata +7 -7
@@ -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)
|
data/spec/spec_helper.rb
CHANGED
@@ -145,6 +145,7 @@ RSpec.configure do |config|
|
|
145
145
|
config.filter_run_excluding macos_only: true unless macos?
|
146
146
|
config.filter_run_excluding macos_1013: true unless macos_1013?
|
147
147
|
config.filter_run_excluding macos_gte_1014: true unless macos_gte_1014?
|
148
|
+
config.filter_run_excluding not_macos_gte_11: true if macos_gte_11?
|
148
149
|
config.filter_run_excluding not_supported_on_aix: true if aix?
|
149
150
|
config.filter_run_excluding not_supported_on_solaris: true if solaris?
|
150
151
|
config.filter_run_excluding not_supported_on_gce: true if gce?
|
@@ -479,12 +479,14 @@ shared_examples_for Chef::Provider::File do
|
|
479
479
|
it "calls #verify on each verification with tempfile path" do
|
480
480
|
provider.new_resource.verify windows? ? "REM" : "true"
|
481
481
|
provider.new_resource.verify windows? ? "REM" : "true"
|
482
|
+
allow(provider).to receive(:contents_changed?).and_return(true)
|
482
483
|
provider.send(:do_validate_content)
|
483
484
|
end
|
484
485
|
|
485
486
|
it "raises an exception if any verification fails" do
|
486
487
|
allow(File).to receive(:directory?).with("C:\\Windows\\system32/cmd.exe").and_return(false)
|
487
488
|
allow(provider).to receive(:tempfile).and_return(tempfile)
|
489
|
+
allow(provider).to receive(:contents_changed?).and_return(true)
|
488
490
|
provider.new_resource.verify windows? ? "cmd.exe c exit 1" : "false"
|
489
491
|
provider.new_resource.verify.each do |v|
|
490
492
|
allow(v).to receive(:verify).and_return(false)
|
@@ -492,9 +494,21 @@ shared_examples_for Chef::Provider::File do
|
|
492
494
|
expect { provider.send(:do_validate_content) }.to raise_error(Chef::Exceptions::ValidationFailed)
|
493
495
|
end
|
494
496
|
|
497
|
+
it "does not run verifications when the contents did not change" do
|
498
|
+
allow(File).to receive(:directory?).with("C:\\Windows\\system32/cmd.exe").and_return(false)
|
499
|
+
allow(provider).to receive(:tempfile).and_return(tempfile)
|
500
|
+
allow(provider).to receive(:contents_changed?).and_return(false)
|
501
|
+
provider.new_resource.verify windows? ? "cmd.exe c exit 1" : "false"
|
502
|
+
provider.new_resource.verify.each do |v|
|
503
|
+
expect(v).not_to receive(:verify)
|
504
|
+
end
|
505
|
+
provider.send(:do_validate_content)
|
506
|
+
end
|
507
|
+
|
495
508
|
it "does not show verification for sensitive resources" do
|
496
509
|
allow(File).to receive(:directory?).with("C:\\Windows\\system32/cmd.exe").and_return(false)
|
497
510
|
allow(provider).to receive(:tempfile).and_return(tempfile)
|
511
|
+
allow(provider).to receive(:contents_changed?).and_return(true)
|
498
512
|
provider.new_resource.sensitive true
|
499
513
|
provider.new_resource.verify windows? ? "cmd.exe c exit 1" : "false"
|
500
514
|
provider.new_resource.verify.each do |v|
|
@@ -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
|
|
@@ -204,19 +204,19 @@ describe Chef::Knife::Core::WindowsBootstrapContext do
|
|
204
204
|
end
|
205
205
|
|
206
206
|
it "returns a chef.io msi url with minimal url parameters" do
|
207
|
-
reference_url = "https://
|
207
|
+
reference_url = "https://omnitruck.chef.io/chef/download?p=windows&channel=stable&v=something"
|
208
208
|
expect(bootstrap_context.msi_url).to eq(reference_url)
|
209
209
|
end
|
210
210
|
|
211
211
|
it "returns a chef.io msi url with provided url parameters substituted" do
|
212
|
-
reference_url = "https://
|
212
|
+
reference_url = "https://omnitruck.chef.io/chef/download?p=windows&pv=machine&m=arch&DownloadContext=ctx&channel=stable&v=something"
|
213
213
|
expect(bootstrap_context.msi_url("machine", "arch", "ctx")).to eq(reference_url)
|
214
214
|
end
|
215
215
|
|
216
216
|
context "when a channel is provided in config" do
|
217
217
|
let(:config) { { channel: "current" } }
|
218
218
|
it "returns a chef.io msi url with the requested channel" do
|
219
|
-
reference_url = "https://
|
219
|
+
reference_url = "https://omnitruck.chef.io/chef/download?p=windows&channel=current&v=something"
|
220
220
|
expect(bootstrap_context.msi_url).to eq(reference_url)
|
221
221
|
end
|
222
222
|
end
|
@@ -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"
|
@@ -506,6 +506,57 @@ describe Chef::Provider::Mount::Mount do
|
|
506
506
|
end
|
507
507
|
end
|
508
508
|
|
509
|
+
context "network mount" do
|
510
|
+
before(:each) do
|
511
|
+
@node = Chef::Node.new
|
512
|
+
@events = Chef::EventDispatch::Dispatcher.new
|
513
|
+
@run_context = Chef::RunContext.new(@node, {}, @events)
|
514
|
+
|
515
|
+
@new_resource = Chef::Resource::Mount.new("/tmp/bar")
|
516
|
+
@new_resource.device "cephserver:6789:/"
|
517
|
+
@new_resource.device_type :device
|
518
|
+
@new_resource.fstype "cephfs"
|
519
|
+
|
520
|
+
@new_resource.supports remount: false
|
521
|
+
|
522
|
+
@provider = Chef::Provider::Mount::Mount.new(@new_resource, @run_context)
|
523
|
+
|
524
|
+
allow(::File).to receive(:exists?).with("cephserver:6789:/").and_return true
|
525
|
+
allow(::File).to receive(:exists?).with("/tmp/bar").and_return true
|
526
|
+
allow(::File).to receive(:realpath).with("cephserver:6789:/").and_return "cephserver:6789:/"
|
527
|
+
allow(::File).to receive(:realpath).with("/tmp/bar").and_return "/tmp/foo"
|
528
|
+
end
|
529
|
+
|
530
|
+
before do
|
531
|
+
@current_resource = Chef::Resource::Mount.new("/tmp/foo")
|
532
|
+
@current_resource.device "cephserver:6789:/"
|
533
|
+
@current_resource.device_type :device
|
534
|
+
@current_resource.fstype "cephfs"
|
535
|
+
|
536
|
+
@provider.current_resource = @current_resource
|
537
|
+
end
|
538
|
+
|
539
|
+
it "should enable network mount if enabled isn't true" do
|
540
|
+
@current_resource.enabled(false)
|
541
|
+
|
542
|
+
@fstab = StringIO.new
|
543
|
+
allow(::File).to receive(:open).with("/etc/fstab", "a").and_yield(@fstab)
|
544
|
+
@provider.enable_fs
|
545
|
+
expect(@fstab.string).to match(%r{^cephserver:6789:/\s+/tmp/bar\s+cephfs\s+defaults\s+0\s+2\s*$})
|
546
|
+
end
|
547
|
+
|
548
|
+
it "should not enable network if enabled is true and resources match" do
|
549
|
+
@current_resource.enabled(true)
|
550
|
+
@current_resource.fstype("cephfs")
|
551
|
+
@current_resource.options(["defaults"])
|
552
|
+
@current_resource.dump(0)
|
553
|
+
@current_resource.pass(2)
|
554
|
+
expect(::File).not_to receive(:open).with("/etc/fstab", "a")
|
555
|
+
|
556
|
+
@provider.enable_fs
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
509
560
|
# the fstab might contain the mount with the device as a device but the resource has a label.
|
510
561
|
# we should not create two mount lines, but update the existing one
|
511
562
|
# not supported on solaris because it can't cope with a UUID device type
|