chef-config 17.10.26 → 17.10.68

Sign up to get free protection for your applications and to get access to all the features.
@@ -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