chef 16.7.61 → 16.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -2
  3. data/README.md +1 -1
  4. data/chef.gemspec +2 -1
  5. data/lib/chef/application/base.rb +1 -1
  6. data/lib/chef/client.rb +3 -0
  7. data/lib/chef/compliance/default_attributes.rb +89 -0
  8. data/lib/chef/compliance/fetcher/automate.rb +69 -0
  9. data/lib/chef/compliance/fetcher/chef_server.rb +134 -0
  10. data/lib/chef/compliance/reporter/automate.rb +202 -0
  11. data/lib/chef/compliance/reporter/chef_server_automate.rb +92 -0
  12. data/lib/chef/compliance/reporter/compliance_enforcer.rb +20 -0
  13. data/lib/chef/compliance/reporter/json_file.rb +19 -0
  14. data/lib/chef/compliance/runner.rb +250 -0
  15. data/lib/chef/cookbook_manifest.rb +1 -0
  16. data/lib/chef/encrypted_data_bag_item/assertions.rb +1 -1
  17. data/lib/chef/exceptions.rb +4 -0
  18. data/lib/chef/http/ssl_policies.rb +6 -0
  19. data/lib/chef/knife/bootstrap/train_connector.rb +1 -1
  20. data/lib/chef/knife/core/ui.rb +4 -1
  21. data/lib/chef/knife/ssh.rb +1 -1
  22. data/lib/chef/mixin/powershell_exec.rb +3 -1
  23. data/lib/chef/platform/query_helpers.rb +4 -4
  24. data/lib/chef/powershell.rb +2 -0
  25. data/lib/chef/provider/dsc_resource.rb +12 -24
  26. data/lib/chef/provider/dsc_script.rb +16 -20
  27. data/lib/chef/provider/git.rb +5 -5
  28. data/lib/chef/resource/chef_client_config.rb +1 -1
  29. data/lib/chef/resource/dsc_script.rb +8 -1
  30. data/lib/chef/resource/hostname.rb +3 -3
  31. data/lib/chef/resource/template.rb +2 -2
  32. data/lib/chef/resource/windows_certificate.rb +7 -1
  33. data/lib/chef/resource_collection/resource_set.rb +1 -1
  34. data/lib/chef/util/dsc/configuration_generator.rb +52 -11
  35. data/lib/chef/util/dsc/lcm_output_parser.rb +3 -4
  36. data/lib/chef/util/dsc/local_configuration_manager.rb +17 -14
  37. data/lib/chef/util/dsc/resource_store.rb +5 -11
  38. data/lib/chef/version.rb +1 -1
  39. data/lib/chef/win32/api/file.rb +4 -0
  40. data/spec/functional/resource/dsc_script_spec.rb +3 -6
  41. data/spec/integration/client/client_spec.rb +2 -1
  42. data/spec/integration/compliance/compliance_spec.rb +81 -0
  43. data/spec/integration/recipes/recipe_dsl_spec.rb +1 -0
  44. data/spec/spec_helper.rb +1 -1
  45. data/spec/unit/client_spec.rb +1 -0
  46. data/spec/unit/compliance/fetcher/automate_spec.rb +134 -0
  47. data/spec/unit/compliance/fetcher/chef_server_spec.rb +93 -0
  48. data/spec/unit/compliance/reporter/automate_spec.rb +427 -0
  49. data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +177 -0
  50. data/spec/unit/compliance/reporter/compliance_enforcer_spec.rb +48 -0
  51. data/spec/unit/compliance/runner_spec.rb +113 -0
  52. data/spec/unit/http/ssl_policies_spec.rb +11 -0
  53. data/spec/unit/knife/core/node_editor_spec.rb +1 -1
  54. data/spec/unit/mixin/powershell_exec_spec.rb +1 -1
  55. data/spec/unit/platform/query_helpers_spec.rb +11 -12
  56. data/spec/unit/provider/dsc_resource_spec.rb +10 -27
  57. data/spec/unit/provider/dsc_script_spec.rb +1 -1
  58. data/spec/unit/provider/mount/windows_spec.rb +1 -0
  59. data/spec/unit/provider/systemd_unit_spec.rb +1 -1
  60. data/spec/unit/resource/windows_certificate_spec.rb +12 -0
  61. data/spec/unit/util/dsc/configuration_generator_spec.rb +79 -0
  62. data/spec/unit/util/dsc/local_configuration_manager_spec.rb +27 -35
  63. metadata +37 -12
  64. data/lib/chef/util/powershell/cmdlet.rb +0 -169
  65. data/lib/chef/util/powershell/cmdlet_result.rb +0 -61
  66. data/spec/functional/util/powershell/cmdlet_spec.rb +0 -111
  67. data/spec/unit/util/powershell/cmdlet_spec.rb +0 -106
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+
3
+ describe Chef::Compliance::Reporter::AuditEnforcer do
4
+ let(:reporter) { Chef::Compliance::Reporter::AuditEnforcer.new }
5
+
6
+ it "does not raise error for a successful InSpec report" do
7
+ report = {
8
+ "profiles": [
9
+ {
10
+ "controls": [
11
+ { "id": "c1", "results": [{ "status": "passed" }] },
12
+ { "id": "c2", "results": [{ "status": "passed" }] },
13
+ ],
14
+ },
15
+ ],
16
+ }
17
+
18
+ expect(reporter.send_report(report)).to eq(true)
19
+ end
20
+
21
+ it "does not raise error for an InSpec report with no controls" do
22
+ report = { "profiles": [{ "name": "empty" }] }
23
+
24
+ expect(reporter.send_report(report)).to eq(true)
25
+ end
26
+
27
+ it "does not raise error for an InSpec report with controls but no results" do
28
+ report = { "profiles": [{ "controls": [{ "id": "empty" }] }] }
29
+ expect(reporter.send_report(report)).to eq(true)
30
+ end
31
+
32
+ it "raises an error for a failed InSpec report" do
33
+ report = {
34
+ "profiles": [
35
+ {
36
+ "controls": [
37
+ { "id": "c1", "results": [{ "status": "passed" }] },
38
+ { "id": "c2", "results": [{ "status": "failed" }] },
39
+ ],
40
+ },
41
+ ],
42
+ }
43
+
44
+ expect {
45
+ reporter.send_report(report)
46
+ }.to raise_error(Chef::Compliance::Reporter::AuditEnforcer::ControlFailure, "Audit c2 has failed. Aborting chef-client run.")
47
+ end
48
+ end
@@ -0,0 +1,113 @@
1
+ require "spec_helper"
2
+
3
+ describe Chef::Compliance::Runner do
4
+ let(:logger) { double(:logger).as_null_object }
5
+ let(:node) { Chef::Node.new(logger: logger) }
6
+
7
+ let(:runner) do
8
+ described_class.new.tap do |r|
9
+ r.node = node
10
+ r.run_id = "my_run_id"
11
+ r.recipes = []
12
+ end
13
+ end
14
+
15
+ describe "#enabled?" do
16
+ it "is true if the node attributes have audit profiles and the audit cookbook is not present" do
17
+ node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
18
+ runner.recipes = %w{ fancy_cookbook::fanciness tacobell::nachos }
19
+
20
+ expect(runner).to be_enabled
21
+ end
22
+
23
+ it "is false if the node attributes have audit profiles and the audit cookbook is present" do
24
+ node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
25
+ runner.recipes = %w{ audit::default fancy_cookbook::fanciness tacobell::nachos }
26
+
27
+ expect(runner).not_to be_enabled
28
+ end
29
+
30
+ it "is false if the node attributes do not have audit profiles and the audit cookbook is not present" do
31
+ node.normal["audit"]["profiles"] = {}
32
+ runner.recipes = %w{ fancy_cookbook::fanciness tacobell::nachos }
33
+
34
+ expect(runner).not_to be_enabled
35
+ end
36
+
37
+ it "is false if the node attributes do not have audit profiles and the audit cookbook is present" do
38
+ node.normal["audit"]["profiles"] = {}
39
+ runner.recipes = %w{ audit::default fancy_cookbook::fanciness tacobell::nachos }
40
+
41
+ expect(runner).not_to be_enabled
42
+ end
43
+
44
+ it "is false if the node attributes do not have audit attributes and the audit cookbook is not present" do
45
+ runner.recipes = %w{ fancy_cookbook::fanciness tacobell::nachos }
46
+ expect(runner).not_to be_enabled
47
+ end
48
+ end
49
+
50
+ describe "#inspec_profiles" do
51
+ it "returns an empty list with no profiles defined" do
52
+ expect(runner.inspec_profiles).to eq([])
53
+ end
54
+
55
+ it "converts from the attribute format to the format Inspec expects" do
56
+ node.normal["audit"]["profiles"]["linux-baseline"] = {
57
+ 'compliance': "user/linux-baseline",
58
+ 'version': "2.1.0",
59
+ }
60
+
61
+ node.normal["audit"]["profiles"]["ssh"] = {
62
+ 'supermarket': "hardening/ssh-hardening",
63
+ }
64
+
65
+ expected = [
66
+ {
67
+ compliance: "user/linux-baseline",
68
+ name: "linux-baseline",
69
+ version: "2.1.0",
70
+ },
71
+ {
72
+ name: "ssh",
73
+ supermarket: "hardening/ssh-hardening",
74
+ },
75
+ ]
76
+
77
+ expect(runner.inspec_profiles).to eq(expected)
78
+ end
79
+
80
+ it "raises an error when the profiles are in the old audit-cookbook format" do
81
+ node.normal["audit"]["profiles"] = [
82
+ {
83
+ name: "Windows 2019 Baseline",
84
+ compliance: "admin/windows-2019-baseline",
85
+ },
86
+ ]
87
+
88
+ expect { runner.inspec_profiles }.to raise_error(/profiles specified in an unrecognized format, expected a hash of hashes./)
89
+ end
90
+ end
91
+
92
+ describe "#warn_for_deprecated_config_values!" do
93
+ it "logs a warning when deprecated config values are present" do
94
+ node.normal["audit"]["owner"] = "my_org"
95
+ node.normal["audit"]["inspec_version"] = "90210"
96
+
97
+ expect(logger).to receive(:warn).with(/config values 'inspec_version', 'owner' are not supported/)
98
+
99
+ runner.warn_for_deprecated_config_values!
100
+ end
101
+
102
+ it "does not log a warning with no deprecated config values" do
103
+ node.normal["audit"]["profiles"]["linux-baseline"] = {
104
+ 'compliance': "user/linux-baseline",
105
+ 'version': "2.1.0",
106
+ }
107
+
108
+ expect(logger).not_to receive(:warn)
109
+
110
+ runner.warn_for_deprecated_config_values!
111
+ end
112
+ end
113
+ end
@@ -26,6 +26,7 @@ describe "HTTP SSL Policy" do
26
26
  Chef::Config[:ssl_client_key] = nil
