chef-config 17.9.52 → 17.10.19

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.
@@ -1,1390 +1,1390 @@
1
- #
2
- # Author:: Adam Jacob (<adam@chef.io>)
3
- # Author:: Kyle Goodwin (<kgoodwin@primerevenue.com>)
4
- # Copyright:: Copyright (c) Chef Software Inc.
5
- # License:: Apache License, Version 2.0
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
- #
19
-
20
- require "spec_helper"
21
- require "chef-config/config"
22
-
23
- RSpec.describe ChefConfig::Config do
24
- before(:each) do
25
- ChefConfig::Config.reset
26
-
27
- # By default, treat deprecation warnings as errors in tests.
28
- ChefConfig::Config.treat_deprecation_warnings_as_errors(true)
29
-
30
- # Set environment variable so the setting persists in child processes
31
- ENV["CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS"] = "1"
32
- end
33
-
34
- describe "config attribute writer: chef_server_url" do
35
- before do
36
- ChefConfig::Config.chef_server_url = "https://junglist.gen.nz"
37
- end
38
-
39
- it "sets the server url" do
40
- expect(ChefConfig::Config.chef_server_url).to eq("https://junglist.gen.nz")
41
- end
42
-
43
- context "when the url has a leading space" do
44
- before do
45
- ChefConfig::Config.chef_server_url = " https://junglist.gen.nz"
46
- end
47
-
48
- it "strips the space from the url when setting" do
49
- expect(ChefConfig::Config.chef_server_url).to eq("https://junglist.gen.nz")
50
- end
51
-
52
- end
53
-
54
- context "when the url is a frozen string" do
55
- before do
56
- ChefConfig::Config.chef_server_url = " https://junglist.gen.nz".freeze
57
- end
58
-
59
- it "strips the space from the url when setting without raising an error" do
60
- expect(ChefConfig::Config.chef_server_url).to eq("https://junglist.gen.nz")
61
- end
62
- end
63
-
64
- context "when the url is invalid" do
65
- it "raises an exception" do
66
- expect { ChefConfig::Config.chef_server_url = "127.0.0.1" }.to raise_error(ChefConfig::ConfigurationError)
67
- end
68
- end
69
- end
70
-
71
- describe "parsing arbitrary config from the CLI" do
72
-
73
- def apply_config
74
- described_class.apply_extra_config_options(extra_config_options)
75
- end
76
-
77
- context "when no arbitrary config is given" do
78
-
79
- let(:extra_config_options) { nil }
80
-
81
- it "succeeds" do
82
- expect { apply_config }.to_not raise_error
83
- end
84
-
85
- end
86
-
87
- context "when given a simple string option" do
88
-
89
- let(:extra_config_options) { [ "node_name=bobotclown" ] }
90
-
91
- it "applies the string option" do
92
- apply_config
93
- expect(described_class[:node_name]).to eq("bobotclown")
94
- end
95
-
96
- end
97
-
98
- context "when given a blank value" do
99
-
100
- let(:extra_config_options) { [ "http_retries=" ] }
101
-
102
- it "sets the value to nil" do
103
- # ensure the value is actually changed in the test
104
- described_class[:http_retries] = 55
105
- apply_config
106
- expect(described_class[:http_retries]).to eq(nil)
107
- end
108
- end
109
-
110
- context "when given spaces between `key = value`" do
111
-
112
- let(:extra_config_options) { [ "node_name = bobo" ] }
113
-
114
- it "handles the extra spaces and applies the config option" do
115
- apply_config
116
- expect(described_class[:node_name]).to eq("bobo")
117
- end
118
-
119
- end
120
-
121
- context "when given an integer value" do
122
-
123
- let(:extra_config_options) { [ "http_retries=9000" ] }
124
-
125
- it "converts to a numeric type and applies the config option" do
126
- apply_config
127
- expect(described_class[:http_retries]).to eq(9000)
128
- end
129
-
130
- end
131
-
132
- context "when given a boolean" do
133
-
134
- let(:extra_config_options) { [ "boolean_thing=true" ] }
135
-
136
- it "converts to a boolean type and applies the config option" do
137
- apply_config
138
- expect(described_class[:boolean_thing]).to eq(true)
139
- end
140
-
141
- end
142
-
143
- context "when given input that is not in key=value form" do
144
-
145
- let(:extra_config_options) { [ "http_retries:9000" ] }
146
-
147
- it "raises UnparsableConfigOption" do
148
- message = 'Unparsable config option "http_retries:9000"'
149
- expect { apply_config }.to raise_error(ChefConfig::UnparsableConfigOption, message)
150
- end
151
-
152
- end
153
-
154
- describe "expand relative paths" do
155
- let(:current_directory) { Dir.pwd }
156
-
157
- context "when given cookbook_path" do
158
- let(:extra_config_options) { [ "cookbook_path=cookbooks/" ] }
159
-
160
- it "expanded cookbook_path" do
161
- apply_config
162
- expect(described_class[:cookbook_path]).to eq("#{current_directory}/cookbooks")
163
- end
164
- end
165
-
166
- context "when passes multiple config options" do
167
- let(:extra_config_options) { ["data_bag_path=data_bags/", "cookbook_path=cookbooks", "chef_repo_path=."] }
168
-
169
- it "expanded paths" do
170
- apply_config
171
- expect(described_class[:data_bag_path]).to eq("#{current_directory}/data_bags")
172
- expect(described_class[:cookbook_path]).to eq("#{current_directory}/cookbooks")
173
- expect(described_class[:chef_repo_path]).to eq(current_directory)
174
- end
175
- end
176
-
177
- context "when passes multiple cookbook_paths in config options" do
178
- let(:extra_config_options) { ["cookbook_path=[first_cookbook, second_cookbooks]"] }
179
-
180
- it "expanded paths" do
181
- apply_config
182
- expect(described_class[:cookbook_path]).to eq(["#{current_directory}/first_cookbook", "#{current_directory}/second_cookbooks"])
183
- end
184
- end
185
- end
186
- end
187
-
188
- describe "when configuring formatters" do
189
- # if TTY and not(force-logger)
190
- # formatter = configured formatter or default formatter
191
- # formatter goes to STDOUT/ERR
192
- # if log file is writeable
193
- # log level is configured level or info
194
- # log location is file
195
- # else
196
- # log level is warn
197
- # log location is STDERR
198
- # end
199
- # elsif not(TTY) and force formatter
200
- # formatter = configured formatter or default formatter
201
- # if log_location specified
202
- # formatter goes to log_location
203
- # else
204
- # formatter goes to STDOUT/ERR
205
- # end
206
- # else
207
- # formatter = "null"
208
- # log_location = configured-value or default
209
- # log_level = info or default
210
- # end
211
- #
212
- it "has an empty list of formatters by default" do
213
- expect(ChefConfig::Config.formatters).to eq([])
214
- end
215
-
216
- it "configures a formatter with a short name" do
217
- ChefConfig::Config.add_formatter(:doc)
218
- expect(ChefConfig::Config.formatters).to eq([[:doc, nil]])
219
- end
220
-
221
- it "configures a formatter with a file output" do
222
- ChefConfig::Config.add_formatter(:doc, "/var/log/formatter.log")
223
- expect(ChefConfig::Config.formatters).to eq([[:doc, "/var/log/formatter.log"]])
224
- end
225
- end
226
-
227
- describe "#var_chef_path" do
228
- let(:dirname) { ChefUtils::Dist::Infra::DIR_SUFFIX }
229
-
230
- context "on unix", :unix_only do
231
- it "var_chef_dir is /var/chef" do
232
- expect(ChefConfig::Config.var_chef_dir).to eql("/var/#{dirname}")
233
- end
234
-
235
- it "var_root_dir is /var" do
236
- expect(ChefConfig::Config.var_root_dir).to eql("/var")
237
- end
238
-
239
- it "etc_chef_dir is /etc/chef" do
240
- expect(ChefConfig::Config.etc_chef_dir).to eql("/etc/#{dirname}")
241
- end
242
- end
243
-
244
- context "on windows", :windows_only do
245
- it "var_chef_dir is C:\\chef" do
246
- expect(ChefConfig::Config.var_chef_dir).to eql("C:\\#{dirname}")
247
- end
248
-
249
- it "var_root_dir is C:\\" do
250
- expect(ChefConfig::Config.var_root_dir).to eql("C:\\")
251
- end
252
-
253
- it "etc_chef_dir is C:\\chef" do
254
- expect(ChefConfig::Config.etc_chef_dir).to eql("C:\\#{dirname}")
255
- end
256
- end
257
-
258
- context "when forced to unix" do
259
- it "var_chef_dir is /var/chef" do
260
- expect(ChefConfig::Config.var_chef_dir(windows: false)).to eql("/var/#{dirname}")
261
- end
262
-
263
- it "var_root_dir is /var" do
264
- expect(ChefConfig::Config.var_root_dir(windows: false)).to eql("/var")
265
- end
266
-
267
- it "etc_chef_dir is /etc/chef" do
268
- expect(ChefConfig::Config.etc_chef_dir(windows: false)).to eql("/etc/#{dirname}")
269
- end
270
- end
271
-
272
- context "when forced to windows" do
273
- it "var_chef_dir is C:\\chef" do
274
- expect(ChefConfig::Config.var_chef_dir(windows: true)).to eql("C:\\#{dirname}")
275
- end
276
-
277
- it "var_root_dir is C:\\" do
278
- expect(ChefConfig::Config.var_root_dir(windows: true)).to eql("C:\\")
279
- end
280
-
281
- it "etc_chef_dir is C:\\chef" do
282
- expect(ChefConfig::Config.etc_chef_dir(windows: true)).to eql("C:\\#{dirname}")
283
- end
284
- end
285
- end
286
-
287
- [ false, true ].each do |is_windows|
288
- context "On #{is_windows ? "Windows" : "Unix"}" do
289
- before :each do
290
- allow(ChefUtils).to receive(:windows?).and_return(is_windows)
291
- end
292
- describe "class method: windows_installation_drive" do
293
- before do
294
- allow(File).to receive(:expand_path).and_return("D:/Path/To/Executable")
295
- end
296
- if is_windows
297
- it "should return D: on a windows system" do
298
- expect(ChefConfig::Config.windows_installation_drive).to eq("D:")
299
- end
300
- else
301
- it "should return nil on a non-windows system" do
302
- expect(ChefConfig::Config.windows_installation_drive).to eq(nil)
303
- end
304
- end
305
- end
306
- describe "class method: platform_specific_path" do
307
- before do
308
- allow(ChefConfig::Config).to receive(:env).and_return({ "SYSTEMDRIVE" => "C:" })
309
- end
310
- if is_windows
311
- path = "/etc/chef/cookbooks"
312
- context "a windows system with chef installed on C: drive" do
313
- before do
314
- allow(ChefConfig::Config).to receive(:windows_installation_drive).and_return("C:")
315
- end
316
- it "should return a windows path rooted in C:" do
317
- expect(ChefConfig::Config.platform_specific_path(path)).to eq("C:\\chef\\cookbooks")
318
- end
319
- end
320
- context "a windows system with chef installed on D: drive" do
321
- before do
322
- allow(ChefConfig::Config).to receive(:windows_installation_drive).and_return("D:")
323
- end
324
- it "should return a windows path rooted in D:" do
325
- expect(ChefConfig::Config.platform_specific_path(path)).to eq("D:\\chef\\cookbooks")
326
- end
327
- end
328
- else
329
- it "should return given path on non-windows systems" do
330
- path = "/etc/chef/cookbooks"
331
- expect(ChefConfig::Config.platform_specific_path(path)).to eq("/etc/chef/cookbooks")
332
- end
333
- end
334
- end
335
-
336
- describe "default values" do
337
- let(:system_drive) { ChefConfig::Config.env["SYSTEMDRIVE"] } if is_windows
338
- let :primary_cache_path do
339
- if is_windows
340
- "#{system_drive}\\chef"
341
- else
342
- "/var/chef"
343
- end
344
- end
345
-
346
- let :secondary_cache_path do
347
- if is_windows
348
- "#{ChefConfig::Config[:user_home]}\\.chef"
349
- else
350
- "#{ChefConfig::Config[:user_home]}/.chef"
351
- end
352
- end
353
-
354
- before do
355
- if is_windows
356
- allow(ChefConfig::Config).to receive(:env).and_return({ "SYSTEMDRIVE" => "C:" })
357
- ChefConfig::Config[:user_home] = 'C:\Users\charlie'
358
- else
359
- ChefConfig::Config[:user_home] = "/Users/charlie"
360
- end
361
-
362
- allow(ChefConfig::Config).to receive(:path_accessible?).and_return(false)
363
- end
364
-
365
- describe "ChefConfig::Config[:client_key]" do
366
- let(:path_to_client_key) { ChefConfig::Config.etc_chef_dir + ChefConfig::PathHelper.path_separator }
367
-
368
- it "sets the default path to the client key" do
369
- expect(ChefConfig::Config.client_key).to eq(path_to_client_key + "client.pem")
370
- end
371
-
372
- context "when target mode is enabled" do
373
- let(:target_mode_host) { "fluffy.kittens.org" }
374
-
375
- before do
376
- ChefConfig::Config.target_mode.enabled = true
377
- ChefConfig::Config.target_mode.host = target_mode_host
378
- end
379
-
380
- it "sets the default path to the client key with the target host name" do
381
- expect(ChefConfig::Config.client_key).to eq(path_to_client_key + target_mode_host + ChefConfig::PathHelper.path_separator + "client.pem")
382
- end
383
- end
384
-
385
- context "when local mode is enabled" do
386
- before { ChefConfig::Config[:local_mode] = true }
387
-
388
- it "returns nil" do
389
- expect(ChefConfig::Config.client_key).to be_nil
390
- end
391
- end
392
- end
393
-
394
- describe "ChefConfig::Config[:fips]" do
395
- let(:fips_enabled) { false }
396
-
397
- before(:all) do
398
- @original_env = ENV.to_hash
399
- end
400
-
401
- after(:all) do
402
- ENV.clear
403
- ENV.update(@original_env)
404
- end
405
-
406
- before(:each) do
407
- ENV["CHEF_FIPS"] = nil
408
- allow(ChefConfig).to receive(:fips?).and_return(fips_enabled)
409
- end
410
-
411
- it "returns false when no environment is set and not enabled on system" do
412
- expect(ChefConfig::Config[:fips]).to eq(false)
413
- end
414
-
415
- context "when ENV['CHEF_FIPS'] is empty" do
416
- before do
417
- ENV["CHEF_FIPS"] = ""
418
- end
419
-
420
- it "returns false" do
421
- expect(ChefConfig::Config[:fips]).to eq(false)
422
- end
423
- end
424
-
425
- context "when ENV['CHEF_FIPS'] is set" do
426
- before do
427
- ENV["CHEF_FIPS"] = "1"
428
- end
429
-
430
- it "returns true" do
431
- expect(ChefConfig::Config[:fips]).to eq(true)
432
- end
433
- end
434
-
435
- context "when fips is enabled on system" do
436
- let(:fips_enabled) { true }
437
-
438
- it "returns true" do
439
- expect(ChefConfig::Config[:fips]).to eq(true)
440
- end
441
- end
442
- end
443
-
444
- describe "ChefConfig::Config[:chef_server_root]" do
445
- context "when chef_server_url isn't set manually" do
446
- it "returns the default of 'https://localhost:443'" do
447
- expect(ChefConfig::Config[:chef_server_root]).to eq("https://localhost:443")
448
- end
449
- end
450
-
451
- context "when chef_server_url matches '../organizations/*' without a trailing slash" do
452
- before do
453
- ChefConfig::Config[:chef_server_url] = "https://example.com/organizations/myorg"
454
- end
455
- it "returns the full URL without /organizations/*" do
456
- expect(ChefConfig::Config[:chef_server_root]).to eq("https://example.com")
457
- end
458
- end
459
-
460
- context "when chef_server_url matches '../organizations/*' with a trailing slash" do
461
- before do
462
- ChefConfig::Config[:chef_server_url] = "https://example.com/organizations/myorg/"
463
- end
464
- it "returns the full URL without /organizations/*" do
465
- expect(ChefConfig::Config[:chef_server_root]).to eq("https://example.com")
466
- end
467
- end
468
-
469
- context "when chef_server_url matches '..organizations..' but not '../organizations/*'" do
470
- before do
471
- ChefConfig::Config[:chef_server_url] = "https://organizations.com/organizations"
472
- end
473
- it "returns the full URL without any modifications" do
474
- expect(ChefConfig::Config[:chef_server_root]).to eq(ChefConfig::Config[:chef_server_url])
475
- end
476
- end
477
-
478
- context "when chef_server_url is a standard URL without the string organization(s)" do
479
- before do
480
- ChefConfig::Config[:chef_server_url] = "https://example.com/some_other_string"
481
- end
482
- it "returns the full URL without any modifications" do
483
- expect(ChefConfig::Config[:chef_server_root]).to eq(ChefConfig::Config[:chef_server_url])
484
- end
485
- end
486
- end
487
-
488
- describe "ChefConfig::Config[:cache_path]" do
489
- let(:target_mode_host) { "fluffy.kittens.org" }
490
- let(:target_mode_primary_cache_path) { ChefUtils.windows? ? "#{primary_cache_path}\\#{target_mode_host}" : "#{primary_cache_path}/#{target_mode_host}" }
491
- let(:target_mode_secondary_cache_path) { ChefUtils.windows? ? "#{secondary_cache_path}\\#{target_mode_host}" : "#{secondary_cache_path}/#{target_mode_host}" }
492
-
493
- before do
494
- if is_windows
495
- allow(File).to receive(:expand_path).and_return("#{system_drive}/Path/To/Executable")
496
- end
497
- end
498
-
499
- context "when /var/chef exists and is accessible" do
500
- before do
501
- allow(ChefConfig::Config).to receive(:path_accessible?).with(ChefConfig::Config.var_chef_dir).and_return(true)
502
- end
503
-
504
- it "defaults to /var/chef" do
505
- expect(ChefConfig::Config[:cache_path]).to eq(primary_cache_path)
506
- end
507
-
508
- context "and target mode is enabled" do
509
- it "cache path includes the target host name" do
510
- ChefConfig::Config.target_mode.enabled = true
511
- ChefConfig::Config.target_mode.host = target_mode_host
512
- expect(ChefConfig::Config[:cache_path]).to eq(target_mode_primary_cache_path)
513
- end
514
- end
515
- end
516
-
517
- context "when /var/chef does not exist and /var is accessible" do
518
- it "defaults to /var/chef" do
519
- allow(File).to receive(:exists?).with(ChefConfig::Config.var_chef_dir).and_return(false)
520
- allow(ChefConfig::Config).to receive(:path_accessible?).with(ChefConfig::Config.var_root_dir).and_return(true)
521
- expect(ChefConfig::Config[:cache_path]).to eq(primary_cache_path)
522
- end
523
- end
524
-
525
- context "when /var/chef does not exist and /var is not accessible" do
526
- it "defaults to $HOME/.chef" do
527
- allow(File).to receive(:exists?).with(ChefConfig::Config.var_chef_dir).and_return(false)
528
- allow(ChefConfig::Config).to receive(:path_accessible?).with(ChefConfig::Config.var_root_dir).and_return(false)
529
- expect(ChefConfig::Config[:cache_path]).to eq(secondary_cache_path)
530
- end
531
- end
532
-
533
- context "when /var/chef exists and is not accessible" do
534
- before do
535
- allow(File).to receive(:exists?).with(ChefConfig::Config.var_chef_dir).and_return(true)
536
- allow(File).to receive(:readable?).with(ChefConfig::Config.var_chef_dir).and_return(true)
537
- allow(File).to receive(:writable?).with(ChefConfig::Config.var_chef_dir).and_return(false)
538
- end
539
-
540
- it "defaults to $HOME/.chef" do
541
- expect(ChefConfig::Config[:cache_path]).to eq(secondary_cache_path)
542
- end
543
-
544
- context "and target mode is enabled" do
545
- it "cache path defaults to $HOME/.chef with the target host name" do
546
- ChefConfig::Config.target_mode.enabled = true
547
- ChefConfig::Config.target_mode.host = target_mode_host
548
- expect(ChefConfig::Config[:cache_path]).to eq(target_mode_secondary_cache_path)
549
- end
550
- end
551
- end
552
-
553
- context "when chef is running in local mode" do
554
- before do
555
- ChefConfig::Config.local_mode = true
556
- end
557
-
558
- context "and config_dir is /a/b/c" do
559
- before do
560
- ChefConfig::Config.config_dir ChefConfig::PathHelper.cleanpath("/a/b/c")
561
- end
562
-
563
- it "cache_path is /a/b/c/local-mode-cache" do
564
- expect(ChefConfig::Config.cache_path).to eq(ChefConfig::PathHelper.cleanpath("/a/b/c/local-mode-cache"))
565
- end
566
- end
567
-
568
- context "and config_dir is /a/b/c/" do
569
- before do
570
- ChefConfig::Config.config_dir ChefConfig::PathHelper.cleanpath("/a/b/c/")
571
- end
572
-
573
- it "cache_path is /a/b/c/local-mode-cache" do
574
- expect(ChefConfig::Config.cache_path).to eq(ChefConfig::PathHelper.cleanpath("/a/b/c/local-mode-cache"))
575
- end
576
- end
577
- end
578
- end
579
-
580
- it "ChefConfig::Config[:stream_execute_output] defaults to false" do
581
- expect(ChefConfig::Config[:stream_execute_output]).to eq(false)
582
- end
583
-
584
- it "ChefConfig::Config[:show_download_progress] defaults to false" do
585
- expect(ChefConfig::Config[:show_download_progress]).to eq(false)
586
- end
587
-
588
- it "ChefConfig::Config[:download_progress_interval] defaults to every 10%" do
589
- expect(ChefConfig::Config[:download_progress_interval]).to eq(10)
590
- end
591
-
592
- it "ChefConfig::Config[:file_backup_path] defaults to /var/chef/backup" do
593
- allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
594
- backup_path = is_windows ? "#{primary_cache_path}\\backup" : "#{primary_cache_path}/backup"
595
- expect(ChefConfig::Config[:file_backup_path]).to eq(backup_path)
596
- end
597
-
598
- it "ChefConfig::Config[:ssl_verify_mode] defaults to :verify_peer" do
599
- expect(ChefConfig::Config[:ssl_verify_mode]).to eq(:verify_peer)
600
- end
601
-
602
- it "ChefConfig::Config[:ssl_ca_path] defaults to nil" do
603
- expect(ChefConfig::Config[:ssl_ca_path]).to be_nil
604
- end
605
-
606
- describe "ChefConfig::Config[:repo_mode]" do
607
-
608
- context "when local mode is enabled" do
609
-
610
- before { ChefConfig::Config[:local_mode] = true }
611
-
612
- it "defaults to 'hosted_everything'" do
613
- expect(ChefConfig::Config[:repo_mode]).to eq("hosted_everything")
614
- end
615
-
616
- context "and osc_compat is enabled" do
617
-
618
- before { ChefConfig::Config.chef_zero.osc_compat = true }
619
-
620
- it "defaults to 'everything'" do
621
- expect(ChefConfig::Config[:repo_mode]).to eq("everything")
622
- end
623
- end
624
- end
625
-
626
- context "when local mode is not enabled" do
627
-
628
- context "and the chef_server_url is multi-tenant" do
629
-
630
- before { ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/example" }
631
-
632
- it "defaults to 'hosted_everything'" do
633
- expect(ChefConfig::Config[:repo_mode]).to eq("hosted_everything")
634
- end
635
-
636
- end
637
-
638
- context "and the chef_server_url is not multi-tenant" do
639
-
640
- before { ChefConfig::Config[:chef_server_url] = "https://chef.example/" }
641
-
642
- it "defaults to 'everything'" do
643
- expect(ChefConfig::Config[:repo_mode]).to eq("everything")
644
- end
645
- end
646
- end
647
- end
648
-
649
- describe "ChefConfig::Config[:chef_repo_path]" do
650
-
651
- context "when cookbook_path is set to a single path" do
652
-
653
- before { ChefConfig::Config[:cookbook_path] = "/home/anne/repo/cookbooks" }
654
-
655
- it "is set to a path one directory up from the cookbook_path" do
656
- expected = File.expand_path("/home/anne/repo")
657
- expect(ChefConfig::Config[:chef_repo_path]).to eq(expected)
658
- end
659
-
660
- end
661
-
662
- context "when cookbook_path is set to multiple paths" do
663
-
664
- before do
665
- ChefConfig::Config[:cookbook_path] = [
666
- "/home/anne/repo/cookbooks",
667
- "/home/anne/other_repo/cookbooks",
668
- ]
669
- end
670
-
671
- it "is set to an Array of paths one directory up from the cookbook_paths" do
672
- expected = [ "/home/anne/repo", "/home/anne/other_repo"].map { |p| File.expand_path(p) }
673
- expect(ChefConfig::Config[:chef_repo_path]).to eq(expected)
674
- end
675
-
676
- end
677
-
678
- context "when cookbook_path is not set but cookbook_artifact_path is set" do
679
-
680
- before do
681
- ChefConfig::Config[:cookbook_path] = nil
682
- ChefConfig::Config[:cookbook_artifact_path] = "/home/roxie/repo/cookbook_artifacts"
683
- end
684
-
685
- it "is set to a path one directory up from the cookbook_artifact_path" do
686
- expected = File.expand_path("/home/roxie/repo")
687
- expect(ChefConfig::Config[:chef_repo_path]).to eq(expected)
688
- end
689
-
690
- end
691
-
692
- context "when cookbook_path is not set" do
693
-
694
- before { ChefConfig::Config[:cookbook_path] = nil }
695
-
696
- it "is set to the cache_path" do
697
- expect(ChefConfig::Config[:chef_repo_path]).to eq(ChefConfig::Config[:cache_path])
698
- end
699
-
700
- end
701
-
702
- end
703
-
704
- # On Windows, we'll detect an omnibus build and set this to the
705
- # cacert.pem included in the package, but it's nil if you're on Windows
706
- # w/o omnibus (e.g., doing development on Windows, custom build, etc.)
707
- unless is_windows
708
- it "ChefConfig::Config[:ssl_ca_file] defaults to nil" do
709
- expect(ChefConfig::Config[:ssl_ca_file]).to be_nil
710
- end
711
- end
712
-
713
- it "ChefConfig::Config[:data_bag_path] defaults to /var/chef/data_bags" do
714
- allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
715
- data_bag_path = is_windows ? "#{primary_cache_path}\\data_bags" : "#{primary_cache_path}/data_bags"
716
- expect(ChefConfig::Config[:data_bag_path]).to eq(data_bag_path)
717
- end
718
-
719
- it "ChefConfig::Config[:environment_path] defaults to /var/chef/environments" do
720
- allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
721
- environment_path = is_windows ? "#{primary_cache_path}\\environments" : "#{primary_cache_path}/environments"
722
- expect(ChefConfig::Config[:environment_path]).to eq(environment_path)
723
- end
724
-
725
- it "ChefConfig::Config[:cookbook_artifact_path] defaults to /var/chef/cookbook_artifacts" do
726
- allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
727
- environment_path = is_windows ? "#{primary_cache_path}\\cookbook_artifacts" : "#{primary_cache_path}/cookbook_artifacts"
728
- expect(ChefConfig::Config[:cookbook_artifact_path]).to eq(environment_path)
729
- end
730
-
731
- describe "setting the config dir" do
732
-
733
- context "when the config file is given with a relative path" do
734
-
735
- before do
736
- ChefConfig::Config.config_file = "client.rb"
737
- end
738
-
739
- it "expands the path when determining config_dir" do
740
- # config_dir goes through ChefConfig::PathHelper.canonical_path, which
741
- # downcases on windows because the FS is case insensitive, so we
742
- # have to downcase expected and actual to make the tests work.
743
- expect(ChefConfig::Config.config_dir.downcase).to eq(ChefConfig::PathHelper.cleanpath(Dir.pwd).downcase)
744
- end
745
-
746
- it "does not set derived paths at FS root" do
747
- ChefConfig::Config.local_mode = true
748
- expect(ChefConfig::Config.cache_path.downcase).to eq(ChefConfig::PathHelper.cleanpath(File.join(Dir.pwd, "local-mode-cache")).downcase)
749
- end
750
-
751
- end
752
-
753
- context "when the config file is /etc/chef/client.rb" do
754
-
755
- before do
756
- config_location = ChefConfig::PathHelper.cleanpath(ChefConfig::PathHelper.join(ChefConfig::Config.etc_chef_dir, "client.rb")).downcase
757
- allow(File).to receive(:absolute_path).with(config_location).and_return(config_location)
758
- ChefConfig::Config.config_file = config_location
759
- end
760
-
761
- it "config_dir is /etc/chef" do
762
- expect(ChefConfig::Config.config_dir).to eq(ChefConfig::Config.etc_chef_dir.downcase)
763
- end
764
-
765
- context "and chef is running in local mode" do
766
- before do
767
- ChefConfig::Config.local_mode = true
768
- end
769
-
770
- it "config_dir is /etc/chef" do
771
- expect(ChefConfig::Config.config_dir).to eq(ChefConfig::Config.etc_chef_dir.downcase)
772
- end
773
- end
774
-
775
- context "when config_dir is set to /other/config/dir/" do
776
- before do
777
- ChefConfig::Config.config_dir = ChefConfig::PathHelper.cleanpath("/other/config/dir/")
778
- end
779
-
780
- it "yields the explicit value" do
781
- expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.cleanpath("/other/config/dir/"))
782
- end
783
- end
784
-
785
- end
786
-
787
- context "when the user's home dir is /home/charlie/" do
788
- before do
789
- ChefConfig::Config.user_home = "/home/charlie/"
790
- end
791
-
792
- it "config_dir is /home/charlie/.chef/" do
793
- expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
794
- end
795
-
796
- context "and chef is running in local mode" do
797
- before do
798
- ChefConfig::Config.local_mode = true
799
- end
800
-
801
- it "config_dir is /home/charlie/.chef/" do
802
- expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
803
- end
804
- end
805
- end
806
-
807
- if is_windows
808
- context "when the user's home dir is windows specific" do
809
- before do
810
- ChefConfig::Config.user_home = ChefConfig::PathHelper.cleanpath("/home/charlie/")
811
- end
812
-
813
- it "config_dir is with backslashes" do
814
- expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
815
- end
816
-
817
- context "and chef is running in local mode" do
818
- before do
819
- ChefConfig::Config.local_mode = true
820
- end
821
-
822
- it "config_dir is with backslashes" do
823
- expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
824
- end
825
- end
826
- end
827
-
828
- end
829
-
830
- end
831
-
832
- if is_windows
833
- describe "finding the windows embedded dir" do
834
- let(:default_config_location) { "c:/opscode/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/config.rb" }
835
- let(:alternate_install_location) { "c:/my/alternate/install/place/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/config.rb" }
836
- let(:non_omnibus_location) { "c:/my/dev/stuff/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/config.rb" }
837
-
838
- let(:default_ca_file) { "c:/opscode/chef/embedded/ssl/certs/cacert.pem" }
839
-
840
- it "finds the embedded dir in the default location" do
841
- allow(ChefConfig::Config).to receive(:_this_file).and_return(default_config_location)
842
- expect(ChefConfig::Config.embedded_dir).to eq("c:/opscode/chef/embedded")
843
- end
844
-
845
- it "finds the embedded dir in a custom install location" do
846
- allow(ChefConfig::Config).to receive(:_this_file).and_return(alternate_install_location)
847
- expect(ChefConfig::Config.embedded_dir).to eq("c:/my/alternate/install/place/chef/embedded")
848
- end
849
-
850
- it "doesn't error when not in an omnibus install" do
851
- allow(ChefConfig::Config).to receive(:_this_file).and_return(non_omnibus_location)
852
- expect(ChefConfig::Config.embedded_dir).to be_nil
853
- end
854
-
855
- it "sets the ssl_ca_cert path if the cert file is available" do
856
- allow(ChefConfig::Config).to receive(:_this_file).and_return(default_config_location)
857
- allow(File).to receive(:exist?).with(default_ca_file).and_return(true)
858
- expect(ChefConfig::Config.ssl_ca_file).to eq(default_ca_file)
859
- end
860
- end
861
- end
862
- end
863
-
864
- describe "ChefConfig::Config[:user_home]" do
865
- it "should set when HOME is provided" do
866
- expected = ChefConfig::PathHelper.cleanpath("/home/kitten")
867
- allow(ChefConfig::PathHelper).to receive(:home).and_return(expected)
868
- expect(ChefConfig::Config[:user_home]).to eq(expected)
869
- end
870
-
871
- it "falls back to the current working directory when HOME and USERPROFILE is not set" do
872
- allow(ChefConfig::PathHelper).to receive(:home).and_return(nil)
873
- expect(ChefConfig::Config[:user_home]).to eq(Dir.pwd)
874
- end
875
- end
876
-
877
- describe "ChefConfig::Config[:encrypted_data_bag_secret]" do
878
- let(:db_secret_default_path) { ChefConfig::PathHelper.cleanpath("#{ChefConfig::Config.etc_chef_dir}/encrypted_data_bag_secret") }
879
-
880
- before do
881
- allow(File).to receive(:exist?).with(db_secret_default_path).and_return(secret_exists)
882
- end
883
-
884
- context "/etc/chef/encrypted_data_bag_secret exists" do
885
- let(:secret_exists) { true }
886
- it "sets the value to /etc/chef/encrypted_data_bag_secret" do
887
- expect(ChefConfig::Config[:encrypted_data_bag_secret]).to eq db_secret_default_path
888
- end
889
- end
890
-
891
- context "/etc/chef/encrypted_data_bag_secret does not exist" do
892
- let(:secret_exists) { false }
893
- it "sets the value to nil" do
894
- expect(ChefConfig::Config[:encrypted_data_bag_secret]).to be_nil
895
- end
896
- end
897
- end
898
-
899
- describe "ChefConfig::Config[:event_handlers]" do
900
- it "sets a event_handlers to an empty array by default" do
901
- expect(ChefConfig::Config[:event_handlers]).to eq([])
902
- end
903
- it "should be able to add custom handlers" do
904
- o = Object.new
905
- ChefConfig::Config[:event_handlers] << o
906
- expect(ChefConfig::Config[:event_handlers]).to be_include(o)
907
- end
908
- end
909
-
910
- describe "ChefConfig::Config[:user_valid_regex]" do
911
- context "on a platform that is not Windows" do
912
- it "allows one letter usernames" do
913
- any_match = ChefConfig::Config[:user_valid_regex].any? { |regex| regex.match("a") }
914
- expect(any_match).to be_truthy
915
- end
916
- end
917
- end
918
-
919
- describe "ChefConfig::Config[:internal_locale]" do
920
- let(:shell_out) do
921
- cmd = instance_double("Mixlib::ShellOut", exitstatus: 0, stdout: locales, error!: nil)
922
- allow(cmd).to receive(:run_command).and_return(cmd)
923
- cmd
924
- end
925
-
926
- let(:locales) { locale_array.join("\n") }
927
-
928
- before do
929
- allow(Mixlib::ShellOut).to receive(:new).with("locale -a").and_return(shell_out)
930
- end
931
-
932
- shared_examples_for "a suitable locale" do
933
- it "returns an English UTF-8 locale" do
934
- expect(ChefConfig.logger).to_not receive(:warn).with(/Please install an English UTF-8 locale for Chef Infra Client to use/)
935
- expect(ChefConfig.logger).to_not receive(:trace).with(/Defaulting to locale en_US.UTF-8 on Windows/)
936
- expect(ChefConfig.logger).to_not receive(:trace).with(/No usable locale -a command found/)
937
- expect(ChefConfig::Config.guess_internal_locale).to eq expected_locale
938
- end
939
- end
940
-
941
- context "when the result includes 'C.UTF-8'" do
942
- include_examples "a suitable locale" do
943
- let(:locale_array) { [expected_locale, "en_US.UTF-8"] }
944
- let(:expected_locale) { "C.UTF-8" }
945
- end
946
- end
947
-
948
- context "when the result includes 'en_US.UTF-8'" do
949
- include_examples "a suitable locale" do
950
- let(:locale_array) { ["en_CA.UTF-8", expected_locale, "en_NZ.UTF-8"] }
951
- let(:expected_locale) { "en_US.UTF-8" }
952
- end
953
- end
954
-
955
- context "when the result includes 'en_US.utf8'" do
956
- include_examples "a suitable locale" do
957
- let(:locale_array) { ["en_CA.utf8", "en_US.utf8", "en_NZ.utf8"] }
958
- let(:expected_locale) { "en_US.UTF-8" }
959
- end
960
- end
961
-
962
- context "when the result includes 'en.UTF-8'" do
963
- include_examples "a suitable locale" do
964
- let(:locale_array) { ["en.ISO8859-1", expected_locale] }
965
- let(:expected_locale) { "en.UTF-8" }
966
- end
967
- end
968
-
969
- context "when the result includes 'en_*.UTF-8'" do
970
- include_examples "a suitable locale" do
971
- let(:locale_array) { [expected_locale, "en_CA.UTF-8", "en_GB.UTF-8"] }
972
- let(:expected_locale) { "en_AU.UTF-8" }
973
- end
974
- end
975
-
976
- context "when the result includes 'en_*.utf8'" do
977
- include_examples "a suitable locale" do
978
- let(:locale_array) { ["en_AU.utf8", "en_CA.utf8", "en_GB.utf8"] }
979
- let(:expected_locale) { "en_AU.UTF-8" }
980
- end
981
- end
982
-
983
- context "when the result does not include 'en_*.UTF-8'" do
984
- let(:locale_array) { ["af_ZA", "af_ZA.ISO8859-1", "af_ZA.ISO8859-15", "af_ZA.UTF-8"] }
985
-
986
- it "should fall back to C locale" do
987
- expect(ChefConfig.logger).to receive(:warn).with("Please install an English UTF-8 locale for Chef Infra Client to use, falling back to C locale and disabling UTF-8 support.")
988
- expect(ChefConfig::Config.guess_internal_locale).to eq "C"
989
- end
990
- end
991
-
992
- context "on error" do
993
- let(:locale_array) { [] }
994
-
995
- let(:shell_out_cmd) { instance_double("Mixlib::ShellOut") }
996
-
997
- before do
998
- allow(Mixlib::ShellOut).to receive(:new).and_return(shell_out_cmd)
999
- allow(shell_out_cmd).to receive(:run_command)
1000
- allow(shell_out_cmd).to receive(:error!).and_raise(Mixlib::ShellOut::ShellCommandFailed, "this is an error")
1001
- end
1002
-
1003
- it "should default to 'en_US.UTF-8'" do
1004
- if is_windows
1005
- expect(ChefConfig.logger).to receive(:trace).with("Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else.")
1006
- else
1007
- expect(ChefConfig.logger).to receive(:trace).with("No usable locale -a command found, assuming you have en_US.UTF-8 installed.")
1008
- end
1009
- expect(ChefConfig::Config.guess_internal_locale).to eq "en_US.UTF-8"
1010
- end
1011
- end
1012
- end
1013
- end
1014
- end
1015
-
1016
- describe "export_proxies" do
1017
- before(:all) do
1018
- @original_env = ENV.to_hash
1019
- ENV["http_proxy"] = nil
1020
- ENV["HTTP_PROXY"] = nil
1021
- ENV["https_proxy"] = nil
1022
- ENV["HTTPS_PROXY"] = nil
1023
- ENV["ftp_proxy"] = nil
1024
- ENV["FTP_PROXY"] = nil
1025
- ENV["no_proxy"] = nil
1026
- ENV["NO_PROXY"] = nil
1027
- end
1028
-
1029
- after(:all) do
1030
- ENV.clear
1031
- ENV.update(@original_env)
1032
- end
1033
-
1034
- let(:http_proxy) { "http://localhost:7979" }
1035
- let(:https_proxy) { "https://localhost:7979" }
1036
- let(:ftp_proxy) { "ftp://localhost:7979" }
1037
- let(:proxy_user) { "http_user" }
1038
- let(:proxy_pass) { "http_pass" }
1039
-
1040
- context "when http_proxy, proxy_pass and proxy_user are set" do
1041
- before do
1042
- ChefConfig::Config.http_proxy = http_proxy
1043
- ChefConfig::Config.http_proxy_user = proxy_user
1044
- ChefConfig::Config.http_proxy_pass = proxy_pass
1045
- end
1046
- it "exports ENV['http_proxy']" do
1047
- expect(ENV).to receive(:[]=).with("http_proxy", "http://http_user:http_pass@localhost:7979")
1048
- expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://http_user:http_pass@localhost:7979")
1049
- ChefConfig::Config.export_proxies
1050
- end
1051
- end
1052
-
1053
- context "when https_proxy, proxy_pass and proxy_user are set" do
1054
- before do
1055
- ChefConfig::Config.https_proxy = https_proxy
1056
- ChefConfig::Config.https_proxy_user = proxy_user
1057
- ChefConfig::Config.https_proxy_pass = proxy_pass
1058
- end
1059
- it "exports ENV['https_proxy']" do
1060
- expect(ENV).to receive(:[]=).with("https_proxy", "https://http_user:http_pass@localhost:7979")
1061
- expect(ENV).to receive(:[]=).with("HTTPS_PROXY", "https://http_user:http_pass@localhost:7979")
1062
- ChefConfig::Config.export_proxies
1063
- end
1064
- end
1065
-
1066
- context "when ftp_proxy, proxy_pass and proxy_user are set" do
1067
- before do
1068
- ChefConfig::Config.ftp_proxy = ftp_proxy
1069
- ChefConfig::Config.ftp_proxy_user = proxy_user
1070
- ChefConfig::Config.ftp_proxy_pass = proxy_pass
1071
- end
1072
- it "exports ENV['ftp_proxy']" do
1073
- expect(ENV).to receive(:[]=).with("ftp_proxy", "ftp://http_user:http_pass@localhost:7979")
1074
- expect(ENV).to receive(:[]=).with("FTP_PROXY", "ftp://http_user:http_pass@localhost:7979")
1075
- ChefConfig::Config.export_proxies
1076
- end
1077
- end
1078
-
1079
- shared_examples "no user pass" do
1080
- it "does not populate the user or password" do
1081
- expect(ENV).to receive(:[]=).with("http_proxy", "http://localhost:7979")
1082
- expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://localhost:7979")
1083
- ChefConfig::Config.export_proxies
1084
- end
1085
- end
1086
-
1087
- context "when proxy_pass and proxy_user are passed as empty strings" do
1088
- before do
1089
- ChefConfig::Config.http_proxy = http_proxy
1090
- ChefConfig::Config.http_proxy_user = ""
1091
- ChefConfig::Config.http_proxy_pass = proxy_pass
1092
- end
1093
- include_examples "no user pass"
1094
- end
1095
-
1096
- context "when proxy_pass and proxy_user are not provided" do
1097
- before do
1098
- ChefConfig::Config.http_proxy = http_proxy
1099
- end
1100
- include_examples "no user pass"
1101
- end
1102
-
1103
- context "when the proxy is provided without a scheme" do
1104
- before do
1105
- ChefConfig::Config.http_proxy = "localhost:1111"
1106
- end
1107
- it "automatically adds the scheme to the proxy url" do
1108
- expect(ENV).to receive(:[]=).with("http_proxy", "http://localhost:1111")
1109
- expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://localhost:1111")
1110
- ChefConfig::Config.export_proxies
1111
- end
1112
- end
1113
-
1114
- shared_examples "no export" do
1115
- it "does not export any proxy settings" do
1116
- ChefConfig::Config.export_proxies
1117
- expect(ENV["http_proxy"]).to eq(nil)
1118
- expect(ENV["https_proxy"]).to eq(nil)
1119
- expect(ENV["ftp_proxy"]).to eq(nil)
1120
- expect(ENV["no_proxy"]).to eq(nil)
1121
- end
1122
- end
1123
-
1124
- context "when nothing is set" do
1125
- include_examples "no export"
1126
- end
1127
-
1128
- context "when all the users and passwords are set but no proxies are set" do
1129
- before do
1130
- ChefConfig::Config.http_proxy_user = proxy_user
1131
- ChefConfig::Config.http_proxy_pass = proxy_pass
1132
- ChefConfig::Config.https_proxy_user = proxy_user
1133
- ChefConfig::Config.https_proxy_pass = proxy_pass
1134
- ChefConfig::Config.ftp_proxy_user = proxy_user
1135
- ChefConfig::Config.ftp_proxy_pass = proxy_pass
1136
- end
1137
- include_examples "no export"
1138
- end
1139
-
1140
- context "no_proxy is set" do
1141
- before do
1142
- ChefConfig::Config.no_proxy = "localhost"
1143
- end
1144
- it "exports ENV['no_proxy']" do
1145
- expect(ENV).to receive(:[]=).with("no_proxy", "localhost")
1146
- expect(ENV).to receive(:[]=).with("NO_PROXY", "localhost")
1147
- ChefConfig::Config.export_proxies
1148
- end
1149
- end
1150
- end
1151
-
1152
- describe "proxy_uri" do
1153
- subject(:proxy_uri) { described_class.proxy_uri(scheme, host, port) }
1154
- let(:env) { {} }
1155
- let(:scheme) { "http" }
1156
- let(:host) { "test.example.com" }
1157
- let(:port) { 8080 }
1158
- let(:proxy) { "#{proxy_prefix}#{proxy_host}:#{proxy_port}" }
1159
- let(:proxy_prefix) { "http://" }
1160
- let(:proxy_host) { "proxy.mycorp.com" }
1161
- let(:proxy_port) { 8080 }
1162
-
1163
- before do
1164
- stub_const("ENV", env)
1165
- end
1166
-
1167
- shared_examples_for "a proxy uri" do
1168
- it "contains the host" do
1169
- expect(proxy_uri.host).to eq(proxy_host)
1170
- end
1171
-
1172
- it "contains the port" do
1173
- expect(proxy_uri.port).to eq(proxy_port)
1174
- end
1175
- end
1176
-
1177
- context "when the config setting is normalized (does not contain the scheme)" do
1178
- include_examples "a proxy uri" do
1179
-
1180
- let(:proxy_prefix) { "" }
1181
-
1182
- let(:env) do
1183
- {
1184
- "#{scheme}_proxy" => proxy,
1185
- "no_proxy" => nil,
1186
- }
1187
- end
1188
- end
1189
- end
1190
-
1191
- context "when the proxy is set by the environment" do
1192
- include_examples "a proxy uri" do
1193
- let(:scheme) { "https" }
1194
- let(:env) do
1195
- {
1196
- "https_proxy" => "https://jane_username:opensesame@proxy.mycorp.com:8080",
1197
- }
1198
- end
1199
- end
1200
- end
1201
-
1202
- context "when an empty proxy is set by the environment" do
1203
- let(:env) do
1204
- {
1205
- "https_proxy" => "",
1206
- }
1207
- end
1208
-
1209
- it "does not fail with URI parse exception" do
1210
- expect { proxy_uri }.to_not raise_error
1211
- end
1212
- end
1213
-
1214
- context "when no_proxy is set" do
1215
- context "when no_proxy is the exact host" do
1216
- let(:env) do
1217
- {
1218
- "http_proxy" => proxy,
1219
- "no_proxy" => host,
1220
- }
1221
- end
1222
-
1223
- it { is_expected.to eq nil }
1224
- end
1225
-
1226
- context "when no_proxy includes the same domain with a wildcard" do
1227
- let(:env) do
1228
- {
1229
- "http_proxy" => proxy,
1230
- "no_proxy" => "*.example.com",
1231
- }
1232
- end
1233
-
1234
- it { is_expected.to eq nil }
1235
- end
1236
-
1237
- context "when no_proxy is included on a list" do
1238
- let(:env) do
1239
- {
1240
- "http_proxy" => proxy,
1241
- "no_proxy" => "chef.io,getchef.com,opscode.com,test.example.com",
1242
- }
1243
- end
1244
-
1245
- it { is_expected.to eq nil }
1246
- end
1247
-
1248
- context "when no_proxy is included on a list with wildcards" do
1249
- let(:env) do
1250
- {
1251
- "http_proxy" => proxy,
1252
- "no_proxy" => "10.*,*.example.com",
1253
- }
1254
- end
1255
-
1256
- it { is_expected.to eq nil }
1257
- end
1258
-
1259
- context "when no_proxy is a domain with a dot prefix" do
1260
- let(:env) do
1261
- {
1262
- "http_proxy" => proxy,
1263
- "no_proxy" => ".example.com",
1264
- }
1265
- end
1266
-
1267
- it { is_expected.to eq nil }
1268
- end
1269
-
1270
- context "when no_proxy is a domain with no wildcard" do
1271
- let(:env) do
1272
- {
1273
- "http_proxy" => proxy,
1274
- "no_proxy" => "example.com",
1275
- }
1276
- end
1277
-
1278
- it { is_expected.to eq nil }
1279
- end
1280
- end
1281
- end
1282
-
1283
- describe "allowing chefdk configuration outside of chefdk" do
1284
-
1285
- it "allows arbitrary settings in the chefdk config context" do
1286
- expect { ChefConfig::Config.chefdk.generator_cookbook("/path") }.to_not raise_error
1287
- end
1288
-
1289
- end
1290
-
1291
- describe "Treating deprecation warnings as errors" do
1292
-
1293
- context "when using our default RSpec configuration" do
1294
-
1295
- it "defaults to treating deprecation warnings as errors" do
1296
- expect(ChefConfig::Config[:treat_deprecation_warnings_as_errors]).to be(true)
1297
- end
1298
-
1299
- it "sets CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS environment variable" do
1300
- expect(ENV["CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS"]).to eq("1")
1301
- end
1302
-
1303
- it "treats deprecation warnings as errors in child processes when testing" do
1304
- # Doing a full integration test where we launch a child process is slow
1305
- # and liable to break for weird reasons (bundler env stuff, etc.), so
1306
- # we're just checking that the presence of the environment variable
1307
- # causes treat_deprecation_warnings_as_errors to be set to true after a
1308
- # config reset.
1309
- ChefConfig::Config.reset
1310
- expect(ChefConfig::Config[:treat_deprecation_warnings_as_errors]).to be(true)
1311
- end
1312
-
1313
- end
1314
-
1315
- context "outside of our test environment" do
1316
-
1317
- before do
1318
- ENV.delete("CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS")
1319
- ChefConfig::Config.reset
1320
- end
1321
-
1322
- it "defaults to NOT treating deprecation warnings as errors" do
1323
- expect(ChefConfig::Config[:treat_deprecation_warnings_as_errors]).to be(false)
1324
- end
1325
- end
1326
-
1327
- end
1328
-
1329
- describe "data collector URL" do
1330
-
1331
- context "when using default settings" do
1332
-
1333
- context "for Chef Client" do
1334
-
1335
- it "configures the data collector URL as a relative path to the Chef Server URL" do
1336
- ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg"
1337
- expect(ChefConfig::Config[:data_collector][:server_url]).to eq("https://chef.example/organizations/myorg/data-collector")
1338
- end
1339
-
1340
- end
1341
-
1342
- context "for Chef Solo legacy mode" do
1343
-
1344
- before do
1345
- ChefConfig::Config[:solo_legacy_mode] = true
1346
- end
1347
-
1348
- it "sets the data collector server URL to nil" do
1349
- ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg"
1350
- expect(ChefConfig::Config[:data_collector][:server_url]).to be_nil
1351
- end
1352
-
1353
- end
1354
-
1355
- context "for local mode" do
1356
-
1357
- before do
1358
- ChefConfig::Config[:local_mode] = true
1359
- end
1360
-
1361
- it "sets the data collector server URL to nil" do
1362
- ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg"
1363
- expect(ChefConfig::Config[:data_collector][:server_url]).to be_nil
1364
- end
1365
-
1366
- end
1367
-
1368
- end
1369
-
1370
- end
1371
-
1372
- describe "validation_client_name" do
1373
- context "with a normal server URL" do
1374
- before { ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg" }
1375
-
1376
- it "sets the validation client to myorg-validator" do
1377
- expect(ChefConfig::Config[:validation_client_name]).to eq "myorg-validator"
1378
- end
1379
- end
1380
-
1381
- context "with an unusual server URL" do
1382
- before { ChefConfig::Config[:chef_server_url] = "https://chef.example/myorg" }
1383
-
1384
- it "sets the validation client to chef-validator" do
1385
- expect(ChefConfig::Config[:validation_client_name]).to eq "chef-validator"
1386
- end
1387
- end
1388
- end
1389
-
1390
- end
1
+ #
2
+ # Author:: Adam Jacob (<adam@chef.io>)
3
+ # Author:: Kyle Goodwin (<kgoodwin@primerevenue.com>)
4
+ # Copyright:: Copyright (c) Chef Software Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require "spec_helper"
21
+ require "chef-config/config"
22
+
23
+ RSpec.describe ChefConfig::Config do
24
+ before(:each) do
25
+ ChefConfig::Config.reset
26
+
27
+ # By default, treat deprecation warnings as errors in tests.
28
+ ChefConfig::Config.treat_deprecation_warnings_as_errors(true)
29
+
30
+ # Set environment variable so the setting persists in child processes
31
+ ENV["CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS"] = "1"
32
+ end
33
+
34
+ describe "config attribute writer: chef_server_url" do
35
+ before do
36
+ ChefConfig::Config.chef_server_url = "https://junglist.gen.nz"
37
+ end
38
+
39
+ it "sets the server url" do
40
+ expect(ChefConfig::Config.chef_server_url).to eq("https://junglist.gen.nz")
41
+ end
42
+
43
+ context "when the url has a leading space" do
44
+ before do
45
+ ChefConfig::Config.chef_server_url = " https://junglist.gen.nz"
46
+ end
47
+
48
+ it "strips the space from the url when setting" do
49
+ expect(ChefConfig::Config.chef_server_url).to eq("https://junglist.gen.nz")
50
+ end
51
+
52
+ end
53
+
54
+ context "when the url is a frozen string" do
55
+ before do
56
+ ChefConfig::Config.chef_server_url = " https://junglist.gen.nz".freeze
57
+ end
58
+
59
+ it "strips the space from the url when setting without raising an error" do
60
+ expect(ChefConfig::Config.chef_server_url).to eq("https://junglist.gen.nz")
61
+ end
62
+ end
63
+
64
+ context "when the url is invalid" do
65
+ it "raises an exception" do
66
+ expect { ChefConfig::Config.chef_server_url = "127.0.0.1" }.to raise_error(ChefConfig::ConfigurationError)
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "parsing arbitrary config from the CLI" do
72
+
73
+ def apply_config
74
+ described_class.apply_extra_config_options(extra_config_options)
75
+ end
76
+
77
+ context "when no arbitrary config is given" do
78
+
79
+ let(:extra_config_options) { nil }
80
+
81
+ it "succeeds" do
82
+ expect { apply_config }.to_not raise_error
83
+ end
84
+
85
+ end
86
+
87
+ context "when given a simple string option" do
88
+
89
+ let(:extra_config_options) { [ "node_name=bobotclown" ] }
90
+
91
+ it "applies the string option" do
92
+ apply_config
93
+ expect(described_class[:node_name]).to eq("bobotclown")
94
+ end
95
+
96
+ end
97
+
98
+ context "when given a blank value" do
99
+
100
+ let(:extra_config_options) { [ "http_retries=" ] }
101
+
102
+ it "sets the value to nil" do
103
+ # ensure the value is actually changed in the test
104
+ described_class[:http_retries] = 55
105
+ apply_config
106
+ expect(described_class[:http_retries]).to eq(nil)
107
+ end
108
+ end
109
+
110
+ context "when given spaces between `key = value`" do
111
+
112
+ let(:extra_config_options) { [ "node_name = bobo" ] }
113
+
114
+ it "handles the extra spaces and applies the config option" do
115
+ apply_config
116
+ expect(described_class[:node_name]).to eq("bobo")
117
+ end
118
+
119
+ end
120
+
121
+ context "when given an integer value" do
122
+
123
+ let(:extra_config_options) { [ "http_retries=9000" ] }
124
+
125
+ it "converts to a numeric type and applies the config option" do
126
+ apply_config
127
+ expect(described_class[:http_retries]).to eq(9000)
128
+ end
129
+
130
+ end
131
+
132
+ context "when given a boolean" do
133
+
134
+ let(:extra_config_options) { [ "boolean_thing=true" ] }
135
+
136
+ it "converts to a boolean type and applies the config option" do
137
+ apply_config
138
+ expect(described_class[:boolean_thing]).to eq(true)
139
+ end
140
+
141
+ end
142
+
143
+ context "when given input that is not in key=value form" do
144
+
145
+ let(:extra_config_options) { [ "http_retries:9000" ] }
146
+
147
+ it "raises UnparsableConfigOption" do
148
+ message = 'Unparsable config option "http_retries:9000"'
149
+ expect { apply_config }.to raise_error(ChefConfig::UnparsableConfigOption, message)
150
+ end
151
+
152
+ end
153
+
154
+ describe "expand relative paths" do
155
+ let(:current_directory) { Dir.pwd }
156
+
157
+ context "when given cookbook_path" do
158
+ let(:extra_config_options) { [ "cookbook_path=cookbooks/" ] }
159
+
160
+ it "expanded cookbook_path" do
161
+ apply_config
162
+ expect(described_class[:cookbook_path]).to eq("#{current_directory}/cookbooks")
163
+ end
164
+ end
165
+
166
+ context "when passes multiple config options" do
167
+ let(:extra_config_options) { ["data_bag_path=data_bags/", "cookbook_path=cookbooks", "chef_repo_path=."] }
168
+
169
+ it "expanded paths" do
170
+ apply_config
171
+ expect(described_class[:data_bag_path]).to eq("#{current_directory}/data_bags")
172
+ expect(described_class[:cookbook_path]).to eq("#{current_directory}/cookbooks")
173
+ expect(described_class[:chef_repo_path]).to eq(current_directory)
174
+ end
175
+ end
176
+
177
+ context "when passes multiple cookbook_paths in config options" do
178
+ let(:extra_config_options) { ["cookbook_path=[first_cookbook, second_cookbooks]"] }
179
+
180
+ it "expanded paths" do
181
+ apply_config
182
+ expect(described_class[:cookbook_path]).to eq(["#{current_directory}/first_cookbook", "#{current_directory}/second_cookbooks"])
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ describe "when configuring formatters" do
189
+ # if TTY and not(force-logger)
190
+ # formatter = configured formatter or default formatter
191
+ # formatter goes to STDOUT/ERR
192
+ # if log file is writeable
193
+ # log level is configured level or info
194
+ # log location is file
195
+ # else
196
+ # log level is warn
197
+ # log location is STDERR
198
+ # end
199
+ # elsif not(TTY) and force formatter
200
+ # formatter = configured formatter or default formatter
201
+ # if log_location specified
202
+ # formatter goes to log_location
203
+ # else
204
+ # formatter goes to STDOUT/ERR
205
+ # end
206
+ # else
207
+ # formatter = "null"
208
+ # log_location = configured-value or default
209
+ # log_level = info or default
210
+ # end
211
+ #
212
+ it "has an empty list of formatters by default" do
213
+ expect(ChefConfig::Config.formatters).to eq([])
214
+ end
215
+
216
+ it "configures a formatter with a short name" do
217
+ ChefConfig::Config.add_formatter(:doc)
218
+ expect(ChefConfig::Config.formatters).to eq([[:doc, nil]])
219
+ end
220
+
221
+ it "configures a formatter with a file output" do
222
+ ChefConfig::Config.add_formatter(:doc, "/var/log/formatter.log")
223
+ expect(ChefConfig::Config.formatters).to eq([[:doc, "/var/log/formatter.log"]])
224
+ end
225
+ end
226
+
227
+ describe "#var_chef_path" do
228
+ let(:dirname) { ChefUtils::Dist::Infra::DIR_SUFFIX }
229
+
230
+ context "on unix", :unix_only do
231
+ it "var_chef_dir is /var/chef" do
232
+ expect(ChefConfig::Config.var_chef_dir).to eql("/var/#{dirname}")
233
+ end
234
+
235
+ it "var_root_dir is /var" do
236
+ expect(ChefConfig::Config.var_root_dir).to eql("/var")
237
+ end
238
+
239
+ it "etc_chef_dir is /etc/chef" do
240
+ expect(ChefConfig::Config.etc_chef_dir).to eql("/etc/#{dirname}")
241
+ end
242
+ end
243
+
244
+ context "on windows", :windows_only do
245
+ it "var_chef_dir is C:\\chef" do
246
+ expect(ChefConfig::Config.var_chef_dir).to eql("C:\\#{dirname}")
247
+ end
248
+
249
+ it "var_root_dir is C:\\" do
250
+ expect(ChefConfig::Config.var_root_dir).to eql("C:\\")
251
+ end
252
+
253
+ it "etc_chef_dir is C:\\chef" do
254
+ expect(ChefConfig::Config.etc_chef_dir).to eql("C:\\#{dirname}")
255
+ end
256
+ end
257
+
258
+ context "when forced to unix" do
259
+ it "var_chef_dir is /var/chef" do
260
+ expect(ChefConfig::Config.var_chef_dir(windows: false)).to eql("/var/#{dirname}")
261
+ end
262
+
263
+ it "var_root_dir is /var" do
264
+ expect(ChefConfig::Config.var_root_dir(windows: false)).to eql("/var")
265
+ end
266
+
267
+ it "etc_chef_dir is /etc/chef" do
268
+ expect(ChefConfig::Config.etc_chef_dir(windows: false)).to eql("/etc/#{dirname}")
269
+ end
270
+ end
271
+
272
+ context "when forced to windows" do
273
+ it "var_chef_dir is C:\\chef" do
274
+ expect(ChefConfig::Config.var_chef_dir(windows: true)).to eql("C:\\#{dirname}")
275
+ end
276
+
277
+ it "var_root_dir is C:\\" do
278
+ expect(ChefConfig::Config.var_root_dir(windows: true)).to eql("C:\\")
279
+ end
280
+
281
+ it "etc_chef_dir is C:\\chef" do
282
+ expect(ChefConfig::Config.etc_chef_dir(windows: true)).to eql("C:\\#{dirname}")
283
+ end
284
+ end
285
+ end
286
+
287
+ [ false, true ].each do |is_windows|
288
+ context "On #{is_windows ? "Windows" : "Unix"}" do
289
+ before :each do
290
+ allow(ChefUtils).to receive(:windows?).and_return(is_windows)
291
+ end
292
+ describe "class method: windows_installation_drive" do
293
+ before do
294
+ allow(File).to receive(:expand_path).and_return("D:/Path/To/Executable")
295
+ end
296
+ if is_windows
297
+ it "should return D: on a windows system" do
298
+ expect(ChefConfig::Config.windows_installation_drive).to eq("D:")
299
+ end
300
+ else
301
+ it "should return nil on a non-windows system" do
302
+ expect(ChefConfig::Config.windows_installation_drive).to eq(nil)
303
+ end
304
+ end
305
+ end
306
+ describe "class method: platform_specific_path" do
307
+ before do
308
+ allow(ChefConfig::Config).to receive(:env).and_return({ "SYSTEMDRIVE" => "C:" })
309
+ end
310
+ if is_windows
311
+ path = "/etc/chef/cookbooks"
312
+ context "a windows system with chef installed on C: drive" do
313
+ before do
314
+ allow(ChefConfig::Config).to receive(:windows_installation_drive).and_return("C:")
315
+ end
316
+ it "should return a windows path rooted in C:" do
317
+ expect(ChefConfig::Config.platform_specific_path(path)).to eq("C:\\chef\\cookbooks")
318
+ end
319
+ end
320
+ context "a windows system with chef installed on D: drive" do
321
+ before do
322
+ allow(ChefConfig::Config).to receive(:windows_installation_drive).and_return("D:")
323
+ end
324
+ it "should return a windows path rooted in D:" do
325
+ expect(ChefConfig::Config.platform_specific_path(path)).to eq("D:\\chef\\cookbooks")
326
+ end
327
+ end
328
+ else
329
+ it "should return given path on non-windows systems" do
330
+ path = "/etc/chef/cookbooks"
331
+ expect(ChefConfig::Config.platform_specific_path(path)).to eq("/etc/chef/cookbooks")
332
+ end
333
+ end
334
+ end
335
+
336
+ describe "default values" do
337
+ let(:system_drive) { ChefConfig::Config.env["SYSTEMDRIVE"] } if is_windows
338
+ let :primary_cache_path do
339
+ if is_windows
340
+ "#{system_drive}\\chef"
341
+ else
342
+ "/var/chef"
343
+ end
344
+ end
345
+
346
+ let :secondary_cache_path do
347
+ if is_windows
348
+ "#{ChefConfig::Config[:user_home]}\\.chef"
349
+ else
350
+ "#{ChefConfig::Config[:user_home]}/.chef"
351
+ end
352
+ end
353
+
354
+ before do
355
+ if is_windows
356
+ allow(ChefConfig::Config).to receive(:env).and_return({ "SYSTEMDRIVE" => "C:" })
357
+ ChefConfig::Config[:user_home] = 'C:\Users\charlie'
358
+ else
359
+ ChefConfig::Config[:user_home] = "/Users/charlie"
360
+ end
361
+
362
+ allow(ChefConfig::Config).to receive(:path_accessible?).and_return(false)
363
+ end
364
+
365
+ describe "ChefConfig::Config[:client_key]" do
366
+ let(:path_to_client_key) { ChefConfig::Config.etc_chef_dir + ChefConfig::PathHelper.path_separator }
367
+
368
+ it "sets the default path to the client key" do
369
+ expect(ChefConfig::Config.client_key).to eq(path_to_client_key + "client.pem")
370
+ end
371
+
372
+ context "when target mode is enabled" do
373
+ let(:target_mode_host) { "fluffy.kittens.org" }
374
+
375
+ before do
376
+ ChefConfig::Config.target_mode.enabled = true
377
+ ChefConfig::Config.target_mode.host = target_mode_host
378
+ end
379
+
380
+ it "sets the default path to the client key with the target host name" do
381
+ expect(ChefConfig::Config.client_key).to eq(path_to_client_key + target_mode_host + ChefConfig::PathHelper.path_separator + "client.pem")
382
+ end
383
+ end
384
+
385
+ context "when local mode is enabled" do
386
+ before { ChefConfig::Config[:local_mode] = true }
387
+
388
+ it "returns nil" do
389
+ expect(ChefConfig::Config.client_key).to be_nil
390
+ end
391
+ end
392
+ end
393
+
394
+ describe "ChefConfig::Config[:fips]" do
395
+ let(:fips_enabled) { false }
396
+
397
+ before(:all) do
398
+ @original_env = ENV.to_hash
399
+ end
400
+
401
+ after(:all) do
402
+ ENV.clear
403
+ ENV.update(@original_env)
404
+ end
405
+
406
+ before(:each) do
407
+ ENV["CHEF_FIPS"] = nil
408
+ allow(ChefConfig).to receive(:fips?).and_return(fips_enabled)
409
+ end
410
+
411
+ it "returns false when no environment is set and not enabled on system" do
412
+ expect(ChefConfig::Config[:fips]).to eq(false)
413
+ end
414
+
415
+ context "when ENV['CHEF_FIPS'] is empty" do
416
+ before do
417
+ ENV["CHEF_FIPS"] = ""
418
+ end
419
+
420
+ it "returns false" do
421
+ expect(ChefConfig::Config[:fips]).to eq(false)
422
+ end
423
+ end
424
+
425
+ context "when ENV['CHEF_FIPS'] is set" do
426
+ before do
427
+ ENV["CHEF_FIPS"] = "1"
428
+ end
429
+
430
+ it "returns true" do
431
+ expect(ChefConfig::Config[:fips]).to eq(true)
432
+ end
433
+ end
434
+
435
+ context "when fips is enabled on system" do
436
+ let(:fips_enabled) { true }
437
+
438
+ it "returns true" do
439
+ expect(ChefConfig::Config[:fips]).to eq(true)
440
+ end
441
+ end
442
+ end
443
+
444
+ describe "ChefConfig::Config[:chef_server_root]" do
445
+ context "when chef_server_url isn't set manually" do
446
+ it "returns the default of 'https://localhost:443'" do
447
+ expect(ChefConfig::Config[:chef_server_root]).to eq("https://localhost:443")
448
+ end
449
+ end
450
+
451
+ context "when chef_server_url matches '../organizations/*' without a trailing slash" do
452
+ before do
453
+ ChefConfig::Config[:chef_server_url] = "https://example.com/organizations/myorg"
454
+ end
455
+ it "returns the full URL without /organizations/*" do
456
+ expect(ChefConfig::Config[:chef_server_root]).to eq("https://example.com")
457
+ end
458
+ end
459
+
460
+ context "when chef_server_url matches '../organizations/*' with a trailing slash" do
461
+ before do
462
+ ChefConfig::Config[:chef_server_url] = "https://example.com/organizations/myorg/"
463
+ end
464
+ it "returns the full URL without /organizations/*" do
465
+ expect(ChefConfig::Config[:chef_server_root]).to eq("https://example.com")
466
+ end
467
+ end
468
+
469
+ context "when chef_server_url matches '..organizations..' but not '../organizations/*'" do
470
+ before do
471
+ ChefConfig::Config[:chef_server_url] = "https://organizations.com/organizations"
472
+ end
473
+ it "returns the full URL without any modifications" do
474
+ expect(ChefConfig::Config[:chef_server_root]).to eq(ChefConfig::Config[:chef_server_url])
475
+ end
476
+ end
477
+
478
+ context "when chef_server_url is a standard URL without the string organization(s)" do
479
+ before do
480
+ ChefConfig::Config[:chef_server_url] = "https://example.com/some_other_string"
481
+ end
482
+ it "returns the full URL without any modifications" do
483
+ expect(ChefConfig::Config[:chef_server_root]).to eq(ChefConfig::Config[:chef_server_url])
484
+ end
485
+ end
486
+ end
487
+
488
+ describe "ChefConfig::Config[:cache_path]" do
489
+ let(:target_mode_host) { "fluffy.kittens.org" }
490
+ let(:target_mode_primary_cache_path) { ChefUtils.windows? ? "#{primary_cache_path}\\#{target_mode_host}" : "#{primary_cache_path}/#{target_mode_host}" }
491
+ let(:target_mode_secondary_cache_path) { ChefUtils.windows? ? "#{secondary_cache_path}\\#{target_mode_host}" : "#{secondary_cache_path}/#{target_mode_host}" }
492
+
493
+ before do
494
+ if is_windows
495
+ allow(File).to receive(:expand_path).and_return("#{system_drive}/Path/To/Executable")
496
+ end
497
+ end
498
+
499
+ context "when /var/chef exists and is accessible" do
500
+ before do
501
+ allow(ChefConfig::Config).to receive(:path_accessible?).with(ChefConfig::Config.var_chef_dir).and_return(true)
502
+ end
503
+
504
+ it "defaults to /var/chef" do
505
+ expect(ChefConfig::Config[:cache_path]).to eq(primary_cache_path)
506
+ end
507
+
508
+ context "and target mode is enabled" do
509
+ it "cache path includes the target host name" do
510
+ ChefConfig::Config.target_mode.enabled = true
511
+ ChefConfig::Config.target_mode.host = target_mode_host
512
+ expect(ChefConfig::Config[:cache_path]).to eq(target_mode_primary_cache_path)
513
+ end
514
+ end
515
+ end
516
+
517
+ context "when /var/chef does not exist and /var is accessible" do
518
+ it "defaults to /var/chef" do
519
+ allow(File).to receive(:exists?).with(ChefConfig::Config.var_chef_dir).and_return(false)
520
+ allow(ChefConfig::Config).to receive(:path_accessible?).with(ChefConfig::Config.var_root_dir).and_return(true)
521
+ expect(ChefConfig::Config[:cache_path]).to eq(primary_cache_path)
522
+ end
523
+ end
524
+
525
+ context "when /var/chef does not exist and /var is not accessible" do
526
+ it "defaults to $HOME/.chef" do
527
+ allow(File).to receive(:exists?).with(ChefConfig::Config.var_chef_dir).and_return(false)
528
+ allow(ChefConfig::Config).to receive(:path_accessible?).with(ChefConfig::Config.var_root_dir).and_return(false)
529
+ expect(ChefConfig::Config[:cache_path]).to eq(secondary_cache_path)
530
+ end
531
+ end
532
+
533
+ context "when /var/chef exists and is not accessible" do
534
+ before do
535
+ allow(File).to receive(:exists?).with(ChefConfig::Config.var_chef_dir).and_return(true)
536
+ allow(File).to receive(:readable?).with(ChefConfig::Config.var_chef_dir).and_return(true)
537
+ allow(File).to receive(:writable?).with(ChefConfig::Config.var_chef_dir).and_return(false)
538
+ end
539
+
540
+ it "defaults to $HOME/.chef" do
541
+ expect(ChefConfig::Config[:cache_path]).to eq(secondary_cache_path)
542
+ end
543
+
544
+ context "and target mode is enabled" do
545
+ it "cache path defaults to $HOME/.chef with the target host name" do
546
+ ChefConfig::Config.target_mode.enabled = true
547
+ ChefConfig::Config.target_mode.host = target_mode_host
548
+ expect(ChefConfig::Config[:cache_path]).to eq(target_mode_secondary_cache_path)
549
+ end
550
+ end
551
+ end
552
+
553
+ context "when chef is running in local mode" do
554
+ before do
555
+ ChefConfig::Config.local_mode = true
556
+ end
557
+
558
+ context "and config_dir is /a/b/c" do
559
+ before do
560
+ ChefConfig::Config.config_dir ChefConfig::PathHelper.cleanpath("/a/b/c")
561
+ end
562
+
563
+ it "cache_path is /a/b/c/local-mode-cache" do
564
+ expect(ChefConfig::Config.cache_path).to eq(ChefConfig::PathHelper.cleanpath("/a/b/c/local-mode-cache"))
565
+ end
566
+ end
567
+
568
+ context "and config_dir is /a/b/c/" do
569
+ before do
570
+ ChefConfig::Config.config_dir ChefConfig::PathHelper.cleanpath("/a/b/c/")
571
+ end
572
+
573
+ it "cache_path is /a/b/c/local-mode-cache" do
574
+ expect(ChefConfig::Config.cache_path).to eq(ChefConfig::PathHelper.cleanpath("/a/b/c/local-mode-cache"))
575
+ end
576
+ end
577
+ end
578
+ end
579
+
580
+ it "ChefConfig::Config[:stream_execute_output] defaults to false" do
581
+ expect(ChefConfig::Config[:stream_execute_output]).to eq(false)
582
+ end
583
+
584
+ it "ChefConfig::Config[:show_download_progress] defaults to false" do
585
+ expect(ChefConfig::Config[:show_download_progress]).to eq(false)
586
+ end
587
+
588
+ it "ChefConfig::Config[:download_progress_interval] defaults to every 10%" do
589
+ expect(ChefConfig::Config[:download_progress_interval]).to eq(10)
590
+ end
591
+
592
+ it "ChefConfig::Config[:file_backup_path] defaults to /var/chef/backup" do
593
+ allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
594
+ backup_path = is_windows ? "#{primary_cache_path}\\backup" : "#{primary_cache_path}/backup"
595
+ expect(ChefConfig::Config[:file_backup_path]).to eq(backup_path)
596
+ end
597
+
598
+ it "ChefConfig::Config[:ssl_verify_mode] defaults to :verify_peer" do
599
+ expect(ChefConfig::Config[:ssl_verify_mode]).to eq(:verify_peer)
600
+ end
601
+
602
+ it "ChefConfig::Config[:ssl_ca_path] defaults to nil" do
603
+ expect(ChefConfig::Config[:ssl_ca_path]).to be_nil
604
+ end
605
+
606
+ describe "ChefConfig::Config[:repo_mode]" do
607
+
608
+ context "when local mode is enabled" do
609
+
610
+ before { ChefConfig::Config[:local_mode] = true }
611
+
612
+ it "defaults to 'hosted_everything'" do
613
+ expect(ChefConfig::Config[:repo_mode]).to eq("hosted_everything")
614
+ end
615
+
616
+ context "and osc_compat is enabled" do
617
+
618
+ before { ChefConfig::Config.chef_zero.osc_compat = true }
619
+
620
+ it "defaults to 'everything'" do
621
+ expect(ChefConfig::Config[:repo_mode]).to eq("everything")
622
+ end
623
+ end
624
+ end
625
+
626
+ context "when local mode is not enabled" do
627
+
628
+ context "and the chef_server_url is multi-tenant" do
629
+
630
+ before { ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/example" }
631
+
632
+ it "defaults to 'hosted_everything'" do
633
+ expect(ChefConfig::Config[:repo_mode]).to eq("hosted_everything")
634
+ end
635
+
636
+ end
637
+
638
+ context "and the chef_server_url is not multi-tenant" do
639
+
640
+ before { ChefConfig::Config[:chef_server_url] = "https://chef.example/" }
641
+
642
+ it "defaults to 'everything'" do
643
+ expect(ChefConfig::Config[:repo_mode]).to eq("everything")
644
+ end
645
+ end
646
+ end
647
+ end
648
+
649
+ describe "ChefConfig::Config[:chef_repo_path]" do
650
+
651
+ context "when cookbook_path is set to a single path" do
652
+
653
+ before { ChefConfig::Config[:cookbook_path] = "/home/anne/repo/cookbooks" }
654
+
655
+ it "is set to a path one directory up from the cookbook_path" do
656
+ expected = File.expand_path("/home/anne/repo")
657
+ expect(ChefConfig::Config[:chef_repo_path]).to eq(expected)
658
+ end
659
+
660
+ end
661
+
662
+ context "when cookbook_path is set to multiple paths" do
663
+
664
+ before do
665
+ ChefConfig::Config[:cookbook_path] = [
666
+ "/home/anne/repo/cookbooks",
667
+ "/home/anne/other_repo/cookbooks",
668
+ ]
669
+ end
670
+
671
+ it "is set to an Array of paths one directory up from the cookbook_paths" do
672
+ expected = [ "/home/anne/repo", "/home/anne/other_repo"].map { |p| File.expand_path(p) }
673
+ expect(ChefConfig::Config[:chef_repo_path]).to eq(expected)
674
+ end
675
+
676
+ end
677
+
678
+ context "when cookbook_path is not set but cookbook_artifact_path is set" do
679
+
680
+ before do
681
+ ChefConfig::Config[:cookbook_path] = nil
682
+ ChefConfig::Config[:cookbook_artifact_path] = "/home/roxie/repo/cookbook_artifacts"
683
+ end
684
+
685
+ it "is set to a path one directory up from the cookbook_artifact_path" do
686
+ expected = File.expand_path("/home/roxie/repo")
687
+ expect(ChefConfig::Config[:chef_repo_path]).to eq(expected)
688
+ end
689
+
690
+ end
691
+
692
+ context "when cookbook_path is not set" do
693
+
694
+ before { ChefConfig::Config[:cookbook_path] = nil }
695
+
696
+ it "is set to the cache_path" do
697
+ expect(ChefConfig::Config[:chef_repo_path]).to eq(ChefConfig::Config[:cache_path])
698
+ end
699
+
700
+ end
701
+
702
+ end
703
+
704
+ # On Windows, we'll detect an omnibus build and set this to the
705
+ # cacert.pem included in the package, but it's nil if you're on Windows
706
+ # w/o omnibus (e.g., doing development on Windows, custom build, etc.)
707
+ unless is_windows
708
+ it "ChefConfig::Config[:ssl_ca_file] defaults to nil" do
709
+ expect(ChefConfig::Config[:ssl_ca_file]).to be_nil
710
+ end
711
+ end
712
+
713
+ it "ChefConfig::Config[:data_bag_path] defaults to /var/chef/data_bags" do
714
+ allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
715
+ data_bag_path = is_windows ? "#{primary_cache_path}\\data_bags" : "#{primary_cache_path}/data_bags"
716
+ expect(ChefConfig::Config[:data_bag_path]).to eq(data_bag_path)
717
+ end
718
+
719
+ it "ChefConfig::Config[:environment_path] defaults to /var/chef/environments" do
720
+ allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
721
+ environment_path = is_windows ? "#{primary_cache_path}\\environments" : "#{primary_cache_path}/environments"
722
+ expect(ChefConfig::Config[:environment_path]).to eq(environment_path)
723
+ end
724
+
725
+ it "ChefConfig::Config[:cookbook_artifact_path] defaults to /var/chef/cookbook_artifacts" do
726
+ allow(ChefConfig::Config).to receive(:cache_path).and_return(primary_cache_path)
727
+ environment_path = is_windows ? "#{primary_cache_path}\\cookbook_artifacts" : "#{primary_cache_path}/cookbook_artifacts"
728
+ expect(ChefConfig::Config[:cookbook_artifact_path]).to eq(environment_path)
729
+ end
730
+
731
+ describe "setting the config dir" do
732
+
733
+ context "when the config file is given with a relative path" do
734
+
735
+ before do
736
+ ChefConfig::Config.config_file = "client.rb"
737
+ end
738
+
739
+ it "expands the path when determining config_dir" do
740
+ # config_dir goes through ChefConfig::PathHelper.canonical_path, which
741
+ # downcases on windows because the FS is case insensitive, so we
742
+ # have to downcase expected and actual to make the tests work.
743
+ expect(ChefConfig::Config.config_dir.downcase).to eq(ChefConfig::PathHelper.cleanpath(Dir.pwd).downcase)
744
+ end
745
+
746
+ it "does not set derived paths at FS root" do
747
+ ChefConfig::Config.local_mode = true
748
+ expect(ChefConfig::Config.cache_path.downcase).to eq(ChefConfig::PathHelper.cleanpath(File.join(Dir.pwd, "local-mode-cache")).downcase)
749
+ end
750
+
751
+ end
752
+
753
+ context "when the config file is /etc/chef/client.rb" do
754
+
755
+ before do
756
+ config_location = ChefConfig::PathHelper.cleanpath(ChefConfig::PathHelper.join(ChefConfig::Config.etc_chef_dir, "client.rb")).downcase
757
+ allow(File).to receive(:absolute_path).with(config_location).and_return(config_location)
758
+ ChefConfig::Config.config_file = config_location
759
+ end
760
+
761
+ it "config_dir is /etc/chef" do
762
+ expect(ChefConfig::Config.config_dir).to eq(ChefConfig::Config.etc_chef_dir.downcase)
763
+ end
764
+
765
+ context "and chef is running in local mode" do
766
+ before do
767
+ ChefConfig::Config.local_mode = true
768
+ end
769
+
770
+ it "config_dir is /etc/chef" do
771
+ expect(ChefConfig::Config.config_dir).to eq(ChefConfig::Config.etc_chef_dir.downcase)
772
+ end
773
+ end
774
+
775
+ context "when config_dir is set to /other/config/dir/" do
776
+ before do
777
+ ChefConfig::Config.config_dir = ChefConfig::PathHelper.cleanpath("/other/config/dir/")
778
+ end
779
+
780
+ it "yields the explicit value" do
781
+ expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.cleanpath("/other/config/dir/"))
782
+ end
783
+ end
784
+
785
+ end
786
+
787
+ context "when the user's home dir is /home/charlie/" do
788
+ before do
789
+ ChefConfig::Config.user_home = "/home/charlie/"
790
+ end
791
+
792
+ it "config_dir is /home/charlie/.chef/" do
793
+ expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
794
+ end
795
+
796
+ context "and chef is running in local mode" do
797
+ before do
798
+ ChefConfig::Config.local_mode = true
799
+ end
800
+
801
+ it "config_dir is /home/charlie/.chef/" do
802
+ expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
803
+ end
804
+ end
805
+ end
806
+
807
+ if is_windows
808
+ context "when the user's home dir is windows specific" do
809
+ before do
810
+ ChefConfig::Config.user_home = ChefConfig::PathHelper.cleanpath("/home/charlie/")
811
+ end
812
+
813
+ it "config_dir is with backslashes" do
814
+ expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
815
+ end
816
+
817
+ context "and chef is running in local mode" do
818
+ before do
819
+ ChefConfig::Config.local_mode = true
820
+ end
821
+
822
+ it "config_dir is with backslashes" do
823
+ expect(ChefConfig::Config.config_dir).to eq(ChefConfig::PathHelper.join(ChefConfig::PathHelper.cleanpath("/home/charlie/"), ".chef", ""))
824
+ end
825
+ end
826
+ end
827
+
828
+ end
829
+
830
+ end
831
+
832
+ if is_windows
833
+ describe "finding the windows embedded dir" do
834
+ let(:default_config_location) { "c:/opscode/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/config.rb" }
835
+ let(:alternate_install_location) { "c:/my/alternate/install/place/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/config.rb" }
836
+ let(:non_omnibus_location) { "c:/my/dev/stuff/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/config.rb" }
837
+
838
+ let(:default_ca_file) { "c:/opscode/chef/embedded/ssl/certs/cacert.pem" }
839
+
840
+ it "finds the embedded dir in the default location" do
841
+ allow(ChefConfig::Config).to receive(:_this_file).and_return(default_config_location)
842
+ expect(ChefConfig::Config.embedded_dir).to eq("c:/opscode/chef/embedded")
843
+ end
844
+
845
+ it "finds the embedded dir in a custom install location" do
846
+ allow(ChefConfig::Config).to receive(:_this_file).and_return(alternate_install_location)
847
+ expect(ChefConfig::Config.embedded_dir).to eq("c:/my/alternate/install/place/chef/embedded")
848
+ end
849
+
850
+ it "doesn't error when not in an omnibus install" do
851
+ allow(ChefConfig::Config).to receive(:_this_file).and_return(non_omnibus_location)
852
+ expect(ChefConfig::Config.embedded_dir).to be_nil
853
+ end
854
+
855
+ it "sets the ssl_ca_cert path if the cert file is available" do
856
+ allow(ChefConfig::Config).to receive(:_this_file).and_return(default_config_location)
857
+ allow(File).to receive(:exist?).with(default_ca_file).and_return(true)
858
+ expect(ChefConfig::Config.ssl_ca_file).to eq(default_ca_file)
859
+ end
860
+ end
861
+ end
862
+ end
863
+
864
+ describe "ChefConfig::Config[:user_home]" do
865
+ it "should set when HOME is provided" do
866
+ expected = ChefConfig::PathHelper.cleanpath("/home/kitten")
867
+ allow(ChefConfig::PathHelper).to receive(:home).and_return(expected)
868
+ expect(ChefConfig::Config[:user_home]).to eq(expected)
869
+ end
870
+
871
+ it "falls back to the current working directory when HOME and USERPROFILE is not set" do
872
+ allow(ChefConfig::PathHelper).to receive(:home).and_return(nil)
873
+ expect(ChefConfig::Config[:user_home]).to eq(Dir.pwd)
874
+ end
875
+ end
876
+
877
+ describe "ChefConfig::Config[:encrypted_data_bag_secret]" do
878
+ let(:db_secret_default_path) { ChefConfig::PathHelper.cleanpath("#{ChefConfig::Config.etc_chef_dir}/encrypted_data_bag_secret") }
879
+
880
+ before do
881
+ allow(File).to receive(:exist?).with(db_secret_default_path).and_return(secret_exists)
882
+ end
883
+
884
+ context "/etc/chef/encrypted_data_bag_secret exists" do
885
+ let(:secret_exists) { true }
886
+ it "sets the value to /etc/chef/encrypted_data_bag_secret" do
887
+ expect(ChefConfig::Config[:encrypted_data_bag_secret]).to eq db_secret_default_path
888
+ end
889
+ end
890
+
891
+ context "/etc/chef/encrypted_data_bag_secret does not exist" do
892
+ let(:secret_exists) { false }
893
+ it "sets the value to nil" do
894
+ expect(ChefConfig::Config[:encrypted_data_bag_secret]).to be_nil
895
+ end
896
+ end
897
+ end
898
+
899
+ describe "ChefConfig::Config[:event_handlers]" do
900
+ it "sets a event_handlers to an empty array by default" do
901
+ expect(ChefConfig::Config[:event_handlers]).to eq([])
902
+ end
903
+ it "should be able to add custom handlers" do
904
+ o = Object.new
905
+ ChefConfig::Config[:event_handlers] << o
906
+ expect(ChefConfig::Config[:event_handlers]).to be_include(o)
907
+ end
908
+ end
909
+
910
+ describe "ChefConfig::Config[:user_valid_regex]" do
911
+ context "on a platform that is not Windows" do
912
+ it "allows one letter usernames" do
913
+ any_match = ChefConfig::Config[:user_valid_regex].any? { |regex| regex.match("a") }
914
+ expect(any_match).to be_truthy
915
+ end
916
+ end
917
+ end
918
+
919
+ describe "ChefConfig::Config[:internal_locale]" do
920
+ let(:shell_out) do
921
+ cmd = instance_double("Mixlib::ShellOut", exitstatus: 0, stdout: locales, error!: nil)
922
+ allow(cmd).to receive(:run_command).and_return(cmd)
923
+ cmd
924
+ end
925
+
926
+ let(:locales) { locale_array.join("\n") }
927
+
928
+ before do
929
+ allow(Mixlib::ShellOut).to receive(:new).with("locale -a").and_return(shell_out)
930
+ end
931
+
932
+ shared_examples_for "a suitable locale" do
933
+ it "returns an English UTF-8 locale" do
934
+ expect(ChefConfig.logger).to_not receive(:warn).with(/Please install an English UTF-8 locale for Chef Infra Client to use/)
935
+ expect(ChefConfig.logger).to_not receive(:trace).with(/Defaulting to locale en_US.UTF-8 on Windows/)
936
+ expect(ChefConfig.logger).to_not receive(:trace).with(/No usable locale -a command found/)
937
+ expect(ChefConfig::Config.guess_internal_locale).to eq expected_locale
938
+ end
939
+ end
940
+
941
+ context "when the result includes 'C.UTF-8'" do
942
+ include_examples "a suitable locale" do
943
+ let(:locale_array) { [expected_locale, "en_US.UTF-8"] }
944
+ let(:expected_locale) { "C.UTF-8" }
945
+ end
946
+ end
947
+
948
+ context "when the result includes 'en_US.UTF-8'" do
949
+ include_examples "a suitable locale" do
950
+ let(:locale_array) { ["en_CA.UTF-8", expected_locale, "en_NZ.UTF-8"] }
951
+ let(:expected_locale) { "en_US.UTF-8" }
952
+ end
953
+ end
954
+
955
+ context "when the result includes 'en_US.utf8'" do
956
+ include_examples "a suitable locale" do
957
+ let(:locale_array) { ["en_CA.utf8", "en_US.utf8", "en_NZ.utf8"] }
958
+ let(:expected_locale) { "en_US.UTF-8" }
959
+ end
960
+ end
961
+
962
+ context "when the result includes 'en.UTF-8'" do
963
+ include_examples "a suitable locale" do
964
+ let(:locale_array) { ["en.ISO8859-1", expected_locale] }
965
+ let(:expected_locale) { "en.UTF-8" }
966
+ end
967
+ end
968
+
969
+ context "when the result includes 'en_*.UTF-8'" do
970
+ include_examples "a suitable locale" do
971
+ let(:locale_array) { [expected_locale, "en_CA.UTF-8", "en_GB.UTF-8"] }
972
+ let(:expected_locale) { "en_AU.UTF-8" }
973
+ end
974
+ end
975
+
976
+ context "when the result includes 'en_*.utf8'" do
977
+ include_examples "a suitable locale" do
978
+ let(:locale_array) { ["en_AU.utf8", "en_CA.utf8", "en_GB.utf8"] }
979
+ let(:expected_locale) { "en_AU.UTF-8" }
980
+ end
981
+ end
982
+
983
+ context "when the result does not include 'en_*.UTF-8'" do
984
+ let(:locale_array) { ["af_ZA", "af_ZA.ISO8859-1", "af_ZA.ISO8859-15", "af_ZA.UTF-8"] }
985
+
986
+ it "should fall back to C locale" do
987
+ expect(ChefConfig.logger).to receive(:warn).with("Please install an English UTF-8 locale for Chef Infra Client to use, falling back to C locale and disabling UTF-8 support.")
988
+ expect(ChefConfig::Config.guess_internal_locale).to eq "C"
989
+ end
990
+ end
991
+
992
+ context "on error" do
993
+ let(:locale_array) { [] }
994
+
995
+ let(:shell_out_cmd) { instance_double("Mixlib::ShellOut") }
996
+
997
+ before do
998
+ allow(Mixlib::ShellOut).to receive(:new).and_return(shell_out_cmd)
999
+ allow(shell_out_cmd).to receive(:run_command)
1000
+ allow(shell_out_cmd).to receive(:error!).and_raise(Mixlib::ShellOut::ShellCommandFailed, "this is an error")
1001
+ end
1002
+
1003
+ it "should default to 'en_US.UTF-8'" do
1004
+ if is_windows
1005
+ expect(ChefConfig.logger).to receive(:trace).with("Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else.")
1006
+ else
1007
+ expect(ChefConfig.logger).to receive(:trace).with("No usable locale -a command found, assuming you have en_US.UTF-8 installed.")
1008
+ end
1009
+ expect(ChefConfig::Config.guess_internal_locale).to eq "en_US.UTF-8"
1010
+ end
1011
+ end
1012
+ end
1013
+ end
1014
+ end
1015
+
1016
+ describe "export_proxies" do
1017
+ before(:all) do
1018
+ @original_env = ENV.to_hash
1019
+ ENV["http_proxy"] = nil
1020
+ ENV["HTTP_PROXY"] = nil
1021
+ ENV["https_proxy"] = nil
1022
+ ENV["HTTPS_PROXY"] = nil
1023
+ ENV["ftp_proxy"] = nil
1024
+ ENV["FTP_PROXY"] = nil
1025
+ ENV["no_proxy"] = nil
1026
+ ENV["NO_PROXY"] = nil
1027
+ end
1028
+
1029
+ after(:all) do
1030
+ ENV.clear
1031
+ ENV.update(@original_env)
1032
+ end
1033
+
1034
+ let(:http_proxy) { "http://localhost:7979" }
1035
+ let(:https_proxy) { "https://localhost:7979" }
1036
+ let(:ftp_proxy) { "ftp://localhost:7979" }
1037
+ let(:proxy_user) { "http_user" }
1038
+ let(:proxy_pass) { "http_pass" }
1039
+
1040
+ context "when http_proxy, proxy_pass and proxy_user are set" do
1041
+ before do
1042
+ ChefConfig::Config.http_proxy = http_proxy
1043
+ ChefConfig::Config.http_proxy_user = proxy_user
1044
+ ChefConfig::Config.http_proxy_pass = proxy_pass
1045
+ end
1046
+ it "exports ENV['http_proxy']" do
1047
+ expect(ENV).to receive(:[]=).with("http_proxy", "http://http_user:http_pass@localhost:7979")
1048
+ expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://http_user:http_pass@localhost:7979")
1049
+ ChefConfig::Config.export_proxies
1050
+ end
1051
+ end
1052
+
1053
+ context "when https_proxy, proxy_pass and proxy_user are set" do
1054
+ before do
1055
+ ChefConfig::Config.https_proxy = https_proxy
1056
+ ChefConfig::Config.https_proxy_user = proxy_user
1057
+ ChefConfig::Config.https_proxy_pass = proxy_pass
1058
+ end
1059
+ it "exports ENV['https_proxy']" do
1060
+ expect(ENV).to receive(:[]=).with("https_proxy", "https://http_user:http_pass@localhost:7979")
1061
+ expect(ENV).to receive(:[]=).with("HTTPS_PROXY", "https://http_user:http_pass@localhost:7979")
1062
+ ChefConfig::Config.export_proxies
1063
+ end
1064
+ end
1065
+
1066
+ context "when ftp_proxy, proxy_pass and proxy_user are set" do
1067
+ before do
1068
+ ChefConfig::Config.ftp_proxy = ftp_proxy
1069
+ ChefConfig::Config.ftp_proxy_user = proxy_user
1070
+ ChefConfig::Config.ftp_proxy_pass = proxy_pass
1071
+ end
1072
+ it "exports ENV['ftp_proxy']" do
1073
+ expect(ENV).to receive(:[]=).with("ftp_proxy", "ftp://http_user:http_pass@localhost:7979")
1074
+ expect(ENV).to receive(:[]=).with("FTP_PROXY", "ftp://http_user:http_pass@localhost:7979")
1075
+ ChefConfig::Config.export_proxies
1076
+ end
1077
+ end
1078
+
1079
+ shared_examples "no user pass" do
1080
+ it "does not populate the user or password" do
1081
+ expect(ENV).to receive(:[]=).with("http_proxy", "http://localhost:7979")
1082
+ expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://localhost:7979")
1083
+ ChefConfig::Config.export_proxies
1084
+ end
1085
+ end
1086
+
1087
+ context "when proxy_pass and proxy_user are passed as empty strings" do
1088
+ before do
1089
+ ChefConfig::Config.http_proxy = http_proxy
1090
+ ChefConfig::Config.http_proxy_user = ""
1091
+ ChefConfig::Config.http_proxy_pass = proxy_pass
1092
+ end
1093
+ include_examples "no user pass"
1094
+ end
1095
+
1096
+ context "when proxy_pass and proxy_user are not provided" do
1097
+ before do
1098
+ ChefConfig::Config.http_proxy = http_proxy
1099
+ end
1100
+ include_examples "no user pass"
1101
+ end
1102
+
1103
+ context "when the proxy is provided without a scheme" do
1104
+ before do
1105
+ ChefConfig::Config.http_proxy = "localhost:1111"
1106
+ end
1107
+ it "automatically adds the scheme to the proxy url" do
1108
+ expect(ENV).to receive(:[]=).with("http_proxy", "http://localhost:1111")
1109
+ expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://localhost:1111")
1110
+ ChefConfig::Config.export_proxies
1111
+ end
1112
+ end
1113
+
1114
+ shared_examples "no export" do
1115
+ it "does not export any proxy settings" do
1116
+ ChefConfig::Config.export_proxies
1117
+ expect(ENV["http_proxy"]).to eq(nil)
1118
+ expect(ENV["https_proxy"]).to eq(nil)
1119
+ expect(ENV["ftp_proxy"]).to eq(nil)
1120
+ expect(ENV["no_proxy"]).to eq(nil)
1121
+ end
1122
+ end
1123
+
1124
+ context "when nothing is set" do
1125
+ include_examples "no export"
1126
+ end
1127
+
1128
+ context "when all the users and passwords are set but no proxies are set" do
1129
+ before do
1130
+ ChefConfig::Config.http_proxy_user = proxy_user
1131
+ ChefConfig::Config.http_proxy_pass = proxy_pass
1132
+ ChefConfig::Config.https_proxy_user = proxy_user
1133
+ ChefConfig::Config.https_proxy_pass = proxy_pass
1134
+ ChefConfig::Config.ftp_proxy_user = proxy_user
1135
+ ChefConfig::Config.ftp_proxy_pass = proxy_pass
1136
+ end
1137
+ include_examples "no export"
1138
+ end
1139
+
1140
+ context "no_proxy is set" do
1141
+ before do
1142
+ ChefConfig::Config.no_proxy = "localhost"
1143
+ end
1144
+ it "exports ENV['no_proxy']" do
1145
+ expect(ENV).to receive(:[]=).with("no_proxy", "localhost")
1146
+ expect(ENV).to receive(:[]=).with("NO_PROXY", "localhost")
1147
+ ChefConfig::Config.export_proxies
1148
+ end
1149
+ end
1150
+ end
1151
+
1152
+ describe "proxy_uri" do
1153
+ subject(:proxy_uri) { described_class.proxy_uri(scheme, host, port) }
1154
+ let(:env) { {} }
1155
+ let(:scheme) { "http" }
1156
+ let(:host) { "test.example.com" }
1157
+ let(:port) { 8080 }
1158
+ let(:proxy) { "#{proxy_prefix}#{proxy_host}:#{proxy_port}" }
1159
+ let(:proxy_prefix) { "http://" }
1160
+ let(:proxy_host) { "proxy.mycorp.com" }
1161
+ let(:proxy_port) { 8080 }
1162
+
1163
+ before do
1164
+ stub_const("ENV", env)
1165
+ end
1166
+
1167
+ shared_examples_for "a proxy uri" do
1168
+ it "contains the host" do
1169
+ expect(proxy_uri.host).to eq(proxy_host)
1170
+ end
1171
+
1172
+ it "contains the port" do
1173
+ expect(proxy_uri.port).to eq(proxy_port)
1174
+ end
1175
+ end
1176
+
1177
+ context "when the config setting is normalized (does not contain the scheme)" do
1178
+ include_examples "a proxy uri" do
1179
+
1180
+ let(:proxy_prefix) { "" }
1181
+
1182
+ let(:env) do
1183
+ {
1184
+ "#{scheme}_proxy" => proxy,
1185
+ "no_proxy" => nil,
1186
+ }
1187
+ end
1188
+ end
1189
+ end
1190
+
1191
+ context "when the proxy is set by the environment" do
1192
+ include_examples "a proxy uri" do
1193
+ let(:scheme) { "https" }
1194
+ let(:env) do
1195
+ {
1196
+ "https_proxy" => "https://jane_username:opensesame@proxy.mycorp.com:8080",
1197
+ }
1198
+ end
1199
+ end
1200
+ end
1201
+
1202
+ context "when an empty proxy is set by the environment" do
1203
+ let(:env) do
1204
+ {
1205
+ "https_proxy" => "",
1206
+ }
1207
+ end
1208
+
1209
+ it "does not fail with URI parse exception" do
1210
+ expect { proxy_uri }.to_not raise_error
1211
+ end
1212
+ end
1213
+
1214
+ context "when no_proxy is set" do
1215
+ context "when no_proxy is the exact host" do
1216
+ let(:env) do
1217
+ {
1218
+ "http_proxy" => proxy,
1219
+ "no_proxy" => host,
1220
+ }
1221
+ end
1222
+
1223
+ it { is_expected.to eq nil }
1224
+ end
1225
+
1226
+ context "when no_proxy includes the same domain with a wildcard" do
1227
+ let(:env) do
1228
+ {
1229
+ "http_proxy" => proxy,
1230
+ "no_proxy" => "*.example.com",
1231
+ }
1232
+ end
1233
+
1234
+ it { is_expected.to eq nil }
1235
+ end
1236
+
1237
+ context "when no_proxy is included on a list" do
1238
+ let(:env) do
1239
+ {
1240
+ "http_proxy" => proxy,
1241
+ "no_proxy" => "chef.io,getchef.com,opscode.com,test.example.com",
1242
+ }
1243
+ end
1244
+
1245
+ it { is_expected.to eq nil }
1246
+ end
1247
+
1248
+ context "when no_proxy is included on a list with wildcards" do
1249
+ let(:env) do
1250
+ {
1251
+ "http_proxy" => proxy,
1252
+ "no_proxy" => "10.*,*.example.com",
1253
+ }
1254
+ end
1255
+
1256
+ it { is_expected.to eq nil }
1257
+ end
1258
+
1259
+ context "when no_proxy is a domain with a dot prefix" do
1260
+ let(:env) do
1261
+ {
1262
+ "http_proxy" => proxy,
1263
+ "no_proxy" => ".example.com",
1264
+ }
1265
+ end
1266
+
1267
+ it { is_expected.to eq nil }
1268
+ end
1269
+
1270
+ context "when no_proxy is a domain with no wildcard" do
1271
+ let(:env) do
1272
+ {
1273
+ "http_proxy" => proxy,
1274
+ "no_proxy" => "example.com",
1275
+ }
1276
+ end
1277
+
1278
+ it { is_expected.to eq nil }
1279
+ end
1280
+ end
1281
+ end
1282
+
1283
+ describe "allowing chefdk configuration outside of chefdk" do
1284
+
1285
+ it "allows arbitrary settings in the chefdk config context" do
1286
+ expect { ChefConfig::Config.chefdk.generator_cookbook("/path") }.to_not raise_error
1287
+ end
1288
+
1289
+ end
1290
+
1291
+ describe "Treating deprecation warnings as errors" do
1292
+
1293
+ context "when using our default RSpec configuration" do
1294
+
1295
+ it "defaults to treating deprecation warnings as errors" do
1296
+ expect(ChefConfig::Config[:treat_deprecation_warnings_as_errors]).to be(true)
1297
+ end
1298
+
1299
+ it "sets CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS environment variable" do
1300
+ expect(ENV["CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS"]).to eq("1")
1301
+ end
1302
+
1303
+ it "treats deprecation warnings as errors in child processes when testing" do
1304
+ # Doing a full integration test where we launch a child process is slow
1305
+ # and liable to break for weird reasons (bundler env stuff, etc.), so
1306
+ # we're just checking that the presence of the environment variable
1307
+ # causes treat_deprecation_warnings_as_errors to be set to true after a
1308
+ # config reset.
1309
+ ChefConfig::Config.reset
1310
+ expect(ChefConfig::Config[:treat_deprecation_warnings_as_errors]).to be(true)
1311
+ end
1312
+
1313
+ end
1314
+
1315
+ context "outside of our test environment" do
1316
+
1317
+ before do
1318
+ ENV.delete("CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS")
1319
+ ChefConfig::Config.reset
1320
+ end
1321
+
1322
+ it "defaults to NOT treating deprecation warnings as errors" do
1323
+ expect(ChefConfig::Config[:treat_deprecation_warnings_as_errors]).to be(false)
1324
+ end
1325
+ end
1326
+
1327
+ end
1328
+
1329
+ describe "data collector URL" do
1330
+
1331
+ context "when using default settings" do
1332
+
1333
+ context "for Chef Client" do
1334
+
1335
+ it "configures the data collector URL as a relative path to the Chef Server URL" do
1336
+ ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg"
1337
+ expect(ChefConfig::Config[:data_collector][:server_url]).to eq("https://chef.example/organizations/myorg/data-collector")
1338
+ end
1339
+
1340
+ end
1341
+
1342
+ context "for Chef Solo legacy mode" do
1343
+
1344
+ before do
1345
+ ChefConfig::Config[:solo_legacy_mode] = true
1346
+ end
1347
+
1348
+ it "sets the data collector server URL to nil" do
1349
+ ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg"
1350
+ expect(ChefConfig::Config[:data_collector][:server_url]).to be_nil
1351
+ end
1352
+
1353
+ end
1354
+
1355
+ context "for local mode" do
1356
+
1357
+ before do
1358
+ ChefConfig::Config[:local_mode] = true
1359
+ end
1360
+
1361
+ it "sets the data collector server URL to nil" do
1362
+ ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg"
1363
+ expect(ChefConfig::Config[:data_collector][:server_url]).to be_nil
1364
+ end
1365
+
1366
+ end
1367
+
1368
+ end
1369
+
1370
+ end
1371
+
1372
+ describe "validation_client_name" do
1373
+ context "with a normal server URL" do
1374
+ before { ChefConfig::Config[:chef_server_url] = "https://chef.example/organizations/myorg" }
1375
+
1376
+ it "sets the validation client to myorg-validator" do
1377
+ expect(ChefConfig::Config[:validation_client_name]).to eq "myorg-validator"
1378
+ end
1379
+ end
1380
+
1381
+ context "with an unusual server URL" do
1382
+ before { ChefConfig::Config[:chef_server_url] = "https://chef.example/myorg" }
1383
+
1384
+ it "sets the validation client to chef-validator" do
1385
+ expect(ChefConfig::Config[:validation_client_name]).to eq "chef-validator"
1386
+ end
1387
+ end
1388
+ end
1389
+
1390
+ end