chef-config 14.0.202 → 14.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,510 +1,510 @@
1
- #
2
- # Author:: Daniel DeLeo (<dan@chef.io>)
3
- # Copyright:: Copyright 2014-2016, Chef Software, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require "spec_helper"
20
- require "tempfile"
21
-
22
- require "chef-config/exceptions"
23
- require "chef-config/windows"
24
- require "chef-config/workstation_config_loader"
25
-
26
- RSpec.describe ChefConfig::WorkstationConfigLoader do
27
-
28
- let(:explicit_config_location) { nil }
29
-
30
- let(:env) { {} }
31
-
32
- let(:config_loader) do
33
- described_class.new(explicit_config_location).tap do |c|
34
- allow(c).to receive(:env).and_return(env)
35
- end
36
- end
37
-
38
- before do
39
- # We set this to nil so that a dev workstation will
40
- # not interfere with the tests.
41
- ChefConfig::Config.reset
42
- ChefConfig::Config[:config_d_dir] = nil
43
- end
44
-
45
- # Test methods that do I/O or reference external state which are stubbed out
46
- # elsewhere.
47
- describe "external dependencies" do
48
- let(:config_loader) { described_class.new(nil) }
49
-
50
- it "delegates to ENV for env" do
51
- expect(config_loader.env).to equal(ENV)
52
- end
53
-
54
- it "tests a path's existence" do
55
- expect(config_loader.path_exists?("/nope/nope/nope/nope/frab/jab/nab")).to be(false)
56
- expect(config_loader.path_exists?(__FILE__)).to be(true)
57
- end
58
-
59
- end
60
-
61
- describe "locating the config file" do
62
- context "without an explicit config" do
63
-
64
- before do
65
- allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
66
- end
67
-
68
- it "has no config if HOME is not set" do
69
- expect(config_loader.config_location).to be(nil)
70
- expect(config_loader.no_config_found?).to be(true)
71
- end
72
-
73
- context "when HOME is set and contains a knife.rb" do
74
-
75
- let(:home) { "/Users/example.user" }
76
-
77
- before do
78
- allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_yield(File.join(home, ".chef"))
79
- allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/knife.rb").and_return(true)
80
- end
81
-
82
- it "uses the config in HOME/.chef/knife.rb" do
83
- expect(config_loader.config_location).to eq("#{home}/.chef/knife.rb")
84
- end
85
-
86
- context "and has a config.rb" do
87
-
88
- before do
89
- allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/config.rb").and_return(true)
90
- end
91
-
92
- it "uses the config in HOME/.chef/config.rb" do
93
- expect(config_loader.config_location).to eq("#{home}/.chef/config.rb")
94
- end
95
-
96
- context "and/or a parent dir contains a .chef dir" do
97
-
98
- let(:env_pwd) { "/path/to/cwd" }
99
-
100
- before do
101
- if ChefConfig.windows?
102
- env["CD"] = env_pwd
103
- else
104
- env["PWD"] = env_pwd
105
- end
106
-
107
- allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/knife.rb").and_return(true)
108
- allow(File).to receive(:exist?).with("#{env_pwd}/.chef").and_return(true)
109
- allow(File).to receive(:directory?).with("#{env_pwd}/.chef").and_return(true)
110
- end
111
-
112
- it "prefers the config from parent_dir/.chef" do
113
- expect(config_loader.config_location).to eq("#{env_pwd}/.chef/knife.rb")
114
- end
115
-
116
- context "and the parent dir's .chef dir has a config.rb" do
117
-
118
- before do
119
- allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/config.rb").and_return(true)
120
- end
121
-
122
- it "prefers the config from parent_dir/.chef" do
123
- expect(config_loader.config_location).to eq("#{env_pwd}/.chef/config.rb")
124
- end
125
-
126
- context "and/or the current working directory contains a .chef dir" do
127
-
128
- let(:cwd) { Dir.pwd }
129
-
130
- before do
131
- allow(config_loader).to receive(:path_exists?).with("#{cwd}/knife.rb").and_return(true)
132
- end
133
-
134
- it "prefers a knife.rb located in the cwd" do
135
- expect(config_loader.config_location).to eq("#{cwd}/knife.rb")
136
- end
137
-
138
- context "and the CWD's .chef dir has a config.rb" do
139
-
140
- before do
141
- allow(config_loader).to receive(:path_exists?).with("#{cwd}/config.rb").and_return(true)
142
- end
143
-
144
- it "prefers a config located in the cwd" do
145
- expect(config_loader.config_location).to eq("#{cwd}/config.rb")
146
- end
147
-
148
- context "and/or KNIFE_HOME is set" do
149
-
150
- let(:knife_home) { "/path/to/knife/home" }
151
-
152
- before do
153
- env["KNIFE_HOME"] = knife_home
154
- allow(config_loader).to receive(:path_exists?).with("#{knife_home}/knife.rb").and_return(true)
155
- end
156
-
157
- it "prefers a knife located in KNIFE_HOME" do
158
- expect(config_loader.config_location).to eq("/path/to/knife/home/knife.rb")
159
- end
160
-
161
- context "and KNIFE_HOME contains a config.rb" do
162
-
163
- before do
164
- env["KNIFE_HOME"] = knife_home
165
- allow(config_loader).to receive(:path_exists?).with("#{knife_home}/config.rb").and_return(true)
166
- end
167
-
168
- it "prefers a config.rb located in KNIFE_HOME" do
169
- expect(config_loader.config_location).to eq("/path/to/knife/home/config.rb")
170
- end
171
-
172
- end
173
-
174
- end
175
- end
176
- end
177
- end
178
- end
179
- end
180
- end
181
-
182
- context "when the current working dir is inside a symlinked directory" do
183
- before do
184
- # pwd according to your shell is /home/someuser/prod/chef-repo, but
185
- # chef-repo is a symlink to /home/someuser/codes/chef-repo
186
- env["CD"] = "/home/someuser/prod/chef-repo" # windows
187
- env["PWD"] = "/home/someuser/prod/chef-repo" # unix
188
-
189
- allow(Dir).to receive(:pwd).and_return("/home/someuser/codes/chef-repo")
190
- end
191
-
192
- it "loads the config from the non-dereferenced directory path" do
193
- expect(File).to receive(:exist?).with("/home/someuser/prod/chef-repo/.chef").and_return(false)
194
- expect(File).to receive(:exist?).with("/home/someuser/prod/.chef").and_return(true)
195
- expect(File).to receive(:directory?).with("/home/someuser/prod/.chef").and_return(true)
196
-
197
- expect(config_loader).to receive(:path_exists?).with("/home/someuser/prod/.chef/knife.rb").and_return(true)
198
-
199
- expect(config_loader.config_location).to eq("/home/someuser/prod/.chef/knife.rb")
200
- end
201
- end
202
- end
203
-
204
- context "when given an explicit config to load" do
205
-
206
- let(:explicit_config_location) { "/path/to/explicit/config.rb" }
207
-
208
- it "prefers the explicit config" do
209
- expect(config_loader.config_location).to eq(explicit_config_location)
210
- end
211
-
212
- end
213
- end
214
-
215
- describe "loading the config file" do
216
-
217
- context "when no explicit config is specifed and no implicit config is found" do
218
-
219
- before do
220
- allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
221
- end
222
-
223
- it "skips loading" do
224
- expect(config_loader.config_location).to be(nil)
225
- expect(config_loader).not_to receive(:apply_config)
226
- config_loader.load
227
- end
228
-
229
- end
230
-
231
- context "when an explicit config is given but it doesn't exist" do
232
-
233
- let(:explicit_config_location) { "/nope/nope/nope/frab/jab/nab" }
234
-
235
- it "raises a configuration error" do
236
- expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
237
- end
238
-
239
- end
240
-
241
- context "when the config file exists" do
242
-
243
- let(:config_content) { "" }
244
-
245
- # We need to keep a reference to the tempfile because while #close does
246
- # not unlink the file, the object being GC'd will.
247
- let(:tempfile) do
248
- Tempfile.new("Chef-WorkstationConfigLoader-rspec-test").tap do |t|
249
- t.print(config_content)
250
- t.close
251
- end
252
- end
253
-
254
- let(:explicit_config_location) do
255
- tempfile.path
256
- end
257
-
258
- after { File.unlink(explicit_config_location) if File.exist?(explicit_config_location) }
259
-
260
- context "and is valid" do
261
-
262
- let(:config_content) { "config_file_evaluated(true)" }
263
-
264
- it "loads the config" do
265
- expect(config_loader).to receive(:apply_config).and_call_original
266
- config_loader.load
267
- expect(ChefConfig::Config.config_file_evaluated).to be(true)
268
- end
269
-
270
- it "sets ChefConfig::Config.config_file" do
271
- config_loader.load
272
- expect(ChefConfig::Config.config_file).to eq(explicit_config_location)
273
- end
274
- end
275
-
276
- context "and has a syntax error" do
277
-
278
- let(:config_content) { "{{{{{:{{" }
279
-
280
- it "raises a ConfigurationError" do
281
- expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
282
- end
283
- end
284
-
285
- context "and raises a ruby exception during evaluation" do
286
-
287
- let(:config_content) { ":foo\n:bar\nraise 'oops'\n:baz\n" }
288
-
289
- it "raises a ConfigurationError" do
290
- expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
291
- end
292
- end
293
-
294
- end
295
-
296
- end
297
-
298
- describe "when loading config.d" do
299
- context "when the conf.d directory exists" do
300
- let(:config_content) { "" }
301
-
302
- let(:tempdir) { Dir.mktmpdir("chef-workstation-test") }
303
-
304
- let!(:confd_file) do
305
- Tempfile.new(["Chef-WorkstationConfigLoader-rspec-test", ".rb"], tempdir).tap do |t|
306
- t.print(config_content)
307
- t.close
308
- end
309
- end
310
-
311
- before do
312
- ChefConfig::Config[:config_d_dir] = tempdir
313
- allow(config_loader).to receive(:path_exists?).with(
314
- an_instance_of(String)).and_return(false)
315
- end
316
-
317
- after do
318
- FileUtils.remove_entry_secure tempdir
319
- end
320
-
321
- context "and is valid" do
322
- let(:config_content) { "config_d_file_evaluated(true)" }
323
-
324
- it "loads the config" do
325
- expect(config_loader).to receive(:apply_config).and_call_original
326
- config_loader.load
327
- expect(ChefConfig::Config.config_d_file_evaluated).to be(true)
328
- end
329
- end
330
-
331
- context "and has a syntax error" do
332
- let(:config_content) { "{{{{{:{{" }
333
-
334
- it "raises a ConfigurationError" do
335
- expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
336
- end
337
- end
338
-
339
- context "has a non rb file" do
340
- let(:sytax_error_content) { "{{{{{:{{" }
341
- let(:config_content) { "config_d_file_evaluated(true)" }
342
-
343
- let!(:not_confd_file) do
344
- Tempfile.new(["Chef-WorkstationConfigLoader-rspec-test", ".foorb"], tempdir).tap do |t|
345
- t.print(sytax_error_content)
346
- t.close
347
- end
348
- end
349
-
350
- it "does not load the non rb file" do
351
- expect { config_loader.load }.not_to raise_error
352
- expect(ChefConfig::Config.config_d_file_evaluated).to be(true)
353
- end
354
- end
355
- end
356
-
357
- context "when the conf.d directory does not exist" do
358
- before do
359
- ChefConfig::Config[:config_d_dir] = "/nope/nope/nope/nope/notdoingit"
360
- end
361
-
362
- it "does not load anything" do
363
- expect(config_loader).not_to receive(:apply_config)
364
- end
365
- end
366
- end
367
-
368
- describe "when loading a credentials file" do
369
- if ChefConfig.windows?
370
- let(:home) { "C:/Users/example.user" }
371
- else
372
- let(:home) { "/Users/example.user" }
373
- end
374
- let(:credentials_file) { "#{home}/.chef/credentials" }
375
- let(:context_file) { "#{home}/.chef/context" }
376
-
377
- before do
378
- allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_return(File.join(home, ".chef"))
379
- allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "credentials").and_return(credentials_file)
380
- allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "context").and_return(context_file)
381
- allow(File).to receive(:file?).with(context_file).and_return false
382
- end
383
-
384
- context "when the file exists" do
385
- before do
386
- expect(File).to receive(:read).with(credentials_file, { encoding: "utf-8" }).and_return(content)
387
- allow(File).to receive(:file?).with(credentials_file).and_return true
388
- end
389
-
390
- context "and has a default profile" do
391
- let(:content) do
392
- content = <<EOH
393
- [default]
394
- node_name = 'barney'
395
- client_key = "barney_rubble.pem"
396
- chef_server_url = "https://api.chef.io/organizations/bedrock"
397
- EOH
398
- content
399
- end
400
-
401
- it "applies the expected config" do
402
- expect { config_loader.load_credentials }.not_to raise_error
403
- expect(ChefConfig::Config.chef_server_url).to eq("https://api.chef.io/organizations/bedrock")
404
- expect(ChefConfig::Config.client_key.to_s).to eq("#{home}/.chef/barney_rubble.pem")
405
- expect(ChefConfig::Config.profile.to_s).to eq("default")
406
- end
407
- end
408
-
409
- context "and has a profile containing a full key" do
410
- let(:content) do
411
- content = <<EOH
412
- [default]
413
- client_key = """
414
- -----BEGIN RSA PRIVATE KEY-----
415
- foo
416
- """
417
- EOH
418
- content
419
- end
420
-
421
- it "applies the expected config" do
422
- expect { config_loader.load_credentials }.not_to raise_error
423
- expect(ChefConfig::Config.client_key_contents).to eq(<<EOH
424
- -----BEGIN RSA PRIVATE KEY-----
425
- foo
426
- EOH
427
- )
428
- end
429
- end
430
-
431
- context "and has several profiles" do
432
- let(:content) do
433
- content = <<EOH
434
- [default]
435
- client_name = "default"
436
- [environment]
437
- client_name = "environment"
438
- [explicit]
439
- client_name = "explicit"
440
- [context]
441
- client_name = "context"
442
- EOH
443
- content
444
- end
445
-
446
- let(:env) { {} }
447
- before do
448
- stub_const("ENV", env)
449
- end
450
-
451
- it "selects the correct profile explicitly" do
452
- expect { config_loader.load_credentials("explicit") }.not_to raise_error
453
- expect(ChefConfig::Config.node_name).to eq("explicit")
454
- end
455
-
456
- context "with an environment variable" do
457
- let(:env) { { "CHEF_PROFILE" => "environment" } }
458
-
459
- it "selects the correct profile" do
460
- expect { config_loader.load_credentials }.not_to raise_error
461
- expect(ChefConfig::Config.node_name).to eq("environment")
462
- end
463
- end
464
-
465
- it "selects the correct profile with a context file" do
466
- allow(File).to receive(:file?).with(context_file).and_return true
467
- expect(File).to receive(:read).with(context_file).and_return "context"
468
- expect { config_loader.load_credentials }.not_to raise_error
469
- expect(ChefConfig::Config.node_name).to eq("context")
470
- end
471
-
472
- it "falls back to the default" do
473
- expect { config_loader.load_credentials }.not_to raise_error
474
- expect(ChefConfig::Config.node_name).to eq("default")
475
- end
476
- end
477
-
478
- context "and contains both node_name and client_name" do
479
- let(:content) do
480
- content = <<EOH
481
- [default]
482
- node_name = 'barney'
483
- client_name = 'barney'
484
- EOH
485
- content
486
- end
487
-
488
- it "raises a ConfigurationError" do
489
- expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
490
- end
491
- end
492
-
493
- context "and has a syntax error" do
494
- let(:content) { "<<<<<" }
495
-
496
- it "raises a ConfigurationError" do
497
- expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
498
- end
499
- end
500
- end
501
-
502
- context "when the file does not exist" do
503
- it "does not load anything" do
504
- allow(File).to receive(:file?).with(credentials_file).and_return false
505
- expect(Tomlrb).not_to receive(:load_file)
506
- config_loader.load_credentials
507
- end
508
- end
509
- end
510
- end
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@chef.io>)
3
+ # Copyright:: Copyright 2014-2016, Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "spec_helper"
20
+ require "tempfile"
21
+
22
+ require "chef-config/exceptions"
23
+ require "chef-config/windows"
24
+ require "chef-config/workstation_config_loader"
25
+
26
+ RSpec.describe ChefConfig::WorkstationConfigLoader do
27
+
28
+ let(:explicit_config_location) { nil }
29
+
30
+ let(:env) { {} }
31
+
32
+ let(:config_loader) do
33
+ described_class.new(explicit_config_location).tap do |c|
34
+ allow(c).to receive(:env).and_return(env)
35
+ end
36
+ end
37
+
38
+ before do
39
+ # We set this to nil so that a dev workstation will
40
+ # not interfere with the tests.
41
+ ChefConfig::Config.reset
42
+ ChefConfig::Config[:config_d_dir] = nil
43
+ end
44
+
45
+ # Test methods that do I/O or reference external state which are stubbed out
46
+ # elsewhere.
47
+ describe "external dependencies" do
48
+ let(:config_loader) { described_class.new(nil) }
49
+
50
+ it "delegates to ENV for env" do
51
+ expect(config_loader.env).to equal(ENV)
52
+ end
53
+
54
+ it "tests a path's existence" do
55
+ expect(config_loader.path_exists?("/nope/nope/nope/nope/frab/jab/nab")).to be(false)
56
+ expect(config_loader.path_exists?(__FILE__)).to be(true)
57
+ end
58
+
59
+ end
60
+
61
+ describe "locating the config file" do
62
+ context "without an explicit config" do
63
+
64
+ before do
65
+ allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
66
+ end
67
+
68
+ it "has no config if HOME is not set" do
69
+ expect(config_loader.config_location).to be(nil)
70
+ expect(config_loader.no_config_found?).to be(true)
71
+ end
72
+
73
+ context "when HOME is set and contains a knife.rb" do
74
+
75
+ let(:home) { "/Users/example.user" }
76
+
77
+ before do
78
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_yield(File.join(home, ".chef"))
79
+ allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/knife.rb").and_return(true)
80
+ end
81
+
82
+ it "uses the config in HOME/.chef/knife.rb" do
83
+ expect(config_loader.config_location).to eq("#{home}/.chef/knife.rb")
84
+ end
85
+
86
+ context "and has a config.rb" do
87
+
88
+ before do
89
+ allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/config.rb").and_return(true)
90
+ end
91
+
92
+ it "uses the config in HOME/.chef/config.rb" do
93
+ expect(config_loader.config_location).to eq("#{home}/.chef/config.rb")
94
+ end
95
+
96
+ context "and/or a parent dir contains a .chef dir" do
97
+
98
+ let(:env_pwd) { "/path/to/cwd" }
99
+
100
+ before do
101
+ if ChefConfig.windows?
102
+ env["CD"] = env_pwd
103
+ else
104
+ env["PWD"] = env_pwd
105
+ end
106
+
107
+ allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/knife.rb").and_return(true)
108
+ allow(File).to receive(:exist?).with("#{env_pwd}/.chef").and_return(true)
109
+ allow(File).to receive(:directory?).with("#{env_pwd}/.chef").and_return(true)
110
+ end
111
+
112
+ it "prefers the config from parent_dir/.chef" do
113
+ expect(config_loader.config_location).to eq("#{env_pwd}/.chef/knife.rb")
114
+ end
115
+
116
+ context "and the parent dir's .chef dir has a config.rb" do
117
+
118
+ before do
119
+ allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/config.rb").and_return(true)
120
+ end
121
+
122
+ it "prefers the config from parent_dir/.chef" do
123
+ expect(config_loader.config_location).to eq("#{env_pwd}/.chef/config.rb")
124
+ end
125
+
126
+ context "and/or the current working directory contains a .chef dir" do
127
+
128
+ let(:cwd) { Dir.pwd }
129
+
130
+ before do
131
+ allow(config_loader).to receive(:path_exists?).with("#{cwd}/knife.rb").and_return(true)
132
+ end
133
+
134
+ it "prefers a knife.rb located in the cwd" do
135
+ expect(config_loader.config_location).to eq("#{cwd}/knife.rb")
136
+ end
137
+
138
+ context "and the CWD's .chef dir has a config.rb" do
139
+
140
+ before do
141
+ allow(config_loader).to receive(:path_exists?).with("#{cwd}/config.rb").and_return(true)
142
+ end
143
+
144
+ it "prefers a config located in the cwd" do
145
+ expect(config_loader.config_location).to eq("#{cwd}/config.rb")
146
+ end
147
+
148
+ context "and/or KNIFE_HOME is set" do
149
+
150
+ let(:knife_home) { "/path/to/knife/home" }
151
+
152
+ before do
153
+ env["KNIFE_HOME"] = knife_home
154
+ allow(config_loader).to receive(:path_exists?).with("#{knife_home}/knife.rb").and_return(true)
155
+ end
156
+
157
+ it "prefers a knife located in KNIFE_HOME" do
158
+ expect(config_loader.config_location).to eq("/path/to/knife/home/knife.rb")
159
+ end
160
+
161
+ context "and KNIFE_HOME contains a config.rb" do
162
+
163
+ before do
164
+ env["KNIFE_HOME"] = knife_home
165
+ allow(config_loader).to receive(:path_exists?).with("#{knife_home}/config.rb").and_return(true)
166
+ end
167
+
168
+ it "prefers a config.rb located in KNIFE_HOME" do
169
+ expect(config_loader.config_location).to eq("/path/to/knife/home/config.rb")
170
+ end
171
+
172
+ end
173
+
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ context "when the current working dir is inside a symlinked directory" do
183
+ before do
184
+ # pwd according to your shell is /home/someuser/prod/chef-repo, but
185
+ # chef-repo is a symlink to /home/someuser/codes/chef-repo
186
+ env["CD"] = "/home/someuser/prod/chef-repo" # windows
187
+ env["PWD"] = "/home/someuser/prod/chef-repo" # unix
188
+
189
+ allow(Dir).to receive(:pwd).and_return("/home/someuser/codes/chef-repo")
190
+ end
191
+
192
+ it "loads the config from the non-dereferenced directory path" do
193
+ expect(File).to receive(:exist?).with("/home/someuser/prod/chef-repo/.chef").and_return(false)
194
+ expect(File).to receive(:exist?).with("/home/someuser/prod/.chef").and_return(true)
195
+ expect(File).to receive(:directory?).with("/home/someuser/prod/.chef").and_return(true)
196
+
197
+ expect(config_loader).to receive(:path_exists?).with("/home/someuser/prod/.chef/knife.rb").and_return(true)
198
+
199
+ expect(config_loader.config_location).to eq("/home/someuser/prod/.chef/knife.rb")
200
+ end
201
+ end
202
+ end
203
+
204
+ context "when given an explicit config to load" do
205
+
206
+ let(:explicit_config_location) { "/path/to/explicit/config.rb" }
207
+
208
+ it "prefers the explicit config" do
209
+ expect(config_loader.config_location).to eq(explicit_config_location)
210
+ end
211
+
212
+ end
213
+ end
214
+
215
+ describe "loading the config file" do
216
+
217
+ context "when no explicit config is specifed and no implicit config is found" do
218
+
219
+ before do
220
+ allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
221
+ end
222
+
223
+ it "skips loading" do
224
+ expect(config_loader.config_location).to be(nil)
225
+ expect(config_loader).not_to receive(:apply_config)
226
+ config_loader.load
227
+ end
228
+
229
+ end
230
+
231
+ context "when an explicit config is given but it doesn't exist" do
232
+
233
+ let(:explicit_config_location) { "/nope/nope/nope/frab/jab/nab" }
234
+
235
+ it "raises a configuration error" do
236
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
237
+ end
238
+
239
+ end
240
+
241
+ context "when the config file exists" do
242
+
243
+ let(:config_content) { "" }
244
+
245
+ # We need to keep a reference to the tempfile because while #close does
246
+ # not unlink the file, the object being GC'd will.
247
+ let(:tempfile) do
248
+ Tempfile.new("Chef-WorkstationConfigLoader-rspec-test").tap do |t|
249
+ t.print(config_content)
250
+ t.close
251
+ end
252
+ end
253
+
254
+ let(:explicit_config_location) do
255
+ tempfile.path
256
+ end
257
+
258
+ after { File.unlink(explicit_config_location) if File.exist?(explicit_config_location) }
259
+
260
+ context "and is valid" do
261
+
262
+ let(:config_content) { "config_file_evaluated(true)" }
263
+
264
+ it "loads the config" do
265
+ expect(config_loader).to receive(:apply_config).and_call_original
266
+ config_loader.load
267
+ expect(ChefConfig::Config.config_file_evaluated).to be(true)
268
+ end
269
+
270
+ it "sets ChefConfig::Config.config_file" do
271
+ config_loader.load
272
+ expect(ChefConfig::Config.config_file).to eq(explicit_config_location)
273
+ end
274
+ end
275
+
276
+ context "and has a syntax error" do
277
+
278
+ let(:config_content) { "{{{{{:{{" }
279
+
280
+ it "raises a ConfigurationError" do
281
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
282
+ end
283
+ end
284
+
285
+ context "and raises a ruby exception during evaluation" do
286
+
287
+ let(:config_content) { ":foo\n:bar\nraise 'oops'\n:baz\n" }
288
+
289
+ it "raises a ConfigurationError" do
290
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
291
+ end
292
+ end
293
+
294
+ end
295
+
296
+ end
297
+
298
+ describe "when loading config.d" do
299
+ context "when the conf.d directory exists" do
300
+ let(:config_content) { "" }
301
+
302
+ let(:tempdir) { Dir.mktmpdir("chef-workstation-test") }
303
+
304
+ let!(:confd_file) do
305
+ Tempfile.new(["Chef-WorkstationConfigLoader-rspec-test", ".rb"], tempdir).tap do |t|
306
+ t.print(config_content)
307
+ t.close
308
+ end
309
+ end
310
+
311
+ before do
312
+ ChefConfig::Config[:config_d_dir] = tempdir
313
+ allow(config_loader).to receive(:path_exists?).with(
314
+ an_instance_of(String)).and_return(false)
315
+ end
316
+
317
+ after do
318
+ FileUtils.remove_entry_secure tempdir
319
+ end
320
+
321
+ context "and is valid" do
322
+ let(:config_content) { "config_d_file_evaluated(true)" }
323
+
324
+ it "loads the config" do
325
+ expect(config_loader).to receive(:apply_config).and_call_original
326
+ config_loader.load
327
+ expect(ChefConfig::Config.config_d_file_evaluated).to be(true)
328
+ end
329
+ end
330
+
331
+ context "and has a syntax error" do
332
+ let(:config_content) { "{{{{{:{{" }
333
+
334
+ it "raises a ConfigurationError" do
335
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
336
+ end
337
+ end
338
+
339
+ context "has a non rb file" do
340
+ let(:sytax_error_content) { "{{{{{:{{" }
341
+ let(:config_content) { "config_d_file_evaluated(true)" }
342
+
343
+ let!(:not_confd_file) do
344
+ Tempfile.new(["Chef-WorkstationConfigLoader-rspec-test", ".foorb"], tempdir).tap do |t|
345
+ t.print(sytax_error_content)
346
+ t.close
347
+ end
348
+ end
349
+
350
+ it "does not load the non rb file" do
351
+ expect { config_loader.load }.not_to raise_error
352
+ expect(ChefConfig::Config.config_d_file_evaluated).to be(true)
353
+ end
354
+ end
355
+ end
356
+
357
+ context "when the conf.d directory does not exist" do
358
+ before do
359
+ ChefConfig::Config[:config_d_dir] = "/nope/nope/nope/nope/notdoingit"
360
+ end
361
+
362
+ it "does not load anything" do
363
+ expect(config_loader).not_to receive(:apply_config)
364
+ end
365
+ end
366
+ end
367
+
368
+ describe "when loading a credentials file" do
369
+ if ChefConfig.windows?
370
+ let(:home) { "C:/Users/example.user" }
371
+ else
372
+ let(:home) { "/Users/example.user" }
373
+ end
374
+ let(:credentials_file) { "#{home}/.chef/credentials" }
375
+ let(:context_file) { "#{home}/.chef/context" }
376
+
377
+ before do
378
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_return(File.join(home, ".chef"))
379
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "credentials").and_return(credentials_file)
380
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "context").and_return(context_file)
381
+ allow(File).to receive(:file?).with(context_file).and_return false
382
+ end
383
+
384
+ context "when the file exists" do
385
+ before do
386
+ expect(File).to receive(:read).with(credentials_file, { encoding: "utf-8" }).and_return(content)
387
+ allow(File).to receive(:file?).with(credentials_file).and_return true
388
+ end
389
+
390
+ context "and has a default profile" do
391
+ let(:content) do
392
+ content = <<EOH
393
+ [default]
394
+ node_name = 'barney'
395
+ client_key = "barney_rubble.pem"
396
+ chef_server_url = "https://api.chef.io/organizations/bedrock"
397
+ EOH
398
+ content
399
+ end
400
+
401
+ it "applies the expected config" do
402
+ expect { config_loader.load_credentials }.not_to raise_error
403
+ expect(ChefConfig::Config.chef_server_url).to eq("https://api.chef.io/organizations/bedrock")
404
+ expect(ChefConfig::Config.client_key.to_s).to eq("#{home}/.chef/barney_rubble.pem")
405
+ expect(ChefConfig::Config.profile.to_s).to eq("default")
406
+ end
407
+ end
408
+
409
+ context "and has a profile containing a full key" do
410
+ let(:content) do
411
+ content = <<EOH
412
+ [default]
413
+ client_key = """
414
+ -----BEGIN RSA PRIVATE KEY-----
415
+ foo
416
+ """
417
+ EOH
418
+ content
419
+ end
420
+
421
+ it "applies the expected config" do
422
+ expect { config_loader.load_credentials }.not_to raise_error
423
+ expect(ChefConfig::Config.client_key_contents).to eq(<<EOH
424
+ -----BEGIN RSA PRIVATE KEY-----
425
+ foo
426
+ EOH
427
+ )
428
+ end
429
+ end
430
+
431
+ context "and has several profiles" do
432
+ let(:content) do
433
+ content = <<EOH
434
+ [default]
435
+ client_name = "default"
436
+ [environment]
437
+ client_name = "environment"
438
+ [explicit]
439
+ client_name = "explicit"
440
+ [context]
441
+ client_name = "context"
442
+ EOH
443
+ content
444
+ end
445
+
446
+ let(:env) { {} }
447
+ before do
448
+ stub_const("ENV", env)
449
+ end
450
+
451
+ it "selects the correct profile explicitly" do
452
+ expect { config_loader.load_credentials("explicit") }.not_to raise_error
453
+ expect(ChefConfig::Config.node_name).to eq("explicit")
454
+ end
455
+
456
+ context "with an environment variable" do
457
+ let(:env) { { "CHEF_PROFILE" => "environment" } }
458
+
459
+ it "selects the correct profile" do
460
+ expect { config_loader.load_credentials }.not_to raise_error
461
+ expect(ChefConfig::Config.node_name).to eq("environment")
462
+ end
463
+ end
464
+
465
+ it "selects the correct profile with a context file" do
466
+ allow(File).to receive(:file?).with(context_file).and_return true
467
+ expect(File).to receive(:read).with(context_file).and_return "context"
468
+ expect { config_loader.load_credentials }.not_to raise_error
469
+ expect(ChefConfig::Config.node_name).to eq("context")
470
+ end
471
+
472
+ it "falls back to the default" do
473
+ expect { config_loader.load_credentials }.not_to raise_error
474
+ expect(ChefConfig::Config.node_name).to eq("default")
475
+ end
476
+ end
477
+
478
+ context "and contains both node_name and client_name" do
479
+ let(:content) do
480
+ content = <<EOH
481
+ [default]
482
+ node_name = 'barney'
483
+ client_name = 'barney'
484
+ EOH
485
+ content
486
+ end
487
+
488
+ it "raises a ConfigurationError" do
489
+ expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
490
+ end
491
+ end
492
+
493
+ context "and has a syntax error" do
494
+ let(:content) { "<<<<<" }
495
+
496
+ it "raises a ConfigurationError" do
497
+ expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
498
+ end
499
+ end
500
+ end
501
+
502
+ context "when the file does not exist" do
503
+ it "does not load anything" do
504
+ allow(File).to receive(:file?).with(credentials_file).and_return false
505
+ expect(Tomlrb).not_to receive(:load_file)
506
+ config_loader.load_credentials
507
+ end
508
+ end
509
+ end
510
+ end