27
27
  Chef::Config[:ssl_ca_path] = nil
28
28
  Chef::Config[:ssl_ca_file] = nil
29
+ ENV["SSL_CERT_FILE"] = nil
29
30
  end
30
31
 
31
32
  let(:unconfigured_http_client) { Net::HTTP.new("example.com", 443) }
@@ -71,6 +72,16 @@ describe "HTTP SSL Policy" do
71
72
  Chef::Config[:ssl_ca_file] = CHEF_SPEC_DATA + "/ssl/5e707473.0"
72
73
  expect(http_client.ca_file).to eq(CHEF_SPEC_DATA + "/ssl/5e707473.0")
73
74
  end
75
+
76
+ it "should set the custom CA file if SSL_CERT_FILE environment variable is set" do
77
+ ENV["SSL_CERT_FILE"] = CHEF_SPEC_DATA + "/trusted_certs/intermediate.pem"
78
+ expect(http_client.ca_file).to eq(CHEF_SPEC_DATA + "/trusted_certs/intermediate.pem")
79
+ end
80
+
81
+ it "raises a ConfigurationError if SSL_CERT_FILE environment variable is set to a file that does not exist" do
82
+ ENV["SSL_CERT_FILE"] = "/dev/null/nothing_here"
83
+ expect { http_client }.to raise_error(Chef::Exceptions::ConfigurationError)
84
+ end
74
85
  end
