r10k 3.9.1 → 3.11.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/rspec_tests.yml +1 -1
- data/.travis.yml +0 -10
- data/CHANGELOG.mkd +28 -0
- data/README.mkd +6 -0
- data/doc/dynamic-environments/configuration.mkd +21 -0
- data/doc/puppetfile.mkd +15 -1
- data/integration/Rakefile +3 -1
- data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +3 -9
- data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +21 -25
- data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +3 -3
- data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +3 -3
- data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +3 -3
- data/lib/r10k/action/base.rb +6 -3
- data/lib/r10k/action/deploy/display.rb +6 -3
- data/lib/r10k/action/deploy/environment.rb +15 -4
- data/lib/r10k/action/deploy/module.rb +37 -8
- data/lib/r10k/action/runner.rb +45 -10
- data/lib/r10k/cli/deploy.rb +4 -0
- data/lib/r10k/git.rb +3 -0
- data/lib/r10k/git/cache.rb +1 -1
- data/lib/r10k/git/rugged/credentials.rb +77 -0
- data/lib/r10k/git/stateful_repository.rb +1 -0
- data/lib/r10k/initializers.rb +10 -0
- data/lib/r10k/module/base.rb +37 -0
- data/lib/r10k/module/forge.rb +7 -2
- data/lib/r10k/module/git.rb +2 -1
- data/lib/r10k/module/svn.rb +2 -1
- data/lib/r10k/module_loader/puppetfile.rb +206 -0
- data/lib/r10k/module_loader/puppetfile/dsl.rb +37 -0
- data/lib/r10k/puppetfile.rb +83 -160
- data/lib/r10k/settings.rb +47 -2
- data/lib/r10k/settings/definition.rb +1 -1
- data/lib/r10k/source/base.rb +10 -0
- data/lib/r10k/source/git.rb +5 -0
- data/lib/r10k/source/svn.rb +4 -0
- data/lib/r10k/util/purgeable.rb +70 -8
- data/lib/r10k/version.rb +1 -1
- data/locales/r10k.pot +129 -57
- data/r10k.gemspec +2 -0
- data/spec/fixtures/unit/action/r10k_forge_auth.yaml +4 -0
- data/spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml +3 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_subdir_2/ignored_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_two/.hidden/unmanaged_3 +0 -0
- data/spec/unit/action/deploy/environment_spec.rb +25 -0
- data/spec/unit/action/deploy/module_spec.rb +216 -14
- data/spec/unit/action/runner_spec.rb +129 -25
- data/spec/unit/git/cache_spec.rb +14 -0
- data/spec/unit/git/rugged/credentials_spec.rb +29 -0
- data/spec/unit/git/stateful_repository_spec.rb +5 -0
- data/spec/unit/module/base_spec.rb +46 -0
- data/spec/unit/module/forge_spec.rb +27 -1
- data/spec/unit/module/git_spec.rb +17 -8
- data/spec/unit/module/svn_spec.rb +18 -0
- data/spec/unit/module_loader/puppetfile_spec.rb +343 -0
- data/spec/unit/module_spec.rb +28 -0
- data/spec/unit/puppetfile_spec.rb +127 -191
- data/spec/unit/settings_spec.rb +24 -2
- data/spec/unit/util/purgeable_spec.rb +38 -6
- 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'
|
data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_subdir_2/ignored_1
ADDED
File without changes
|
File without changes
|
@@ -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
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
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
|
-
|
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
|
-
|
310
|
+
puppetfile = environment.puppetfile
|
256
311
|
|
257
312
|
if environment.name == 'first'
|
258
|
-
|
259
|
-
|
260
|
-
|
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
|
-
|
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(
|
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 "
|
222
|
-
|
223
|
-
|
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
|
227
|
-
|
228
|
-
runner.
|
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 "
|
233
|
-
|
234
|
-
|
235
|
-
|
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
|
-
|
238
|
-
|
239
|
-
|
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
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
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
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
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
|
-
|
255
|
-
|
256
|
-
|
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
|