r10k 3.9.1 → 3.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec_tests.yml +1 -1
  3. data/.travis.yml +0 -10
  4. data/CHANGELOG.mkd +28 -0
  5. data/README.mkd +6 -0
  6. data/doc/dynamic-environments/configuration.mkd +21 -0
  7. data/doc/puppetfile.mkd +15 -1
  8. data/integration/Rakefile +3 -1
  9. data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +3 -9
  10. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +21 -25
  11. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +3 -3
  12. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +3 -3
  13. data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +3 -3
  14. data/lib/r10k/action/base.rb +6 -3
  15. data/lib/r10k/action/deploy/display.rb +6 -3
  16. data/lib/r10k/action/deploy/environment.rb +15 -4
  17. data/lib/r10k/action/deploy/module.rb +37 -8
  18. data/lib/r10k/action/runner.rb +45 -10
  19. data/lib/r10k/cli/deploy.rb +4 -0
  20. data/lib/r10k/git.rb +3 -0
  21. data/lib/r10k/git/cache.rb +1 -1
  22. data/lib/r10k/git/rugged/credentials.rb +77 -0
  23. data/lib/r10k/git/stateful_repository.rb +1 -0
  24. data/lib/r10k/initializers.rb +10 -0
  25. data/lib/r10k/module/base.rb +37 -0
  26. data/lib/r10k/module/forge.rb +7 -2
  27. data/lib/r10k/module/git.rb +2 -1
  28. data/lib/r10k/module/svn.rb +2 -1
  29. data/lib/r10k/module_loader/puppetfile.rb +206 -0
  30. data/lib/r10k/module_loader/puppetfile/dsl.rb +37 -0
  31. data/lib/r10k/puppetfile.rb +83 -160
  32. data/lib/r10k/settings.rb +47 -2
  33. data/lib/r10k/settings/definition.rb +1 -1
  34. data/lib/r10k/source/base.rb +10 -0
  35. data/lib/r10k/source/git.rb +5 -0
  36. data/lib/r10k/source/svn.rb +4 -0
  37. data/lib/r10k/util/purgeable.rb +70 -8
  38. data/lib/r10k/version.rb +1 -1
  39. data/locales/r10k.pot +129 -57
  40. data/r10k.gemspec +2 -0
  41. data/spec/fixtures/unit/action/r10k_forge_auth.yaml +4 -0
  42. data/spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml +3 -0
  43. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_subdir_2/ignored_1 +0 -0
  44. data/spec/fixtures/unit/util/purgeable/managed_two/.hidden/unmanaged_3 +0 -0
  45. data/spec/unit/action/deploy/environment_spec.rb +25 -0
  46. data/spec/unit/action/deploy/module_spec.rb +216 -14
  47. data/spec/unit/action/runner_spec.rb +129 -25
  48. data/spec/unit/git/cache_spec.rb +14 -0
  49. data/spec/unit/git/rugged/credentials_spec.rb +29 -0
  50. data/spec/unit/git/stateful_repository_spec.rb +5 -0
  51. data/spec/unit/module/base_spec.rb +46 -0
  52. data/spec/unit/module/forge_spec.rb +27 -1
  53. data/spec/unit/module/git_spec.rb +17 -8
  54. data/spec/unit/module/svn_spec.rb +18 -0
  55. data/spec/unit/module_loader/puppetfile_spec.rb +343 -0
  56. data/spec/unit/module_spec.rb +28 -0
  57. data/spec/unit/puppetfile_spec.rb +127 -191
  58. data/spec/unit/settings_spec.rb +24 -2
  59. data/spec/unit/util/purgeable_spec.rb +38 -6
  60. metadata +23 -2
data/r10k.gemspec CHANGED
@@ -36,6 +36,8 @@ Gem::Specification.new do |s|
36
36
  s.add_dependency 'fast_gettext', '~> 1.1.0'
37
37
  s.add_dependency 'gettext', ['>= 3.0.2', '< 3.3.0']
38
38
 
39
+ s.add_dependency 'jwt', '~> 2.2.3'
40
+
39
41
  s.add_development_dependency 'rspec', '~> 3.1'
40
42
 
41
43
  s.add_development_dependency 'rake'