75
86
 
76
87
  describe "when configured with :ssl_verify_mode set to :verify peer" do
@@ -74,7 +74,7 @@ describe Chef::Knife::NodeEditor do
74
74
 
75
75
  expect(ui).to have_received(:warn)
76
76
  .with "Changing the name of a node results in a new node being " +
77
- "created, test_node will not be modified or removed."
77
+ "created, test_node will not be modified or removed."
78
78
 
79
79
  expect(ui).to have_received(:confirm)
80
80
  .with("Proceed with creation of new node")
@@ -66,7 +66,7 @@ describe Chef::Mixin::PowershellExec, :windows_only do
66
66
  execution = object.powershell_exec("this-should-error")
67
67
  expect(execution.errors).to be_a_kind_of(Array)
68
68
  expect(execution.errors[0]).to be_a_kind_of(String)
69
- expect(execution.errors[0]).to include("Runtime exception: this-should-error")
69
+ expect(execution.errors[0]).to include("The term 'this-should-error' is not recognized")
70
70
  end
71
71
 
72
72
  it "raises an error if the interpreter is invalid" do
@@ -41,24 +41,23 @@ end
41
41
 
42
42
  describe "Chef::Platform#dsc_refresh_mode_disabled?" do
43
43
  let(:node) { instance_double("Chef::Node") }
