chef-config 17.10.29 → 18.0.169

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