@@ -0,0 +1,4 @@
1
+ ---
2
+ forge:
3
+ baseurl: 'http://private-forge.com'
4
+ authorization_token: 'faketoken'
@@ -0,0 +1,3 @@
1
+ ---
2
+ forge:
3
+ authorization_token: 'faketoken'
@@ -47,6 +47,22 @@ describe R10K::Action::Deploy::Environment do
47
47
  described_class.new({ 'oauth-token': '/nonexistent' }, [], {})
48
48
  end
49
49
 
50
+ it 'can accept an app id option' do
51
+ described_class.new({ 'github-app-id': '/nonexistent' }, [], {})
52
+ end
53
+
54
+ it 'can accept a ttl option' do
55
+ described_class.new({ 'github-app-ttl': '/nonexistent' }, [], {})
56
+ end
57
+
58
+ it 'can accept a ssl private key option' do
59
+ described_class.new({ 'github-app-key': '/nonexistent' }, [], {})
60
+ end
61
+
62
+ it 'can accept a exclude-spec option' do
63
+ described_class.new({ :'exclude-spec' => true }, [], {})
64
+ end
65
+
50
66
  describe "initializing errors" do
51
67
  let (:settings) { { deploy: { purge_levels: [:environment],
52
68
  purge_whitelist: ['coolfile', 'coolfile2'],
@@ -265,6 +281,15 @@ describe R10K::Action::Deploy::Environment do
265
281
  describe "deployment purge level" do
266
282
  let(:purge_levels) { [:deployment] }
267
283
 
284
+
285
+ it "updates the source's cache before it purges environments" do
286
+ deployment.sources.each do |source|
287
+ expect(source).to receive(:reload!).ordered
288
+ end
289
+ expect(deployment).to receive(:purge!).ordered
290
+ subject.call
291
+ end
292
+
268
293
  it "only logs about purging deployment" do
269
294
  expect(subject).to receive(:visit_environment).and_wrap_original do |original, env, &block|
270
295
  expect(env.logger).to_not receive(:debug).with(/purging unmanaged puppetfile content/i)
@@ -41,6 +41,22 @@ describe R10K::Action::Deploy::Module do
41
41
  it 'can accept a token option' do
42
42
  described_class.new({ 'oauth-token': '/nonexistent' }, [], {})
43
43
  end
44
+
45
+ it 'can accept an app id option' do
46
+ described_class.new({ 'github-app-id': '/nonexistent' }, [], {})
47
+ end
48
+
49
+ it 'can accept a ttl option' do
50
+ described_class.new({ 'github-app-ttl': '/nonexistent' }, [], {})
51
+ end
52
+
53
+ it 'can accept a ssl private key option' do
54
+ described_class.new({ 'github-app-key': '/nonexistent' }, [], {})
55
+ end
56
+
57
+ it 'can accept a exclude-spec option' do
58
+ described_class.new({ :'exclude-spec' => true }, [], {})
59
+ end
44
60
  end
45
61
 
46
62
  describe "with no-force" do
@@ -177,12 +193,39 @@ describe R10K::Action::Deploy::Module do
177
193
  end
178
194
  end
179
195
 
196
+ describe 'with github-app-id' do
197
+
198
+ subject { described_class.new({ config: '/some/nonexistent/path', 'github-app-id': '/nonexistent' }, [], {}) }
199
+
200
+ it 'sets github-app-id' do
201
+ expect(subject.instance_variable_get(:@github_app_id)).to eq('/nonexistent')
202
+ end
203
+ end
204
+
205
+ describe 'with github-app-key' do
206
+
207
+ subject { described_class.new({ config: '/some/nonexistent/path', 'github-app-key': '/nonexistent' }, [], {}) }
208
+
209
+ it 'sets github-app-key' do
210
+ expect(subject.instance_variable_get(:@github_app_key)).to eq('/nonexistent')
211
+ end
212
+ end
213
+
214
+ describe 'with github-app-ttl' do
215
+
216
+ subject { described_class.new({ config: '/some/nonexistent/path', 'github-app-ttl': '/nonexistent' }, [], {}) }
217
+
218
+ it 'sets github-app-ttl' do
219
+ expect(subject.instance_variable_get(:@github_app_ttl)).to eq('/nonexistent')
220
+ end
221
+ end
222
+
180
223
  describe 'with modules' do
181
224
 
182
225
  subject { described_class.new({ config: '/some/nonexistent/path' }, ['mod1', 'mod2'], {}) }
183
226
 
184
227
  let(:cache) { instance_double("R10K::Git::Cache", 'sanitized_dirname' => 'foo', 'cached?' => true, 'sync' => true) }
185
- let(:repo) { instance_double("R10K::Git::StatefulRepository", cache: cache, resolve: 'main') }
228
+ let(:repo) { instance_double("R10K::Git::StatefulRepository", cache: cache, resolve: 'main', tracked_paths: []) }
186
229
 
187
230
  it 'does not sync modules not given' do
188
231
  allow(R10K::Deployment).to receive(:new).and_wrap_original do |original, settings, &block|
@@ -202,14 +245,26 @@ describe R10K::Action::Deploy::Module do
202
245
  allow_any_instance_of(R10K::Source::Git).to receive(:branch_names).and_return([R10K::Environment::Name.new('first', {})])
203
246
 
204
247
  expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
205
- pf = environment.puppetfile
206
- expect(pf).to receive(:load) do
207
- pf.add_module('mod1', { git: 'git://remote' })
208
- pf.add_module('mod2', { git: 'git://remote' })
209
- pf.add_module('mod3', { git: 'git://remote' })
248
+ # For this test we want to have realistic Modules and access to
249
+ # their internal Repos to validate the sync. Unfortunately, to
250
+ # do so we do some invasive mocking, effectively implementing
251
+ # our own R10K::Puppetfile#load. We directly update the Puppetfile's
252
+ # internal ModuleLoader and then call `load` on it so it will create
253
+ # the correct loaded_content.
254
+ puppetfile = environment.puppetfile
255
+ loader = puppetfile.loader
256
+ expect(puppetfile).to receive(:load) do
257
+ loader.add_module('mod1', { git: 'git://remote' })
258
+ loader.add_module('mod2', { git: 'git://remote' })
259
+ loader.add_module('mod3', { git: 'git://remote' })
260
+
261
+ allow(loader).to receive(:puppetfile_content).and_return('')
262
+ loaded_content = loader.load
263
+ puppetfile.instance_variable_set(:@loaded_content, loaded_content)
264
+ puppetfile.instance_variable_set(:@loaded, true)
210
265
  end
211
266
 
212
- pf.modules.each do |mod|
267
+ puppetfile.modules.each do |mod|
213
268
  if ['mod1', 'mod2'].include?(mod.name)
214
269
  expect(mod.should_sync?).to be(true)
215
270
  else
@@ -231,7 +286,7 @@ describe R10K::Action::Deploy::Module do
231
286
  subject { described_class.new({ config: '/some/nonexistent/path', environment: 'first' }, ['mod1'], {}) }
232
287
 
233
288
  let(:cache) { instance_double("R10K::Git::Cache", 'sanitized_dirname' => 'foo', 'cached?' => true, 'sync' => true) }
234
- let(:repo) { instance_double("R10K::Git::StatefulRepository", cache: cache, resolve: 'main') }
289
+ let(:repo) { instance_double("R10K::Git::StatefulRepository", cache: cache, resolve: 'main', tracked_paths: []) }
235
290
 
236
291
  it 'only syncs to the given environments' do
237
292
  allow(R10K::Deployment).to receive(:new).and_wrap_original do |original, settings, &block|
@@ -252,15 +307,27 @@ describe R10K::Action::Deploy::Module do
252
307
  R10K::Environment::Name.new('second', {})])
253
308
 
254
309
  expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
255
- pf = environment.puppetfile
310
+ puppetfile = environment.puppetfile
256
311
 
257
312
  if environment.name == 'first'
258
- expect(pf).to receive(:load) do
259
- pf.add_module('mod1', { git: 'git://remote' })
260
- pf.add_module('mod2', { git: 'git://remote' })
313
+ # For this test we want to have realistic Modules and access to
314
+ # their internal Repos to validate the sync. Unfortunately, to
315
+ # do so we do some invasive mocking, effectively implementing
316
+ # our own R10K::Puppetfile#load. We directly update the Puppetfile's
317
+ # internal ModuleLoader and then call `load` on it so it will create
318
+ # the correct loaded_content.
319
+ loader = puppetfile.loader
320
+ expect(puppetfile).to receive(:load) do
321
+ loader.add_module('mod1', { git: 'git://remote' })
322
+ loader.add_module('mod2', { git: 'git://remote' })
323
+
324
+ allow(loader).to receive(:puppetfile_content).and_return('')
325
+ loaded_content = loader.load
326
+ puppetfile.instance_variable_set(:@loaded_content, loaded_content)
327
+ puppetfile.instance_variable_set(:@loaded, true)
261
328
  end
262
329
 
263
- pf.modules.each do |mod|
330
+ puppetfile.modules.each do |mod|
264
331
  if mod.name == 'mod1'
265
332
  expect(mod.should_sync?).to be(true)
266
333
  else
@@ -269,7 +336,7 @@ describe R10K::Action::Deploy::Module do
269
336
  expect(mod).to receive(:sync).and_call_original
270
337
  end
271
338
  else
272
- expect(pf).not_to receive(:load)
339
+ expect(puppetfile).not_to receive(:load)
273
340
  end
274
341
 
275
342
  original.call(environment, &block)
@@ -282,5 +349,140 @@ describe R10K::Action::Deploy::Module do
282
349
  subject.call
283
350
  end
284
351
  end
352
+
353
+
354
+ describe "postrun" do
355
+ let(:mock_config) do
356
+ R10K::Deployment::MockConfig.new(
357
+ :sources => {
358
+ :control => {
359
+ :type => :mock,
360
+ :basedir => '/some/nonexistent/path/control',
361
+ :environments => %w[first second third],
362
+ }
363
+ }
364
+ )
365
+ end
366
+
367
+ context "basic postrun hook" do
368
+ let(:settings) { { postrun: ["/path/to/executable", "arg1", "arg2"] } }
369
+ let(:deployment) { R10K::Deployment.new(mock_config.merge(settings)) }
370
+
371
+ before do
372
+ expect(R10K::Deployment).to receive(:new).and_return(deployment)
373
+ end
374
+
375
+ subject do
376
+ described_class.new({config: "/some/nonexistent/path" },
377
+ ['mod1'], settings)
378
+ end
379
+
380
+ it "is passed to Subprocess" do
381
+ mock_subprocess = double
382
+ allow(mock_subprocess).to receive(:logger=)
383
+ expect(mock_subprocess).to receive(:execute)
384
+
385
+ expect(R10K::Util::Subprocess).to receive(:new).
386
+ with(["/path/to/executable", "arg1", "arg2"]).
387
+ and_return(mock_subprocess)
388
+
389
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
390
+ modified = subject.instance_variable_get(:@modified_envs) << environment
391
+ subject.instance_variable_set(:modified_envs, modified)
392
+ end.exactly(3).times
393
+
394
+ subject.call
395
+ end
396
+ end
397
+
398
+ context "supports environments" do
399
+ context "with one environment" do
400
+ let(:settings) { { postrun: ["/generate/types/wrapper", "$modifiedenvs"] } }
401
+ let(:deployment) { R10K::Deployment.new(mock_config.merge(settings)) }
402
+
403
+ before do
404
+ expect(R10K::Deployment).to receive(:new).and_return(deployment)
405
+ end
406
+
407
+ subject do
408
+ described_class.new({ config: '/some/nonexistent/path',
409
+ environment: 'first' },
410
+ ['mod1'], settings)
411
+ end
412
+
413
+ it "properly substitutes the environment" do
414
+ mock_subprocess = double
415
+ allow(mock_subprocess).to receive(:logger=)
416
+ expect(mock_subprocess).to receive(:execute)
417
+
418
+ mock_mod = double('mock_mod', name: 'mod1')
419
+
420
+ expect(R10K::Util::Subprocess).to receive(:new).
421
+ with(["/generate/types/wrapper", "first"]).
422
+ and_return(mock_subprocess)
423
+
424
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
425
+ if environment.name == 'first'
426
+ expect(environment).to receive(:deploy).and_return(true)
427
+ expect(environment).to receive(:modules).and_return([mock_mod])
428
+ end
429
+ original.call(environment, &block)
430
+ end.exactly(3).times
431
+
432
+ subject.call
433
+ end
434
+ end
435
+
436
+ context "with all environments" do
437
+ let(:settings) { { postrun: ["/generate/types/wrapper", "$modifiedenvs"] } }
438
+ let(:deployment) { R10K::Deployment.new(mock_config.merge(settings)) }
439
+
440
+ before do
441
+ expect(R10K::Deployment).to receive(:new).and_return(deployment)
442
+ end
443
+
444
+ subject do
445
+ described_class.new({ config: '/some/nonexistent/path' },
446
+ ['mod1'], settings)
447
+ end
448
+
449
+ it "properly substitutes the environment where modules were deployed" do
450
+ mock_subprocess = double
451
+ allow(mock_subprocess).to receive(:logger=)
452
+ expect(mock_subprocess).to receive(:execute)
453
+
454
+ expect(R10K::Util::Subprocess).to receive(:new).
455
+ with(["/generate/types/wrapper", "first third"]).
456
+ and_return(mock_subprocess)
457
+
458
+ mock_mod = double('mock_mod', name: 'mod1')
459
+
460
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
461
+ expect(environment).to receive(:deploy).and_return(true)
462
+ if ['first', 'third'].include?(environment.name)
463
+ expect(environment).to receive(:modules).and_return([mock_mod])
464
+ end
465
+ original.call(environment, &block)
466
+ end.exactly(3).times
467
+
468
+ subject.call
469
+ end
470
+
471
+ it "does not execute the command if no envs had the module" do
472
+ expect(R10K::Util::Subprocess).not_to receive(:new)
473
+
474
+ mock_mod2 = double('mock_mod', name: 'mod2')
475
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
476
+ expect(environment).to receive(:deploy).and_return(true)
477
+ # Envs have a different module than the one we asked to deploy
478
+ expect(environment).to receive(:modules).and_return([mock_mod2])
479
+ original.call(environment, &block)
480
+ end.exactly(3).times
481
+
482
+ subject.call
483
+ end
484
+ end
485
+ end
486
+ end
285
487
  end
286
488
 
@@ -171,6 +171,86 @@ describe R10K::Action::Runner do
171
171
  end
172
172
  end
173
173
 
174
+ describe "configuring github app credentials" do
175
+ it 'errors if app id is passed without ssl key' do
176
+ runner = described_class.new(
177
+ { 'github-app-id': '/nonexistent', },
178
+ %w[args yes],
179
+ action_class
180
+ )
181
+ expect{ runner.call }.to raise_error(R10K::Error, /Must specify both id and SSL private key/)
182
+ end
183
+
184
+ it 'errors if ssl key is passed without app id' do
185
+ runner = described_class.new(
186
+ { 'github-app-key': '/nonexistent', },
187
+ %w[args yes],
188
+ action_class
189
+ )
190
+ expect{ runner.call }.to raise_error(R10K::Error, /Must specify both id and SSL private key/)
191
+ end
192
+
193
+ it 'errors if both app id and token paths are passed' do
194
+ runner = described_class.new(
195
+ { 'github-app-id': '/nonexistent', 'oauth-token': '/also/fake' },
196
+ %w[args yes],
197
+ action_class
198
+ )
199
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
200
+ end
201
+
202
+ it 'errors if both ssl key and token paths are passed' do
203
+ runner = described_class.new(
204
+ { 'github-app-key': '/nonexistent', 'oauth-token': '/also/fake' },
205
+ %w[args yes],
206
+ action_class
207
+ )
208
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
209
+ end
210
+
211
+ it 'errors if both ssl key and ssh key paths are passed' do
212
+ runner = described_class.new(
213
+ { 'github-app-key': '/nonexistent', 'private-key': '/also/fake' },
214
+ %w[args yes],
215
+ action_class
216
+ )
217
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
218
+ end
219
+
220
+ it 'errors if both app id and ssh key are passed' do
221
+ runner = described_class.new(
222
+ { 'github-app-id': '/nonexistent', 'private-key': '/also/fake' },
223
+ %w[args yes],
224
+ action_class
225
+ )
226
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
227
+ end
228
+
229
+ it 'saves the parameters in settings hash' do
230
+ runner = described_class.new(
231
+ { 'github-app-id': '123456', 'github-app-key': '/my/ssl/key', 'github-app-ttl': '600' },
232
+ %w[args yes],
233
+ action_class
234
+ )
235
+ runner.call
236
+ expect(runner.instance.settings[:git][:github_app_id]).to eq('123456')
237
+ expect(runner.instance.settings[:git][:github_app_key]).to eq('/my/ssl/key')
238
+ expect(runner.instance.settings[:git][:github_app_ttl]).to eq('600')
239
+ end
240
+
241
+ it 'saves the parameters in settings hash without ttl and uses its default value' do
242
+ runner = described_class.new(
243
+ { 'github-app-id': '123456', 'github-app-key': '/my/ssl/key', },
244
+ %w[args yes],
245
+ action_class
246
+ )
247
+ runner.call
248
+ expect(runner.instance.settings[:git][:github_app_id]).to eq('123456')
249
+ expect(runner.instance.settings[:git][:github_app_key]).to eq('/my/ssl/key')
250
+ expect(runner.instance.settings[:git][:github_app_ttl]).to eq('120')
251
+ end
252
+ end
253
+
174
254
  describe "configuring git credentials" do
175
255
  it 'errors if both token and key paths are passed' do
176
256
  runner = described_class.new({ 'oauth-token': '/nonexistent',
@@ -218,42 +298,66 @@ describe R10K::Action::Runner do
218
298
  end
219
299
 
220
300
  describe "configuration authorization" do
221
- context "when license is not present" do
222
- before(:each) do
223
- expect(R10K::Util::License).to receive(:load).and_return(nil)
301
+ context "settings auth" do
302
+ it "sets the configured token as the forge authorization header" do
303
+ options = { config: "spec/fixtures/unit/action/r10k_forge_auth.yaml" }
304
+ runner = described_class.new(options, %w[args yes], action_class)
305
+
306
+ expect(PuppetForge).to receive(:host=).with('http://private-forge.com')
307
+ expect(PuppetForge::Connection).to receive(:authorization=).with('faketoken')
308
+ expect(PuppetForge::Connection).to receive(:authorization).and_return('faketoken')
309
+ expect(R10K::Util::License).not_to receive(:load)
310
+ runner.setup_settings
311
+ runner.setup_authorization
224
312
  end
225
313
 
226
- it "does not set authorization header on connection class" do
227
- expect(PuppetForge::Connection).not_to receive(:authorization=)
228
- runner.setup_authorization
314
+ it 'errors if no custom forge URL is set' do
315
+ options = { config: "spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml" }
316
+ runner = described_class.new(options, %w[args yes], action_class)
317
+ expect(PuppetForge::Connection).not_to receive(:authorization=).with('faketoken')
318
+
319
+ expect { runner.setup_settings }.to raise_error(R10K::Error, /Cannot specify a Forge auth/)
229
320
  end
230
321
  end
231
322
 
232
- context "when license is present but invalid" do
233
- before(:each) do
234
- expect(R10K::Util::License).to receive(:load).and_raise(R10K::Error.new('invalid license'))
235
- end
323
+ context "license auth" do
324
+ context "when license is not present" do
325
+ before(:each) do
326
+ expect(R10K::Util::License).to receive(:load).and_return(nil)
327
+ end
236
328
 
237
- it "issues warning to logger" do
238
- expect(runner.logger).to receive(:warn).with(/invalid license/)
239
- runner.setup_authorization
329
+ it "does not set authorization header on connection class" do
330
+ expect(PuppetForge::Connection).not_to receive(:authorization=)
331
+ runner.setup_authorization
332
+ end
240
333
  end
241
334
 
242
- it "does not set authorization header on connection class" do
243
- expect(PuppetForge::Connection).not_to receive(:authorization=)
244
- runner.setup_authorization
245
- end
246
- end
335
+ context "when license is present but invalid" do
336
+ before(:each) do
337
+ expect(R10K::Util::License).to receive(:load).and_raise(R10K::Error.new('invalid license'))
338
+ end
339
+
340
+ it "issues warning to logger" do
341
+ expect(runner.logger).to receive(:warn).with(/invalid license/)
342
+ runner.setup_authorization
343
+ end
247
344
 
248
- context "when license is present and valid" do
249
- before(:each) do
250
- mock_license = double('pe-license', :authorization_token => 'test token')
251
- expect(R10K::Util::License).to receive(:load).and_return(mock_license)
345
+ it "does not set authorization header on connection class" do
346
+ expect(PuppetForge::Connection).not_to receive(:authorization=)
347
+ runner.setup_authorization
348
+ end
252
349
  end
253
350
 
254
- it "sets authorization header on connection class" do
255
- expect(PuppetForge::Connection).to receive(:authorization=).with('test token')
256
- runner.setup_authorization
351
+ context "when license is present and valid" do
352
+ before(:each) do
353
+ mock_license = double('pe-license', :authorization_token => 'test token')
354
+ expect(R10K::Util::License).to receive(:load).and_return(mock_license)
355
+ end
356
+
357
+ it "sets authorization header on connection class" do
358
+ expect(PuppetForge::Connection).to receive(:authorization=).with('test token')
359
+ runner.setup_authorization
360
+ end
257
361
  end
258
362
  end
259
363
  end