44
- let(:cmdlet) { instance_double("Chef::Util::Powershell::Cmdlet") }
45
- let(:cmdlet_result) { instance_double("Chef::Util::Powershell::CmdletResult") }
44
+ let(:powershell) { instance_double("Chef::PowerShell") }
46
45
 
47
46
  it "returns true when RefreshMode is Disabled" do
48
- expect(Chef::Util::Powershell::Cmdlet).to receive(:new)
49
- .with(node, "Get-DscLocalConfigurationManager", :object)
50
- .and_return(cmdlet)
51
- expect(cmdlet).to receive(:run!).and_return(cmdlet_result)
52
- expect(cmdlet_result).to receive(:return_value).and_return({ "RefreshMode" => "Disabled" })
47
+ expect(Chef::PowerShell).to receive(:new)
48
+ .with("Get-DscLocalConfigurationManager")
49
+ .and_return(powershell)
50
+ expect(powershell).to receive(:error!)
51
+ expect(powershell).to receive(:result).and_return({ "RefreshMode" => "Disabled" })
53
52
  expect(Chef::Platform.dsc_refresh_mode_disabled?(node)).to be true
54
53
  end
55
54
 
56
55
  it "returns false when RefreshMode is not Disabled" do
57
- expect(Chef::Util::Powershell::Cmdlet).to receive(:new)
58
- .with(node, "Get-DscLocalConfigurationManager", :object)
59
- .and_return(cmdlet)
60
- expect(cmdlet).to receive(:run!).and_return(cmdlet_result)
61
- expect(cmdlet_result).to receive(:return_value).and_return({ "RefreshMode" => "LaLaLa" })
56
+ expect(Chef::PowerShell).to receive(:new)
57
+ .with("Get-DscLocalConfigurationManager")
58
+ .and_return(powershell)
59
+ expect(powershell).to receive(:error!)
60
+ expect(powershell).to receive(:result).and_return({ "RefreshMode" => "LaLaLa" })
62
61
  expect(Chef::Platform.dsc_refresh_mode_disabled?(node)).to be false
