chef 16.7.61 → 16.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -2
- data/README.md +1 -1
- data/chef.gemspec +2 -1
- data/lib/chef/application/base.rb +1 -1
- data/lib/chef/client.rb +3 -0
- data/lib/chef/compliance/default_attributes.rb +89 -0
- data/lib/chef/compliance/fetcher/automate.rb +69 -0
- data/lib/chef/compliance/fetcher/chef_server.rb +134 -0
- data/lib/chef/compliance/reporter/automate.rb +202 -0
- data/lib/chef/compliance/reporter/chef_server_automate.rb +92 -0
- data/lib/chef/compliance/reporter/compliance_enforcer.rb +20 -0
- data/lib/chef/compliance/reporter/json_file.rb +19 -0
- data/lib/chef/compliance/runner.rb +250 -0
- data/lib/chef/cookbook_manifest.rb +1 -0
- data/lib/chef/encrypted_data_bag_item/assertions.rb +1 -1
- data/lib/chef/exceptions.rb +4 -0
- data/lib/chef/http/ssl_policies.rb +6 -0
- data/lib/chef/knife/bootstrap/train_connector.rb +1 -1
- data/lib/chef/knife/core/ui.rb +4 -1
- data/lib/chef/knife/ssh.rb +1 -1
- data/lib/chef/mixin/powershell_exec.rb +3 -1
- data/lib/chef/platform/query_helpers.rb +4 -4
- data/lib/chef/powershell.rb +2 -0
- data/lib/chef/provider/dsc_resource.rb +12 -24
- data/lib/chef/provider/dsc_script.rb +16 -20
- data/lib/chef/provider/git.rb +5 -5
- data/lib/chef/resource/chef_client_config.rb +1 -1
- data/lib/chef/resource/dsc_script.rb +8 -1
- data/lib/chef/resource/hostname.rb +3 -3
- data/lib/chef/resource/template.rb +2 -2
- data/lib/chef/resource/windows_certificate.rb +7 -1
- data/lib/chef/resource_collection/resource_set.rb +1 -1
- data/lib/chef/util/dsc/configuration_generator.rb +52 -11
- data/lib/chef/util/dsc/lcm_output_parser.rb +3 -4
- data/lib/chef/util/dsc/local_configuration_manager.rb +17 -14
- data/lib/chef/util/dsc/resource_store.rb +5 -11
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api/file.rb +4 -0
- data/spec/functional/resource/dsc_script_spec.rb +3 -6
- data/spec/integration/client/client_spec.rb +2 -1
- data/spec/integration/compliance/compliance_spec.rb +81 -0
- data/spec/integration/recipes/recipe_dsl_spec.rb +1 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/client_spec.rb +1 -0
- data/spec/unit/compliance/fetcher/automate_spec.rb +134 -0
- data/spec/unit/compliance/fetcher/chef_server_spec.rb +93 -0
- data/spec/unit/compliance/reporter/automate_spec.rb +427 -0
- data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +177 -0
- data/spec/unit/compliance/reporter/compliance_enforcer_spec.rb +48 -0
- data/spec/unit/compliance/runner_spec.rb +113 -0
- data/spec/unit/http/ssl_policies_spec.rb +11 -0
- data/spec/unit/knife/core/node_editor_spec.rb +1 -1
- data/spec/unit/mixin/powershell_exec_spec.rb +1 -1
- data/spec/unit/platform/query_helpers_spec.rb +11 -12
- data/spec/unit/provider/dsc_resource_spec.rb +10 -27
- data/spec/unit/provider/dsc_script_spec.rb +1 -1
- data/spec/unit/provider/mount/windows_spec.rb +1 -0
- data/spec/unit/provider/systemd_unit_spec.rb +1 -1
- data/spec/unit/resource/windows_certificate_spec.rb +12 -0
- data/spec/unit/util/dsc/configuration_generator_spec.rb +79 -0
- data/spec/unit/util/dsc/local_configuration_manager_spec.rb +27 -35
- metadata +37 -12
- data/lib/chef/util/powershell/cmdlet.rb +0 -169
- data/lib/chef/util/powershell/cmdlet_result.rb +0 -61
- data/spec/functional/util/powershell/cmdlet_spec.rb +0 -111
- data/spec/unit/util/powershell/cmdlet_spec.rb +0 -106
@@ -16,25 +16,27 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require_relative "
|
19
|
+
require_relative "../../mixin/powershell_exec"
|
20
20
|
require_relative "lcm_output_parser"
|
21
21
|
|
22
22
|
class Chef::Util::DSC
|
23
23
|
class LocalConfigurationManager
|
24
|
+
include Chef::Mixin::PowershellExec
|
25
|
+
|
24
26
|
def initialize(node, configuration_path)
|
25
27
|
@node = node
|
26
28
|
@configuration_path = configuration_path
|
27
29
|
clear_execution_time
|
28
30
|
end
|
29
31
|
|
30
|
-
def test_configuration(configuration_document
|
31
|
-
status = run_configuration_cmdlet(configuration_document, false
|
32
|
-
log_dsc_exception(status.
|
33
|
-
configuration_update_required?(status.
|
32
|
+
def test_configuration(configuration_document)
|
33
|
+
status = run_configuration_cmdlet(configuration_document, false)
|
34
|
+
log_dsc_exception(status.errors.join("\n")) if status.error?
|
35
|
+
configuration_update_required?(status.result)
|
34
36
|
end
|
35
37
|
|
36
|
-
def set_configuration(configuration_document
|
37
|
-
run_configuration_cmdlet(configuration_document, true
|
38
|
+
def set_configuration(configuration_document)
|
39
|
+
run_configuration_cmdlet(configuration_document, true)
|
38
40
|
end
|
39
41
|
|
40
42
|
def last_operation_execution_time_seconds
|
@@ -45,7 +47,7 @@ class Chef::Util::DSC
|
|
45
47
|
|
46
48
|
private
|
47
49
|
|
48
|
-
def run_configuration_cmdlet(configuration_document, apply_configuration
|
50
|
+
def run_configuration_cmdlet(configuration_document, apply_configuration)
|
49
51
|
Chef::Log.trace("DSC: Calling DSC Local Config Manager to #{apply_configuration ? "set" : "test"} configuration document.")
|
50
52
|
|
51
53
|
start_operation_timing
|
@@ -53,11 +55,12 @@ class Chef::Util::DSC
|
|
53
55
|
|
54
56
|
begin
|
55
57
|
save_configuration_document(configuration_document)
|
56
|
-
|
58
|
+
cmd = lcm_command(apply_configuration)
|
59
|
+
Chef::Log.trace("DSC: Calling DSC Local Config Manager with:\n#{cmd}")
|
60
|
+
|
61
|
+
status = powershell_exec(cmd)
|
57
62
|
if apply_configuration
|
58
|
-
status
|
59
|
-
else
|
60
|
-
status = cmdlet.run({}, shellout_flags)
|
63
|
+
status.error!
|
61
64
|
end
|
62
65
|
ensure
|
63
66
|
end_operation_timing
|
@@ -77,7 +80,7 @@ class Chef::Util::DSC
|
|
77
80
|
ps4_base_command
|
78
81
|
else
|
79
82
|
if ps_version_gte_5?
|
80
|
-
"#{common_command_prefix} Test-DscConfiguration -path #{@configuration_path} | format-list"
|
83
|
+
"#{common_command_prefix} Test-DscConfiguration -path #{@configuration_path} | format-list | Out-String"
|
81
84
|
else
|
82
85
|
ps4_base_command + " -whatif; if (! $?) { exit 1 }"
|
83
86
|
end
|
@@ -100,7 +103,7 @@ class Chef::Util::DSC
|
|
100
103
|
end
|
101
104
|
|
102
105
|
def whatif_not_supported?(dsc_exception_output)
|
103
|
-
!! (dsc_exception_output.gsub(/[\
|
106
|
+
!! (dsc_exception_output.gsub(/[\n]+/, "").gsub(/\s+/, " ") =~ /A parameter cannot be found that matches parameter name 'Whatif'/i)
|
104
107
|
end
|
105
108
|
|
106
109
|
def dsc_module_import_failure?(command_output)
|
@@ -16,14 +16,14 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require_relative "
|
20
|
-
require_relative "../powershell/cmdlet_result"
|
19
|
+
require_relative "../../mixin/powershell_exec"
|
21
20
|
require_relative "../../exceptions"
|
22
21
|
|
23
22
|
class Chef
|
24
23
|
class Util
|
25
24
|
class DSC
|
26
25
|
class ResourceStore
|
26
|
+
include Chef::Mixin::PowershellExec
|
27
27
|
|
28
28
|
def self.instance
|
29
29
|
@@instance ||= ResourceStore.new.tap do |store|
|
@@ -83,19 +83,13 @@ class Chef
|
|
83
83
|
|
84
84
|
# Returns a list of dsc resources
|
85
85
|
def query_resources
|
86
|
-
|
87
|
-
:object)
|
88
|
-
result = cmdlet.run
|
89
|
-
result.return_value
|
86
|
+
powershell_exec("get-dscresource").result
|
90
87
|
end
|
91
88
|
|
92
89
|
# Returns a list of dsc resources matching the provided name
|
93
90
|
def query_resource(resource_name)
|
94
|
-
|
95
|
-
|
96
|
-
result = cmdlet.run
|
97
|
-
ret_val = result.return_value
|
98
|
-
if ret_val.nil?
|
91
|
+
ret_val = powershell_exec("get-dscresource #{resource_name}").result
|
92
|
+
if ret_val.empty?
|
99
93
|
[]
|
100
94
|
elsif ret_val.is_a? Array
|
101
95
|
ret_val
|
data/lib/chef/version.rb
CHANGED
data/lib/chef/win32/api/file.rb
CHANGED
@@ -316,6 +316,7 @@ typedef struct _REPARSE_DATA_BUFFER {
|
|
316
316
|
string_pointer.read_wstring(self[:PrintNameLength] / 2)
|
317
317
|
end
|
318
318
|
end
|
319
|
+
|
319
320
|
class REPARSE_DATA_BUFFER_MOUNT_POINT < FFI::Struct
|
320
321
|
layout :SubstituteNameOffset, :ushort,
|
321
322
|
:SubstituteNameLength, :ushort,
|
@@ -333,14 +334,17 @@ typedef struct _REPARSE_DATA_BUFFER {
|
|
333
334
|
string_pointer.read_wstring(self[:PrintNameLength] / 2)
|
334
335
|
end
|
335
336
|
end
|
337
|
+
|
336
338
|
class REPARSE_DATA_BUFFER_GENERIC < FFI::Struct
|
337
339
|
layout :DataBuffer, :uchar
|
338
340
|
end
|
341
|
+
|
339
342
|
class REPARSE_DATA_BUFFER_UNION < FFI::Union
|
340
343
|
layout :SymbolicLinkReparseBuffer, REPARSE_DATA_BUFFER_SYMBOLIC_LINK,
|
341
344
|
:MountPointReparseBuffer, REPARSE_DATA_BUFFER_MOUNT_POINT,
|
342
345
|
:GenericReparseBuffer, REPARSE_DATA_BUFFER_GENERIC
|
343
346
|
end
|
347
|
+
|
344
348
|
class REPARSE_DATA_BUFFER < FFI::Struct
|
345
349
|
layout :ReparseTag, :uint32,
|
346
350
|
:ReparseDataLength, :ushort,
|
@@ -21,7 +21,7 @@ require "chef/mixin/powershell_exec"
|
|
21
21
|
require "chef/mixin/windows_architecture_helper"
|
22
22
|
require "support/shared/integration/integration_helper"
|
23
23
|
|
24
|
-
describe Chef::Resource::DscScript, :windows_powershell_dsc_only do
|
24
|
+
describe Chef::Resource::DscScript, :windows_powershell_dsc_only, :ruby64_only do
|
25
25
|
include Chef::Mixin::WindowsArchitectureHelper
|
26
26
|
include Chef::Mixin::PowershellExec
|
27
27
|
before(:all) do
|
@@ -261,12 +261,9 @@ describe Chef::Resource::DscScript, :windows_powershell_dsc_only do
|
|
261
261
|
|
262
262
|
it "should raise an exception if the cwd is etc" do
|
263
263
|
dsc_test_resource.cwd(dsc_environment_fail_etc_directory)
|
264
|
-
expect {
|
265
|
-
begin
|
264
|
+
expect {
|
266
265
|
dsc_test_resource.run_action(:run)
|
267
|
-
|
268
|
-
expect(e.message).to match(exception_message_signature)
|
269
|
-
end
|
266
|
+
}.to raise_error(Chef::PowerShell::CommandFailed, /#{exception_message_signature}/)
|
270
267
|
end
|
271
268
|
end
|
272
269
|
end
|
@@ -97,7 +97,8 @@ describe "chef-client" do
|
|
97
97
|
before { file ".chef/knife.rb", "xxx.xxx" }
|
98
98
|
|
99
99
|
it "should load .chef/knife.rb when -z is specified" do
|
100
|
-
|
100
|
+
# On Solaris shell_out will invoke /bin/sh which doesn't understand how to correctly update ENV['PWD']
|
101
|
+
result = shell_out("#{chef_client} -z -o 'x::default'", cwd: path_to(""), env: { "PWD" => nil })
|
101
102
|
# FATAL: Configuration error NoMethodError: undefined method `xxx' for nil:NilClass
|
102
103
|
expect(result.stdout).to include("xxx")
|
103
104
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require "support/shared/integration/integration_helper"
|
4
|
+
require "chef/mixin/shell_out"
|
5
|
+
require "chef-utils/dist"
|
6
|
+
|
7
|
+
describe "chef-client with audit mode" do
|
8
|
+
|
9
|
+
include IntegrationSupport
|
10
|
+
include Chef::Mixin::ShellOut
|
11
|
+
|
12
|
+
let(:chef_dir) { File.join(__dir__, "..", "..", "..", "bin") }
|
13
|
+
|
14
|
+
# Invoke `chef-client` as `ruby PATH/TO/chef-client`. This ensures the
|
15
|
+
# following constraints are satisfied:
|
16
|
+
# * Windows: windows can only run batch scripts as bare executables. Rubygems
|
17
|
+
# creates batch wrappers for installed gems, but we don't have batch wrappers
|
18
|
+
# in the source tree.
|
19
|
+
# * Other `chef-client` in PATH: A common case is running the tests on a
|
20
|
+
# machine that has omnibus chef installed. In that case we need to ensure
|
21
|
+
# we're running `chef-client` from the source tree and not the external one.
|
22
|
+
# cf. CHEF-4914
|
23
|
+
let(:chef_client) { "bundle exec #{ChefUtils::Dist::Infra::CLIENT} --minimal-ohai" }
|
24
|
+
|
25
|
+
when_the_repository "has a custom profile" do
|
26
|
+
let(:report_file) { path_to("report_file.json") }
|
27
|
+
|
28
|
+
before do
|
29
|
+
directory "profiles/my-profile" do
|
30
|
+
file "inspec.yml", <<~FILE
|
31
|
+
---
|
32
|
+
name: my-profile
|
33
|
+
FILE
|
34
|
+
|
35
|
+
directory "controls" do
|
36
|
+
file "my_control.rb", <<~FILE
|
37
|
+
control "my control" do
|
38
|
+
describe Dir.home do
|
39
|
+
it { should be_kind_of String }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
FILE
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
file "attributes.json", <<~FILE
|
47
|
+
{
|
48
|
+
"audit": {
|
49
|
+
"json_file": {
|
50
|
+
"location": "#{report_file}"
|
51
|
+
},
|
52
|
+
"profiles": {
|
53
|
+
"my-profile": {
|
54
|
+
"path": "#{path_to("profiles/my-profile")}"
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
FILE
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should complete with success" do
|
63
|
+
result = shell_out!("#{chef_client} --local-mode --json-attributes #{path_to("attributes.json")}", cwd: chef_dir)
|
64
|
+
result.error!
|
65
|
+
|
66
|
+
inspec_report = JSON.parse(File.read(report_file))
|
67
|
+
expect(inspec_report["profiles"].length).to eq(1)
|
68
|
+
|
69
|
+
profile = inspec_report["profiles"].first
|
70
|
+
expect(profile["name"]).to eq("my-profile")
|
71
|
+
expect(profile["controls"].length).to eq(1)
|
72
|
+
|
73
|
+
control = profile["controls"].first
|
74
|
+
expect(control["id"]).to eq("my control")
|
75
|
+
expect(control["results"].length).to eq(1)
|
76
|
+
|
77
|
+
result = control["results"].first
|
78
|
+
expect(result["status"]).to eq("passed")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/unit/client_spec.rb
CHANGED
@@ -129,6 +129,7 @@ shared_context "a client run" do
|
|
129
129
|
expect(client.events).to receive(:register).with(instance_of(Chef::DataCollector::Reporter))
|
130
130
|
expect(client.events).to receive(:register).with(instance_of(Chef::ResourceReporter))
|
131
131
|
expect(client.events).to receive(:register).with(instance_of(Chef::ActionCollection))
|
132
|
+
expect(client.events).to receive(:register).with(instance_of(Chef::Compliance::Runner))
|
132
133
|
end
|
133
134
|
|
134
135
|
def stub_for_node_load
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "chef/compliance/fetcher/automate"
|
3
|
+
|
4
|
+
describe Chef::Compliance::Fetcher::Automate do
|
5
|
+
describe ".resolve" do
|
6
|
+
before do
|
7
|
+
Chef::Config[:data_collector] = {
|
8
|
+
server_url: "https://automate.test/data_collector",
|
9
|
+
token: token,
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:token) { "fake_token" }
|
14
|
+
|
15
|
+
context "when target is a string" do
|
16
|
+
it "should resolve a compliance URL" do
|
17
|
+
res = Chef::Compliance::Fetcher::Automate.resolve("compliance://namespace/profile_name")
|
18
|
+
|
19
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::Automate)
|
20
|
+
expected = "https://automate.test/compliance/profiles/namespace/profile_name/tar"
|
21
|
+
expect(res.target).to eq(expected)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "raises an exception with no data collector token" do
|
25
|
+
Chef::Config[:data_collector].delete(:token)
|
26
|
+
|
27
|
+
expect {
|
28
|
+
Chef::Compliance::Fetcher::Automate.resolve("compliance://namespace/profile_name")
|
29
|
+
}.to raise_error(/No data-collector token set/)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "includes the data collector token" do
|
33
|
+
expect(Chef::Compliance::Fetcher::Automate).to receive(:new).with(
|
34
|
+
"https://automate.test/compliance/profiles/namespace/profile_name/tar",
|
35
|
+
hash_including("token" => token)
|
36
|
+
).and_call_original
|
37
|
+
|
38
|
+
res = Chef::Compliance::Fetcher::Automate.resolve("compliance://namespace/profile_name")
|
39
|
+
|
40
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::Automate)
|
41
|
+
expected = "https://automate.test/compliance/profiles/namespace/profile_name/tar"
|
42
|
+
expect(res.target).to eq(expected)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns nil with a non-compliance URL" do
|
46
|
+
res = Chef::Compliance::Fetcher::Automate.resolve("http://github.com/chef-cookbooks/audit")
|
47
|
+
|
48
|
+
expect(res).to eq(nil)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when target is a hash" do
|
53
|
+
it "should resolve a target with a version" do
|
54
|
+
res = Chef::Compliance::Fetcher::Automate.resolve(
|
55
|
+
compliance: "namespace/profile_name",
|
56
|
+
version: "1.2.3"
|
57
|
+
)
|
58
|
+
|
59
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::Automate)
|
60
|
+
expected = "https://automate.test/compliance/profiles/namespace/profile_name/version/1.2.3/tar"
|
61
|
+
expect(res.target).to eq(expected)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should resolve a target without a version" do
|
65
|
+
res = Chef::Compliance::Fetcher::Automate.resolve(
|
66
|
+
compliance: "namespace/profile_name"
|
67
|
+
)
|
68
|
+
|
69
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::Automate)
|
70
|
+
expected = "https://automate.test/compliance/profiles/namespace/profile_name/tar"
|
71
|
+
expect(res.target).to eq(expected)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "uses url key when present" do
|
75
|
+
res = Chef::Compliance::Fetcher::Automate.resolve(
|
76
|
+
compliance: "namespace/profile_name",
|
77
|
+
version: "1.2.3",
|
78
|
+
url: "https://profile.server.test/profiles/profile_name/1.2.3"
|
79
|
+
)
|
80
|
+
|
81
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::Automate)
|
82
|
+
expected = "https://profile.server.test/profiles/profile_name/1.2.3"
|
83
|
+
expect(res.target).to eq(expected)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "does not include token in the config when url key is present" do
|
87
|
+
expect(Chef::Compliance::Fetcher::Automate).to receive(:new).with(
|
88
|
+
"https://profile.server.test/profiles/profile_name/1.2.3",
|
89
|
+
hash_including("token" => nil)
|
90
|
+
).and_call_original
|
91
|
+
|
92
|
+
res = Chef::Compliance::Fetcher::Automate.resolve(
|
93
|
+
compliance: "namespace/profile_name",
|
94
|
+
version: "1.2.3",
|
95
|
+
url: "https://profile.server.test/profiles/profile_name/1.2.3"
|
96
|
+
)
|
97
|
+
|
98
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::Automate)
|
99
|
+
expected = "https://profile.server.test/profiles/profile_name/1.2.3"
|
100
|
+
expect(res.target).to eq(expected)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "raises an exception with no data collector token" do
|
104
|
+
Chef::Config[:data_collector].delete(:token)
|
105
|
+
|
106
|
+
expect {
|
107
|
+
Chef::Compliance::Fetcher::Automate.resolve(compliance: "namespace/profile_name")
|
108
|
+
}.to raise_error(Inspec::FetcherFailure, /No data-collector token set/)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "includes the data collector token" do
|
112
|
+
expect(Chef::Compliance::Fetcher::Automate).to receive(:new).with(
|
113
|
+
"https://automate.test/compliance/profiles/namespace/profile_name/tar",
|
114
|
+
hash_including("token" => token)
|
115
|
+
).and_call_original
|
116
|
+
|
117
|
+
res = Chef::Compliance::Fetcher::Automate.resolve(compliance: "namespace/profile_name")
|
118
|
+
|
119
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::Automate)
|
120
|
+
expected = "https://automate.test/compliance/profiles/namespace/profile_name/tar"
|
121
|
+
expect(res.target).to eq(expected)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "returns nil with a non-profile Hash" do
|
125
|
+
res = Chef::Compliance::Fetcher::Automate.resolve(
|
126
|
+
profile: "namespace/profile_name",
|
127
|
+
version: "1.2.3"
|
128
|
+
)
|
129
|
+
|
130
|
+
expect(res).to eq(nil)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "chef/compliance/fetcher/chef_server"
|
3
|
+
|
4
|
+
describe Chef::Compliance::Fetcher::ChefServer do
|
5
|
+
let(:node) do
|
6
|
+
Chef::Node.new.tap do |n|
|
7
|
+
n.default["audit"] = {}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
allow(Chef).to receive(:node).and_return(node)
|
13
|
+
|
14
|
+
Chef::Config[:chef_server_url] = "http://127.0.0.1:8889/organizations/my_org"
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".resolve" do
|
18
|
+
context "when target is a string" do
|
19
|
+
it "should resolve a compliance URL" do
|
20
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve("compliance://namespace/profile_name")
|
21
|
+
|
22
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::ChefServer)
|
23
|
+
expected = "http://127.0.0.1:8889/organizations/my_org/owners/namespace/compliance/profile_name/tar"
|
24
|
+
expect(res.target).to eq(expected)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should add /compliance URL prefix if needed" do
|
28
|
+
node.default["audit"]["fetcher"] = "chef-server"
|
29
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve("compliance://namespace/profile_name")
|
30
|
+
|
31
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::ChefServer)
|
32
|
+
expected = "http://127.0.0.1:8889/compliance/organizations/my_org/owners/namespace/compliance/profile_name/tar"
|
33
|
+
expect(res.target).to eq(expected)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "includes user in the URL if present" do
|
37
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve("compliance://username@namespace/profile_name")
|
38
|
+
|
39
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::ChefServer)
|
40
|
+
expected = "http://127.0.0.1:8889/organizations/my_org/owners/username@namespace/compliance/profile_name/tar"
|
41
|
+
expect(res.target).to eq(expected)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns nil with a non-compliance URL" do
|
45
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve("http://github.com/chef-cookbooks/audit")
|
46
|
+
|
47
|
+
expect(res).to eq(nil)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when target is a hash" do
|
52
|
+
it "should resolve a target with a version" do
|
53
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve(
|
54
|
+
compliance: "namespace/profile_name",
|
55
|
+
version: "1.2.3"
|
56
|
+
)
|
57
|
+
|
58
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::ChefServer)
|
59
|
+
expected = "http://127.0.0.1:8889/organizations/my_org/owners/namespace/compliance/profile_name/version/1.2.3/tar"
|
60
|
+
expect(res.target).to eq(expected)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should resolve a target without a version" do
|
64
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve(
|
65
|
+
compliance: "namespace/profile_name"
|
66
|
+
)
|
67
|
+
|
68
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::ChefServer)
|
69
|
+
expected = "http://127.0.0.1:8889/organizations/my_org/owners/namespace/compliance/profile_name/tar"
|
70
|
+
expect(res.target).to eq(expected)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "includes user in the URL if present" do
|
74
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve(
|
75
|
+
compliance: "username@namespace/profile_name"
|
76
|
+
)
|
77
|
+
|
78
|
+
expect(res).to be_kind_of(Chef::Compliance::Fetcher::ChefServer)
|
79
|
+
expected = "http://127.0.0.1:8889/organizations/my_org/owners/username@namespace/compliance/profile_name/tar"
|
80
|
+
expect(res.target).to eq(expected)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns nil with a non-profile Hash" do
|
84
|
+
res = Chef::Compliance::Fetcher::ChefServer.resolve(
|
85
|
+
profile: "namespace/profile_name",
|
86
|
+
version: "1.2.3"
|
87
|
+
)
|
88
|
+
|
89
|
+
expect(res).to eq(nil)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|