chef-config 12.7.2 → 12.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,289 +1,366 @@
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
- # Test methods that do I/O or reference external state which are stubbed out
39
- # elsewhere.
40
- describe "external dependencies" do
41
- let(:config_loader) { described_class.new(nil) }
42
-
43
- it "delegates to ENV for env" do
44
- expect(config_loader.env).to equal(ENV)
45
- end
46
-
47
- it "tests a path's existence" do
48
- expect(config_loader.path_exists?("/nope/nope/nope/nope/frab/jab/nab")).to be(false)
49
- expect(config_loader.path_exists?(__FILE__)).to be(true)
50
- end
51
-
52
- end
53
-
54
- describe "locating the config file" do
55
- context "without an explicit config" do
56
-
57
- before do
58
- allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
59
- end
60
-
61
- it "has no config if HOME is not set" do
62
- expect(config_loader.config_location).to be(nil)
63
- expect(config_loader.no_config_found?).to be(true)
64
- end
65
-
66
- context "when HOME is set and contains a knife.rb" do
67
-
68
- let(:home) { "/Users/example.user" }
69
-
70
- before do
71
- allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_yield(File.join(home, ".chef"))
72
- allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/knife.rb").and_return(true)
73
- end
74
-
75
- it "uses the config in HOME/.chef/knife.rb" do
76
- expect(config_loader.config_location).to eq("#{home}/.chef/knife.rb")
77
- end
78
-
79
- context "and has a config.rb" do
80
-
81
- before do
82
- allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/config.rb").and_return(true)
83
- end
84
-
85
- it "uses the config in HOME/.chef/config.rb" do
86
- expect(config_loader.config_location).to eq("#{home}/.chef/config.rb")
87
- end
88
-
89
- context "and/or a parent dir contains a .chef dir" do
90
-
91
- let(:env_pwd) { "/path/to/cwd" }
92
-
93
- before do
94
- if ChefConfig.windows?
95
- env["CD"] = env_pwd
96
- else
97
- env["PWD"] = env_pwd
98
- end
99
-
100
- allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/knife.rb").and_return(true)
101
- allow(File).to receive(:exist?).with("#{env_pwd}/.chef").and_return(true)
102
- allow(File).to receive(:directory?).with("#{env_pwd}/.chef").and_return(true)
103
- end
104
-
105
- it "prefers the config from parent_dir/.chef" do
106
- expect(config_loader.config_location).to eq("#{env_pwd}/.chef/knife.rb")
107
- end
108
-
109
- context "and the parent dir's .chef dir has a config.rb" do
110
-
111
- before do
112
- allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/config.rb").and_return(true)
113
- end
114
-
115
- it "prefers the config from parent_dir/.chef" do
116
- expect(config_loader.config_location).to eq("#{env_pwd}/.chef/config.rb")
117
- end
118
-
119
- context "and/or the current working directory contains a .chef dir" do
120
-
121
- let(:cwd) { Dir.pwd }
122
-
123
- before do
124
- allow(config_loader).to receive(:path_exists?).with("#{cwd}/knife.rb").and_return(true)
125
- end
126
-
127
- it "prefers a knife.rb located in the cwd" do
128
- expect(config_loader.config_location).to eq("#{cwd}/knife.rb")
129
- end
130
-
131
- context "and the CWD's .chef dir has a config.rb" do
132
-
133
- before do
134
- allow(config_loader).to receive(:path_exists?).with("#{cwd}/config.rb").and_return(true)
135
- end
136
-
137
- it "prefers a config located in the cwd" do
138
- expect(config_loader.config_location).to eq("#{cwd}/config.rb")
139
- end
140
-
141
- context "and/or KNIFE_HOME is set" do
142
-
143
- let(:knife_home) { "/path/to/knife/home" }
144
-
145
- before do
146
- env["KNIFE_HOME"] = knife_home
147
- allow(config_loader).to receive(:path_exists?).with("#{knife_home}/knife.rb").and_return(true)
148
- end
149
-
150
- it "prefers a knife located in KNIFE_HOME" do
151
- expect(config_loader.config_location).to eq("/path/to/knife/home/knife.rb")
152
- end
153
-
154
- context "and KNIFE_HOME contains a config.rb" do
155
-
156
- before do
157
- env["KNIFE_HOME"] = knife_home
158
- allow(config_loader).to receive(:path_exists?).with("#{knife_home}/config.rb").and_return(true)
159
- end
160
-
161
- it "prefers a config.rb located in KNIFE_HOME" do
162
- expect(config_loader.config_location).to eq("/path/to/knife/home/config.rb")
163
- end
164
-
165
- end
166
-
167
- end
168
- end
169
- end
170
- end
171
- end
172
- end
173
- end
174
-
175
- context "when the current working dir is inside a symlinked directory" do
176
- before do
177
- # pwd according to your shell is /home/someuser/prod/chef-repo, but
178
- # chef-repo is a symlink to /home/someuser/codes/chef-repo
179
- env["CD"] = "/home/someuser/prod/chef-repo" # windows
180
- env["PWD"] = "/home/someuser/prod/chef-repo" # unix
181
-
182
- allow(Dir).to receive(:pwd).and_return("/home/someuser/codes/chef-repo")
183
- end
184
-
185
- it "loads the config from the non-dereferenced directory path" do
186
- expect(File).to receive(:exist?).with("/home/someuser/prod/chef-repo/.chef").and_return(false)
187
- expect(File).to receive(:exist?).with("/home/someuser/prod/.chef").and_return(true)
188
- expect(File).to receive(:directory?).with("/home/someuser/prod/.chef").and_return(true)
189
-
190
- expect(config_loader).to receive(:path_exists?).with("/home/someuser/prod/.chef/knife.rb").and_return(true)
191
-
192
- expect(config_loader.config_location).to eq("/home/someuser/prod/.chef/knife.rb")
193
- end
194
- end
195
- end
196
-
197
- context "when given an explicit config to load" do
198
-
199
- let(:explicit_config_location) { "/path/to/explicit/config.rb" }
200
-
201
- it "prefers the explicit config" do
202
- expect(config_loader.config_location).to eq(explicit_config_location)
203
- end
204
-
205
- end
206
- end
207
-
208
- describe "loading the config file" do
209
-
210
- context "when no explicit config is specifed and no implicit config is found" do
211
-
212
- before do
213
- allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
214
- end
215
-
216
- it "skips loading" do
217
- expect(config_loader.config_location).to be(nil)
218
- expect(config_loader.load).to be(false)
219
- end
220
-
221
- end
222
-
223
- context "when an explicit config is given but it doesn't exist" do
224
-
225
- let(:explicit_config_location) { "/nope/nope/nope/frab/jab/nab" }
226
-
227
- it "raises a configuration error" do
228
- expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
229
- end
230
-
231
- end
232
-
233
- context "when the config file exists" do
234
-
235
- let(:config_content) { "" }
236
-
237
- # We need to keep a reference to the tempfile because while #close does
238
- # not unlink the file, the object being GC'd will.
239
- let(:tempfile) do
240
- Tempfile.new("Chef-WorkstationConfigLoader-rspec-test").tap do |t|
241
- t.print(config_content)
242
- t.close
243
- end
244
- end
245
-
246
- let(:explicit_config_location) do
247
- tempfile.path
248
- end
249
-
250
- after { File.unlink(explicit_config_location) if File.exist?(explicit_config_location) }
251
-
252
- context "and is valid" do
253
-
254
- let(:config_content) { "config_file_evaluated(true)" }
255
-
256
- it "loads the config" do
257
- expect(config_loader.load).to be(true)
258
- expect(ChefConfig::Config.config_file_evaluated).to be(true)
259
- end
260
-
261
- it "sets ChefConfig::Config.config_file" do
262
- config_loader.load
263
- expect(ChefConfig::Config.config_file).to eq(explicit_config_location)
264
- end
265
- end
266
-
267
- context "and has a syntax error" do
268
-
269
- let(:config_content) { "{{{{{:{{" }
270
-
271
- it "raises a ConfigurationError" do
272
- expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
273
- end
274
- end
275
-
276
- context "and raises a ruby exception during evaluation" do
277
-
278
- let(:config_content) { ":foo\n:bar\nraise 'oops'\n:baz\n" }
279
-
280
- it "raises a ConfigurationError" do
281
- expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
282
- end
283
- end
284
-
285
- end
286
-
287
- end
288
-
289
- 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[:config_d_dir] = nil
42
+ end
43
+
44
+ # Test methods that do I/O or reference external state which are stubbed out
45
+ # elsewhere.
46
+ describe "external dependencies" do
47
+ let(:config_loader) { described_class.new(nil) }
48
+
49
+ it "delegates to ENV for env" do
50
+ expect(config_loader.env).to equal(ENV)
51
+ end
52
+
53
+ it "tests a path's existence" do
54
+ expect(config_loader.path_exists?("/nope/nope/nope/nope/frab/jab/nab")).to be(false)
55
+ expect(config_loader.path_exists?(__FILE__)).to be(true)
56
+ end
57
+
58
+ end
59
+
60
+ describe "locating the config file" do
61
+ context "without an explicit config" do
62
+
63
+ before do
64
+ allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
65
+ end
66
+
67
+ it "has no config if HOME is not set" do
68
+ expect(config_loader.config_location).to be(nil)
69
+ expect(config_loader.no_config_found?).to be(true)
70
+ end
71
+
72
+ context "when HOME is set and contains a knife.rb" do
73
+
74
+ let(:home) { "/Users/example.user" }
75
+
76
+ before do
77
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_yield(File.join(home, ".chef"))
78
+ allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/knife.rb").and_return(true)
79
+ end
80
+
81
+ it "uses the config in HOME/.chef/knife.rb" do
82
+ expect(config_loader.config_location).to eq("#{home}/.chef/knife.rb")
83
+ end
84
+
85
+ context "and has a config.rb" do
86
+
87
+ before do
88
+ allow(config_loader).to receive(:path_exists?).with("#{home}/.chef/config.rb").and_return(true)
89
+ end
90
+
91
+ it "uses the config in HOME/.chef/config.rb" do
92
+ expect(config_loader.config_location).to eq("#{home}/.chef/config.rb")
93
+ end
94
+
95
+ context "and/or a parent dir contains a .chef dir" do
96
+
97
+ let(:env_pwd) { "/path/to/cwd" }
98
+
99
+ before do
100
+ if ChefConfig.windows?
101
+ env["CD"] = env_pwd
102
+ else
103
+ env["PWD"] = env_pwd
104
+ end
105
+
106
+ allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/knife.rb").and_return(true)
107
+ allow(File).to receive(:exist?).with("#{env_pwd}/.chef").and_return(true)
108
+ allow(File).to receive(:directory?).with("#{env_pwd}/.chef").and_return(true)
109
+ end
110
+
111
+ it "prefers the config from parent_dir/.chef" do
112
+ expect(config_loader.config_location).to eq("#{env_pwd}/.chef/knife.rb")
113
+ end
114
+
115
+ context "and the parent dir's .chef dir has a config.rb" do
116
+
117
+ before do
118
+ allow(config_loader).to receive(:path_exists?).with("#{env_pwd}/.chef/config.rb").and_return(true)
119
+ end
120
+
121
+ it "prefers the config from parent_dir/.chef" do
122
+ expect(config_loader.config_location).to eq("#{env_pwd}/.chef/config.rb")
123
+ end
124
+
125
+ context "and/or the current working directory contains a .chef dir" do
126
+
127
+ let(:cwd) { Dir.pwd }
128
+
129
+ before do
130
+ allow(config_loader).to receive(:path_exists?).with("#{cwd}/knife.rb").and_return(true)
131
+ end
132
+
133
+ it "prefers a knife.rb located in the cwd" do
134
+ expect(config_loader.config_location).to eq("#{cwd}/knife.rb")
135
+ end
136
+
137
+ context "and the CWD's .chef dir has a config.rb" do
138
+
139
+ before do
140
+ allow(config_loader).to receive(:path_exists?).with("#{cwd}/config.rb").and_return(true)
141
+ end
142
+
143
+ it "prefers a config located in the cwd" do
144
+ expect(config_loader.config_location).to eq("#{cwd}/config.rb")
145
+ end
146
+
147
+ context "and/or KNIFE_HOME is set" do
148
+
149
+ let(:knife_home) { "/path/to/knife/home" }
150
+
151
+ before do
152
+ env["KNIFE_HOME"] = knife_home
153
+ allow(config_loader).to receive(:path_exists?).with("#{knife_home}/knife.rb").and_return(true)
154
+ end
155
+
156
+ it "prefers a knife located in KNIFE_HOME" do
157
+ expect(config_loader.config_location).to eq("/path/to/knife/home/knife.rb")
158
+ end
159
+
160
+ context "and KNIFE_HOME contains a config.rb" do
161
+
162
+ before do
163
+ env["KNIFE_HOME"] = knife_home
164
+ allow(config_loader).to receive(:path_exists?).with("#{knife_home}/config.rb").and_return(true)
165
+ end
166
+
167
+ it "prefers a config.rb located in KNIFE_HOME" do
168
+ expect(config_loader.config_location).to eq("/path/to/knife/home/config.rb")
169
+ end
170
+
171
+ end
172
+
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ context "when the current working dir is inside a symlinked directory" do
182
+ before do
183
+ # pwd according to your shell is /home/someuser/prod/chef-repo, but
184
+ # chef-repo is a symlink to /home/someuser/codes/chef-repo
185
+ env["CD"] = "/home/someuser/prod/chef-repo" # windows
186
+ env["PWD"] = "/home/someuser/prod/chef-repo" # unix
187
+
188
+ allow(Dir).to receive(:pwd).and_return("/home/someuser/codes/chef-repo")
189
+ end
190
+
191
+ it "loads the config from the non-dereferenced directory path" do
192
+ expect(File).to receive(:exist?).with("/home/someuser/prod/chef-repo/.chef").and_return(false)
193
+ expect(File).to receive(:exist?).with("/home/someuser/prod/.chef").and_return(true)
194
+ expect(File).to receive(:directory?).with("/home/someuser/prod/.chef").and_return(true)
195
+
196
+ expect(config_loader).to receive(:path_exists?).with("/home/someuser/prod/.chef/knife.rb").and_return(true)
197
+
198
+ expect(config_loader.config_location).to eq("/home/someuser/prod/.chef/knife.rb")
199
+ end
200
+ end
201
+ end
202
+
203
+ context "when given an explicit config to load" do
204
+
205
+ let(:explicit_config_location) { "/path/to/explicit/config.rb" }
206
+
207
+ it "prefers the explicit config" do
208
+ expect(config_loader.config_location).to eq(explicit_config_location)
209
+ end
210
+
211
+ end
212
+ end
213
+
214
+ describe "loading the config file" do
215
+
216
+ context "when no explicit config is specifed and no implicit config is found" do
217
+
218
+ before do
219
+ allow(config_loader).to receive(:path_exists?).with(an_instance_of(String)).and_return(false)
220
+ end
221
+
222
+ it "skips loading" do
223
+ expect(config_loader.config_location).to be(nil)
224
+ expect(config_loader).not_to receive(:apply_config)
225
+ config_loader.load
226
+ end
227
+
228
+ end
229
+
230
+ context "when an explicit config is given but it doesn't exist" do
231
+
232
+ let(:explicit_config_location) { "/nope/nope/nope/frab/jab/nab" }
233
+
234
+ it "raises a configuration error" do
235
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
236
+ end
237
+
238
+ end
239
+
240
+ context "when the config file exists" do
241
+
242
+ let(:config_content) { "" }
243
+
244
+ # We need to keep a reference to the tempfile because while #close does
245
+ # not unlink the file, the object being GC'd will.
246
+ let(:tempfile) do
247
+ Tempfile.new("Chef-WorkstationConfigLoader-rspec-test").tap do |t|
248
+ t.print(config_content)
249
+ t.close
250
+ end
251
+ end
252
+
253
+ let(:explicit_config_location) do
254
+ tempfile.path
255
+ end
256
+
257
+ after { File.unlink(explicit_config_location) if File.exist?(explicit_config_location) }
258
+
259
+ context "and is valid" do
260
+
261
+ let(:config_content) { "config_file_evaluated(true)" }
262
+
263
+ it "loads the config" do
264
+ expect(config_loader).to receive(:apply_config).and_call_original
265
+ config_loader.load
266
+ expect(ChefConfig::Config.config_file_evaluated).to be(true)
267
+ end
268
+
269
+ it "sets ChefConfig::Config.config_file" do
270
+ config_loader.load
271
+ expect(ChefConfig::Config.config_file).to eq(explicit_config_location)
272
+ end
273
+ end
274
+
275
+ context "and has a syntax error" do
276
+
277
+ let(:config_content) { "{{{{{:{{" }
278
+
279
+ it "raises a ConfigurationError" do
280
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
281
+ end
282
+ end
283
+
284
+ context "and raises a ruby exception during evaluation" do
285
+
286
+ let(:config_content) { ":foo\n:bar\nraise 'oops'\n:baz\n" }
287
+
288
+ it "raises a ConfigurationError" do
289
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
290
+ end
291
+ end
292
+
293
+ end
294
+
295
+ end
296
+
297
+ describe "when loading config.d" do
298
+ context "when the conf.d directory exists" do
299
+ let(:config_content) { "" }
300
+
301
+ let(:tempdir) { Dir.mktmpdir("chef-workstation-test") }
302
+
303
+ let!(:confd_file) do
304
+ Tempfile.new(["Chef-WorkstationConfigLoader-rspec-test", ".rb"], tempdir).tap do |t|
305
+ t.print(config_content)
306
+ t.close
307
+ end
308
+ end
309
+
310
+ before do
311
+ ChefConfig::Config[:config_d_dir] = tempdir
312
+ allow(config_loader).to receive(:path_exists?).with(
313
+ an_instance_of(String)).and_return(false)
314
+ end
315
+
316
+ after do
317
+ FileUtils.remove_entry_secure tempdir
318
+ end
319
+
320
+ context "and is valid" do
321
+ let(:config_content) { "config_d_file_evaluated(true)" }
322
+
323
+ it "loads the config" do
324
+ expect(config_loader).to receive(:apply_config).and_call_original
325
+ config_loader.load
326
+ expect(ChefConfig::Config.config_d_file_evaluated).to be(true)
327
+ end
328
+ end
329
+
330
+ context "and has a syntax error" do
331
+ let(:config_content) { "{{{{{:{{" }
332
+
333
+ it "raises a ConfigurationError" do
334
+ expect { config_loader.load }.to raise_error(ChefConfig::ConfigurationError)
335
+ end
336
+ end
337
+
338
+ context "has a non rb file" do
339
+ let(:sytax_error_content) { "{{{{{:{{" }
340
+ let(:config_content) { "config_d_file_evaluated(true)" }
341
+
342
+ let!(:not_confd_file) do
343
+ Tempfile.new(["Chef-WorkstationConfigLoader-rspec-test", ".foorb"], tempdir).tap do |t|
344
+ t.print(sytax_error_content)
345
+ t.close
346
+ end
347
+ end
348
+
349
+ it "does not load the non rb file" do
350
+ expect { config_loader.load }.not_to raise_error
351
+ expect(ChefConfig::Config.config_d_file_evaluated).to be(true)
352
+ end
353
+ end
354
+ end
355
+
356
+ context "when the conf.d directory does not exist" do
357
+ before do
358
+ ChefConfig::Config[:config_d_dir] = "/nope/nope/nope/nope/notdoingit"
359
+ end
360
+
361
+ it "does not load anything" do
362
+ expect(config_loader).not_to receive(:apply_config)
363
+ end
364
+ end
365
+ end
366
+ end