63
62
  end
64
63
  end
@@ -85,14 +85,13 @@ describe Chef::Provider::DscResource do
85
85
  node.automatic[:languages][:powershell][:version] = "5.0.10018.0"
86
86
  node
87
87
  end
88
- let(:resource_result) { double("CmdletResult", return_value: { "InDesiredState" => true }, stream: "description") }
89
- let(:invoke_dsc_resource) { double("cmdlet", run!: resource_result) }
88
+ let(:resource_result) { double("PowerShell", result: { "InDesiredState" => true }, verbose: ["description"]) }
90
89
  let(:store) { double("ResourceStore", find: resource_records) }
91
90
  let(:resource_records) { [] }
92
91
 
93
92
  before do
94
93
  allow(Chef::Util::DSC::ResourceStore).to receive(:instance).and_return(store)
95
- allow(Chef::Util::Powershell::Cmdlet).to receive(:new).and_return(invoke_dsc_resource)
94
+ allow(provider).to receive(:powershell_exec!).and_return(resource_result)
96
95
  allow(provider).to receive(:dsc_refresh_mode_disabled?).and_return(true)
97
96
  end
98
97
 
@@ -112,9 +111,8 @@ describe Chef::Provider::DscResource do
112
111
  it "flags the resource as reboot required when required" do
113
112
  expect(provider).to receive(:test_resource).and_return(false)
114
113
  expect(provider).to receive(:invoke_resource)
115
- .and_return(double(stdout: "", return_value: nil))
114
+ .and_return(double(result: { "RebootRequired" => true }))
116
115
  expect(provider).to receive(:add_dsc_verbose_log)
117
- expect(provider).to receive(:return_dsc_resource_result).and_return(true)
118
116
  expect(provider).to receive(:create_reboot_resource)
119
117
  provider.run_action(:run)
120
118
  end
@@ -122,9 +120,8 @@ describe Chef::Provider::DscResource do
122
120
  it "does not flag the resource as reboot required when not required" do
123
121
  expect(provider).to receive(:test_resource).and_return(false)
124
122
  expect(provider).to receive(:invoke_resource)
125
- .and_return(double(stdout: "", return_value: nil))
123
+ .and_return(double(stdout: "", result: {}))
126
124
  expect(provider).to receive(:add_dsc_verbose_log)
127
- expect(provider).to receive(:return_dsc_resource_result).and_return(false)
128
125
  expect(provider).to_not receive(:create_reboot_resource)
129
126
  provider.run_action(:run)
130
127
  end
@@ -142,9 +139,7 @@ describe Chef::Provider::DscResource do
142
139
  let(:resource_records) { [{}] }
143
140
 
144
141
  it "returns the default dsc resource module" do
145
- expect(Chef::Util::Powershell::Cmdlet).to receive(:new) do |node, cmdlet, format|
146
- expect(cmdlet).to match(/Module PSDesiredStateConfiguration /)
147
- end.and_return(invoke_dsc_resource)
142
+ expect(provider).to receive(:powershell_exec!).with(/Module PSDesiredStateConfiguration /).and_return(resource_result)
148
143
  provider.run_action(:run)
149
144
  end
150
145
  end
@@ -153,9 +148,7 @@ describe Chef::Provider::DscResource do
153
148
  let(:resource_records) { [{ "Module" => { "Name" => "ModuleName" } }] }
154
149
 
155
150
  it "returns the default dsc resource module" do
156
- expect(Chef::Util::Powershell::Cmdlet).to receive(:new) do |node, cmdlet, format|
157
- expect(cmdlet).to match(/Module ModuleName /)
158
- end.and_return(invoke_dsc_resource)
151
+ expect(provider).to receive(:powershell_exec!).with(/Module ModuleName /).and_return(resource_result)
159
152
  provider.run_action(:run)
