chef-config 17.10.26 → 18.0.169

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