chef-config 18.2.5 → 18.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1399 +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
- 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
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(:exist?).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(:exist?).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(:exist?).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