160
153
  end
161
154
  end
@@ -286,8 +279,6 @@ describe Chef::Provider::DscResource do
286
279
  end
287
280
 
288
281
  describe "invoke_resource" do
289
- let(:cmdlet) { double(run!: nil) }
290
-
291
282
  before(:each) do
292
283
  allow(provider).to receive(:translate_type).and_return("my_properties")
293
284
  provider.instance_variable_set(:@new_resource, double(
@@ -301,12 +292,8 @@ describe Chef::Provider::DscResource do
301
292
  end
302
293
 
303
294
  it "invokes Invoke-DscResource command with module name" do
304
- expect(Chef::Util::Powershell::Cmdlet).to receive(:new).with(
305
- node,
306
- "Invoke-DscResource -Method my_method -Name my_resource -Property my_properties -Module my_module -Verbose",
307
- "my_output_format"
308
- ).and_return(cmdlet)
309
- provider.send(:invoke_resource, "my_method", "my_output_format")
295
+ expect(provider).to receive(:powershell_exec!).with("Invoke-DscResource -Method my_method -Name my_resource -Property my_properties -Module my_module -Verbose").and_return(nil)
296
+ provider.send(:invoke_resource, "my_method")
310
297
  end
311
298
  end
312
299
 
@@ -318,12 +305,8 @@ describe Chef::Provider::DscResource do
318
305
  end
319
306
 
320
307
  it "invokes Invoke-DscResource command with module info object" do
321
- expect(Chef::Util::Powershell::Cmdlet).to receive(:new).with(
322
- node,
323
- "Invoke-DscResource -Method my_method -Name my_resource -Property my_properties -Module @{ModuleName='my_module';ModuleVersion='my_module_version'} -Verbose",
324
- "my_output_format"
325
- ).and_return(cmdlet)
326
- provider.send(:invoke_resource, "my_method", "my_output_format")
308
+ expect(provider).to receive(:powershell_exec!).with("Invoke-DscResource -Method my_method -Name my_resource -Property my_properties -Module @{ModuleName='my_module';ModuleVersion='my_module_version'} -Verbose").and_return(nil)
309
+ provider.send(:invoke_resource, "my_method")
327
310
  end
328
311
  end
329
312
  end
@@ -99,7 +99,7 @@ describe Chef::Provider::DscScript do
99
99
  it "should noop if neither code or command are provided" do
100
100
  allow(provider).to receive(:load_current_resource)
101
101
  generator = double("Chef::Util::DSC::ConfigurationGenerator")
102
- expect(generator).to receive(:configuration_document_from_script_code).with("", anything, anything, anything)
102
+ expect(generator).to receive(:configuration_document_from_script_code).with("", anything, anything)
103
103
  allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
104
104
  provider.send(:generate_configuration_document, "tmp", nil)
105
105
  end
@@ -23,6 +23,7 @@ class Chef
23
23
  class Windows
24
24
  class NetUse
25
25
  end
26
+
26
27
  class Volume
27
28
  end
28
29
  end
@@ -18,7 +18,7 @@
18
18
 
19
19
  require "spec_helper"
20
20
 
21
- describe Chef::Provider::SystemdUnit do
21
+ describe Chef::Provider::SystemdUnit, :linux_only do
22
22
 
23
23
  let(:node) { Chef::Node.new }
24
24
  let(:events) { Chef::EventDispatch::Dispatcher.new }
@@ -80,4 +80,16 @@ describe Chef::Resource::WindowsCertificate do
80
80
  resource.store_name "MY"
81
81
  expect { resource.action :create }.not_to raise_error
82
82
  end
83
+
84
+ it "the exportable property defaults to false" do
85
+ expect(resource.exportable).to be false
86
+ end
87
+
88
+ it "doesn't raise error if exportable option is passed" do
89
+ resource.pfx_password "chef$123"
90
+ resource.source "C:\\certs\\test-cert.pfx"
91
+ resource.store_name "MY"
92
+ resource.exportable true
93
+ expect { resource.action :create }.not_to raise_error
94
+ end
83
95
  end
@@ -25,6 +25,85 @@ describe Chef::Util::DSC::ConfigurationGenerator do
25
25
  Chef::Util::DSC::ConfigurationGenerator.new(node, "tmp")
26
26
  end
27
27
 
28
+ describe "#validate_switch_name!" do
29
+ it "should not raise an error if a name contains all upper case letters" do
30
+ conf_man.send(:validate_switch_name!, "HELLO")
31
+ end
32
+
33
+ it "should not raise an error if the name contains all lower case letters" do
34
+ conf_man.send(:validate_switch_name!, "hello")
35
+ end
36
+
37
+ it "should not raise an error if no special characters are used except _" do
38
+ conf_man.send(:validate_switch_name!, "hello_world")
39
+ end
40
+
41
+ %w{! @ # $ % ^ & * & * ( ) - = + \{ \} . ? < > \\ /}.each do |sym|
42
+ it "raises an ArgumentError if configuration name contains #{sym}" do
43
+ expect do
44
+ conf_man.send(:validate_switch_name!, "Hello#{sym}")
45
+ end.to raise_error(ArgumentError)
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#escape_parameter_value" do
51
+ # Is this list really complete?
52
+ %w{` " # '}.each do |c|
53
+ it "escapes #{c}" do
54
+ expect(conf_man.send(:escape_parameter_value, "stuff #{c}")).to eql("stuff `#{c}")
55
+ end
56
+ end
57
+
58
+ it "does not do anything to a string without special characters" do
59
+ expect(conf_man.send(:escape_parameter_value, "stuff")).to eql("stuff")
60
+ end
61
+ end
62
+
63
+ describe "#escape_string_parameter_value" do
64
+ it "surrounds a string with ''" do
65
+ expect(conf_man.send(:escape_string_parameter_value, "stuff")).to eql("'stuff'")
66
+ end
67
+ end
68
+
69
+ describe "#command_switches_string" do
70
+ it "raises an ArgumentError if the key is not a symbol" do
71
+ expect do
72
+ conf_man.send(:command_switches_string, { "foo" => "bar" })
73
+ end.to raise_error(ArgumentError)
74
+ end
75
+
76
+ it "does not allow invalid switch names" do
77
+ expect do
78
+ conf_man.send(:command_switches_string, { foo!: "bar" })
79
+ end.to raise_error(ArgumentError)
80
+ end
81
+
82
+ it "ignores switches with a false value" do
83
+ expect(conf_man.send(:command_switches_string, { foo: false })).to eql("")
84
+ end
85
+
86
+ it "should correctly handle a value type of string" do
87
+ expect(conf_man.send(:command_switches_string, { foo: "bar" })).to eql("-foo 'bar'")
88
+ end
89
+
90
+ it "should correctly handle a value type of string even when it is 0 length" do
91
+ expect(conf_man.send(:command_switches_string, { foo: "" })).to eql("-foo ''")
92
+ end
93
+
94
+ it "should not quote integers" do
95
+ expect(conf_man.send(:command_switches_string, { foo: 1 })).to eql("-foo 1")
96
+ end
97
+
98
+ it "should not quote floats" do
99
+ expect(conf_man.send(:command_switches_string, { foo: 1.0 })).to eql("-foo 1.0")
100
+ end
101
+
102
+ it "has just the switch when the value is true" do
103
+ expect(conf_man.send(:command_switches_string, { foo: true })).to eql("-foo")
104
+ end
105
+ end
106
+
28
107
  describe "#validate_configuration_name!" do
29
108
  it "should not raise an error if a name contains all upper case letters" do
30
109
  conf_man.send(:validate_configuration_name!, "HELLO")