r10k 3.9.0 → 3.9.1

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +1 -1
  3. data/.github/workflows/stale.yml +19 -0
  4. data/CHANGELOG.mkd +5 -0
  5. data/doc/dynamic-environments/configuration.mkd +6 -6
  6. data/lib/r10k/action/base.rb +8 -1
  7. data/lib/r10k/action/deploy/display.rb +39 -9
  8. data/lib/r10k/action/deploy/environment.rb +63 -40
  9. data/lib/r10k/action/deploy/module.rb +47 -28
  10. data/lib/r10k/action/puppetfile/check.rb +3 -1
  11. data/lib/r10k/action/puppetfile/install.rb +20 -23
  12. data/lib/r10k/action/puppetfile/purge.rb +8 -2
  13. data/lib/r10k/content_synchronizer.rb +83 -0
  14. data/lib/r10k/deployment.rb +1 -1
  15. data/lib/r10k/environment/base.rb +21 -1
  16. data/lib/r10k/environment/git.rb +0 -3
  17. data/lib/r10k/environment/svn.rb +4 -6
  18. data/lib/r10k/environment/with_modules.rb +18 -10
  19. data/lib/r10k/module.rb +1 -1
  20. data/lib/r10k/module/base.rb +17 -1
  21. data/lib/r10k/module/forge.rb +24 -18
  22. data/lib/r10k/module/git.rb +22 -13
  23. data/lib/r10k/module/local.rb +1 -0
  24. data/lib/r10k/module/svn.rb +11 -8
  25. data/lib/r10k/puppetfile.rb +55 -70
  26. data/lib/r10k/source/base.rb +4 -0
  27. data/lib/r10k/source/git.rb +14 -6
  28. data/lib/r10k/source/hash.rb +1 -3
  29. data/lib/r10k/source/svn.rb +0 -2
  30. data/lib/r10k/util/cleaner.rb +21 -0
  31. data/lib/r10k/version.rb +1 -1
  32. data/locales/r10k.pot +51 -59
  33. data/spec/r10k-mocks/mock_source.rb +1 -1
  34. data/spec/shared-examples/puppetfile-action.rb +7 -7
  35. data/spec/unit/action/deploy/display_spec.rb +32 -6
  36. data/spec/unit/action/deploy/environment_spec.rb +76 -48
  37. data/spec/unit/action/deploy/module_spec.rb +139 -31
  38. data/spec/unit/action/puppetfile/check_spec.rb +2 -2
  39. data/spec/unit/action/puppetfile/install_spec.rb +31 -10
  40. data/spec/unit/action/puppetfile/purge_spec.rb +25 -5
  41. data/spec/unit/module/forge_spec.rb +15 -13
  42. data/spec/unit/module/git_spec.rb +8 -0
  43. data/spec/unit/module_spec.rb +5 -5
  44. data/spec/unit/puppetfile_spec.rb +40 -26
  45. data/spec/unit/util/purgeable_spec.rb +2 -8
  46. metadata +5 -2
@@ -8,6 +8,6 @@ class R10K::Source::Mock < R10K::Source::Base
8
8
  corrected_environment_names = @options[:environments].map do |env|
9
9
  R10K::Environment::Name.new(env, :prefix => @prefix, :invalid => 'correct_and_warn')
10
10
  end
11
- corrected_environment_names.map { |env| R10K::Environment::Mock.new(env.name, @basedir, env.dirname) }
11
+ corrected_environment_names.map { |env| R10K::Environment::Mock.new(env.name, @basedir, env.dirname, { overrides: @options[:overrides] }) }
12
12
  end
13
13
  end
@@ -3,15 +3,15 @@ require 'spec_helper'
3
3
  shared_examples_for "a puppetfile action" do
4
4
  describe "initializing" do
5
5
  it "accepts the :root option" do
6
- described_class.new({root: "/some/nonexistent/path"}, [])
6
+ described_class.new({root: "/some/nonexistent/path"}, [], {})
7
7
  end
8
8
 
9
9
  it "accepts the :puppetfile option" do
10
- described_class.new({puppetfile: "/some/nonexistent/path/Puppetfile"}, [])
10
+ described_class.new({puppetfile: "/some/nonexistent/path/Puppetfile"}, [], {})
11
11
  end
12
12
 
13
13
  it "accepts the :moduledir option" do
14
- described_class.new({moduledir: "/some/nonexistent/path/modules"}, [])
14
+ described_class.new({moduledir: "/some/nonexistent/path/modules"}, [], {})
15
15
  end
16
16
 
17
17
  end
@@ -20,19 +20,19 @@ end
20
20
  shared_examples_for "a puppetfile install action" do
21
21
  describe "initializing" do
22
22
  it "accepts the :root option" do
23
- described_class.new({root: "/some/nonexistent/path"}, [])
23
+ described_class.new({root: "/some/nonexistent/path"}, [], {})
24
24
  end
25
25
 
26
26
  it "accepts the :puppetfile option" do
27
- described_class.new({puppetfile: "/some/nonexistent/path/Puppetfile"}, [])
27
+ described_class.new({puppetfile: "/some/nonexistent/path/Puppetfile"}, [], {})
28
28
  end
29
29
 
30
30
  it "accepts the :moduledir option" do
31
- described_class.new({moduledir: "/some/nonexistent/path/modules"}, [])
31
+ described_class.new({moduledir: "/some/nonexistent/path/modules"}, [], {})
32
32
  end
33
33
 
34
34
  it "accepts the :force option" do
35
- described_class.new({force: true}, [])
35
+ described_class.new({force: true}, [], {})
36
36
  end
37
37
 
38
38
  end
@@ -5,31 +5,57 @@ require 'r10k/action/deploy/display'
5
5
  describe R10K::Action::Deploy::Display do
6
6
  describe "initializing" do
7
7
  it "accepts a puppetfile option" do
8
- described_class.new({puppetfile: true}, [])
8
+ described_class.new({puppetfile: true}, [], {})
9
9
  end
10
10
 
11
11
  it "accepts a modules option" do
12
- described_class.new({modules: true}, [])
12
+ described_class.new({modules: true}, [], {})
13
13
  end
14
14
 
15
15
  it "accepts a detail option" do
16
- described_class.new({detail: true}, [])
16
+ described_class.new({detail: true}, [], {})
17
17
  end
18
18
 
19
19
  it "accepts a format option" do
20
- described_class.new({format: "json"}, [])
20
+ described_class.new({format: "json"}, [], {})
21
21
  end
22
22
 
23
23
  it "accepts a fetch option" do
24
- described_class.new({fetch: true}, [])
24
+ described_class.new({fetch: true}, [], {})
25
25
  end
26
26
  end
27
27
 
28
- subject { described_class.new({config: "/some/nonexistent/path"}, []) }
28
+ subject { described_class.new({config: "/some/nonexistent/path"}, [], {}) }
29
29
 
30
30
  before do
31
31
  allow(subject).to receive(:puts)
32
32
  end
33
33
 
34
34
  it_behaves_like "a deploy action that requires a config file"
35
+
36
+ describe "collecting info" do
37
+ subject { described_class.new({config: "/some/nonexistent/path", format: 'json', puppetfile: true, detail: true}, ['first'], {}) }
38
+
39
+ let(:mock_config) do
40
+ R10K::Deployment::MockConfig.new(
41
+ :sources => {
42
+ :control => {
43
+ :type => :mock,
44
+ :basedir => '/some/nonexistent/path/control',
45
+ :environments => %w[first second third env-that/will-be-corrected],
46
+ :prefix => 'PREFIX'
47
+ }
48
+ }
49
+ )
50
+ end
51
+
52
+ let(:deployment) { R10K::Deployment.new(mock_config) }
53
+
54
+ it "gathers environment info" do
55
+ source_info = subject.send(:source_info, deployment.sources.first, ['first'])
56
+ expect(source_info[:name]).to eq(:control)
57
+ expect(source_info[:environments].length).to eq(1)
58
+ expect(source_info[:environments][0][:name]).to eq('first')
59
+ end
60
+ end
35
61
  end
@@ -5,46 +5,46 @@ require 'r10k/action/deploy/environment'
5
5
 
6
6
  describe R10K::Action::Deploy::Environment do
7
7
 
8
- subject { described_class.new({config: "/some/nonexistent/path"}, []) }
8
+ subject { described_class.new({config: "/some/nonexistent/path"}, [], {}) }
9
9
 
10
10
  it_behaves_like "a deploy action that can be write locked"
11
11
  it_behaves_like "a deploy action that requires a config file"
12
12
 
13
13
  describe "initializing" do
14
14
  it "can accept a cachedir option" do
15
- described_class.new({cachedir: "/some/nonexistent/cachedir"}, [])
15
+ described_class.new({cachedir: "/some/nonexistent/cachedir"}, [], {})
16
16
  end
17
17
 
18
18
  it "can accept a puppetfile option" do
19
- described_class.new({puppetfile: true}, [])
19
+ described_class.new({puppetfile: true}, [], {})
20
20
  end
21
21
 
22
22
  it "can accept a modules option" do
23
- described_class.new({modules: true}, [])
23
+ described_class.new({modules: true}, [], {})
24
24
  end
25
25
 
26
26
  it "can accept a default_branch_override option" do
27
- described_class.new({:'default-branch-override' => 'default_branch_override_name'}, [])
27
+ described_class.new({:'default-branch-override' => 'default_branch_override_name'}, [], {})
28
28
  end
29
29
 
30
30
  it "can accept a no-force option" do
31
- described_class.new({:'no-force' => true}, [])
31
+ described_class.new({:'no-force' => true}, [], {})
32
32
  end
33
33
 
34
34
  it 'can accept a generate-types option' do
35
- described_class.new({ 'generate-types': true }, [])
35
+ described_class.new({ 'generate-types': true }, [], {})
36
36
  end
37
37
 
38
38
  it 'can accept a puppet-path option' do
39
- described_class.new({ 'puppet-path': '/nonexistent' }, [])
39
+ described_class.new({ 'puppet-path': '/nonexistent' }, [], {})
40
40
  end
41
41
 
42
42
  it 'can accept a private-key option' do
43
- described_class.new({ 'private-key': '/nonexistent' }, [])
43
+ described_class.new({ 'private-key': '/nonexistent' }, [], {})
44
44
  end
45
45
 
46
46
  it 'can accept a token option' do
47
- described_class.new({ 'oauth-token': '/nonexistent' }, [])
47
+ described_class.new({ 'oauth-token': '/nonexistent' }, [], {})
48
48
  end
49
49
 
50
50
  describe "initializing errors" do
@@ -83,14 +83,14 @@ describe R10K::Action::Deploy::Environment do
83
83
  end
84
84
 
85
85
  it "syncs the puppetfile when given the puppetfile flag" do
86
- expect(puppetfile).to receive(:accept).and_return([])
87
- action = described_class.new({config: "/some/nonexistent/path", puppetfile: true}, [])
86
+ expect(puppetfile).to receive(:sync)
87
+ action = described_class.new({config: "/some/nonexistent/path", puppetfile: true}, [], {})
88
88
  action.call
89
89
  end
90
90
 
91
91
  it "syncs the puppetfile when given the modules flag" do
92
- expect(puppetfile).to receive(:accept).and_return([])
93
- action = described_class.new({config: "/some/nonexistent/path", modules: true}, [])
92
+ expect(puppetfile).to receive(:sync)
93
+ action = described_class.new({config: "/some/nonexistent/path", modules: true}, [], {})
94
94
  action.call
95
95
  end
96
96
 
@@ -105,7 +105,7 @@ describe R10K::Action::Deploy::Environment do
105
105
  expect(R10K::Deployment).to receive(:new).and_return(deployment)
106
106
  end
107
107
 
108
- subject { described_class.new({config: "/some/nonexistent/path"}, %w[not_an_environment]) }
108
+ subject { described_class.new({config: "/some/nonexistent/path"}, %w[not_an_environment], {}) }
109
109
 
110
110
  it "logs that the environments can't be deployed and returns false" do
111
111
  expect(subject.logger).to receive(:error).with("Environment(s) 'not_an_environment' cannot be found in any source and will not be deployed.")
@@ -115,10 +115,10 @@ describe R10K::Action::Deploy::Environment do
115
115
  end
116
116
 
117
117
  describe "with no-force" do
118
- subject { described_class.new({ config: "/some/nonexistent/path", modules: true, :'no-force' => true}, %w[first]) }
118
+ subject { described_class.new({ config: "/some/nonexistent/path", modules: true, :'no-force' => true}, %w[first], {}) }
119
119
 
120
120
  it "tries to preserve local modifications" do
121
- expect(subject.force).to equal(false)
121
+ expect(subject.settings[:overrides][:modules][:force]).to equal(false)
122
122
  end
123
123
  end
124
124
 
@@ -206,21 +206,13 @@ describe R10K::Action::Deploy::Environment do
206
206
  end
207
207
  end
208
208
 
209
- describe 'extracting credentials' do
210
- let(:deployment) do
211
- R10K::Deployment.new(mock_config)
212
- end
213
-
214
- end
215
-
216
209
  describe "Purging white/allowlist" do
217
210
 
218
211
  let(:settings) { { deploy: { purge_levels: [:environment], purge_allowlist: ['coolfile', 'coolfile2'] } } }
219
-
212
+ let(:overrides) { { environments: {}, modules: {}, purging: { purge_levels: [:environment], purge_allowlist: ['coolfile', 'coolfile2'] } } }
220
213
  let(:deployment) do
221
- R10K::Deployment.new(mock_config.merge(settings))
214
+ R10K::Deployment.new(mock_config.merge(overrides))
222
215
  end
223
-
224
216
  before do
225
217
  expect(R10K::Deployment).to receive(:new).and_return(deployment)
226
218
  end
@@ -229,7 +221,7 @@ describe R10K::Action::Deploy::Environment do
229
221
 
230
222
  it "reads in the purge_allowlist setting and purges accordingly" do
231
223
  expect(subject.logger).to receive(:debug).with(/purging unmanaged content for environment/i)
232
- expect(subject.instance_variable_get(:@user_purge_allowlist)).to eq(['coolfile', 'coolfile2'])
224
+ expect(subject.settings[:overrides][:purging][:purge_allowlist]).to eq(['coolfile', 'coolfile2'])
233
225
  subject.call
234
226
  end
235
227
 
@@ -238,7 +230,7 @@ describe R10K::Action::Deploy::Environment do
238
230
 
239
231
  it "reads in the purge_whitelist setting and still sets it to purge_allowlist and purges accordingly" do
240
232
  expect(subject.logger).to receive(:debug).with(/purging unmanaged content for environment/i)
241
- expect(subject.instance_variable_get(:@user_purge_allowlist)).to eq(['coolfile', 'coolfile2'])
233
+ expect(subject.settings[:overrides][:purging][:purge_allowlist]).to eq(['coolfile', 'coolfile2'])
242
234
  subject.call
243
235
  end
244
236
  end
@@ -246,9 +238,22 @@ describe R10K::Action::Deploy::Environment do
246
238
 
247
239
  describe "purge_levels" do
248
240
  let(:settings) { { deploy: { purge_levels: purge_levels } } }
241
+ let(:overrides) do
242
+ {
243
+ environments: {
244
+ requested_environments: ['PREFIX_first']
245
+ },
246
+ modules: {
247
+ deploy_modules: true
248
+ },
249
+ purging: {
250
+ purge_levels: purge_levels
251
+ }
252
+ }
253
+ end
249
254
 
250
255
  let(:deployment) do
251
- R10K::Deployment.new(mock_config.merge(settings))
256
+ R10K::Deployment.new(mock_config.merge({ overrides: overrides }))
252
257
  end
253
258
 
254
259
  before do
@@ -261,9 +266,13 @@ describe R10K::Action::Deploy::Environment do
261
266
  let(:purge_levels) { [:deployment] }
262
267
 
263
268
  it "only logs about purging deployment" do
269
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, env, &block|
270
+ expect(env.logger).to_not receive(:debug).with(/purging unmanaged puppetfile content/i)
271
+ original.call(env)
272
+ end.at_least(:once)
273
+
264
274
  expect(subject.logger).to receive(:debug).with(/purging unmanaged environments for deployment/i)
265
275
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged content for environment/i)
266
- expect(subject.logger).to_not receive(:debug).with(/purging unmanaged puppetfile content/i)
267
276
 
268
277
  subject.call
269
278
  end
@@ -273,15 +282,23 @@ describe R10K::Action::Deploy::Environment do
273
282
  let(:purge_levels) { [:environment] }
274
283
 
275
284
  it "only logs about purging environment" do
285
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, env, &block|
286
+ expect(env.logger).to_not receive(:debug).with(/purging unmanaged puppetfile content/i)
287
+ original.call(env)
288
+ end.at_least(:once)
276
289
  expect(subject.logger).to receive(:debug).with(/purging unmanaged content for environment/i)
277
290
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged environments for deployment/i)
278
- expect(subject.logger).to_not receive(:debug).with(/purging unmanaged puppetfile content/i)
279
291
 
280
292
  subject.call
281
293
  end
282
294
 
283
295
  it "logs that environment was not purged if deploy failed" do
284
- expect(subject).to receive(:visit_puppetfile) { subject.instance_variable_set(:@visit_ok, false) }
296
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, env, &block|
297
+ if env.name =~ /first/
298
+ expect(env).to receive(:deploy) { subject.instance_variable_set(:@visit_ok, false) }
299
+ end
300
+ original.call(env)
301
+ end.at_least(:once)
285
302
 
286
303
  expect(subject.logger).to receive(:debug).with(/not purging unmanaged content for environment/i)
287
304
 
@@ -293,7 +310,13 @@ describe R10K::Action::Deploy::Environment do
293
310
  let(:purge_levels) { [:puppetfile] }
294
311
 
295
312
  it "only logs about purging puppetfile" do
296
- expect(subject.logger).to receive(:debug).with(/purging unmanaged puppetfile content/i)
313
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, env, &block|
314
+ if env.name =~ /first/
315
+ expect(env.logger).to receive(:debug).with(/purging unmanaged puppetfile content/i)
316
+ end
317
+ original.call(env)
318
+ end.at_least(:once)
319
+
297
320
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged environments for deployment/i)
298
321
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged content for environment/i)
299
322
 
@@ -334,16 +357,19 @@ describe R10K::Action::Deploy::Environment do
334
357
  modules: true,
335
358
  'generate-types': true
336
359
  },
337
- %w[first second]
360
+ %w[first second],
361
+ {}
338
362
  )
339
363
  end
340
364
 
341
365
  it 'generate_types is true' do
342
- expect(subject.instance_variable_get(:@generate_types)).to eq(true)
366
+ expect(subject.settings[:overrides][:environments][:generate_types]).to eq(true)
343
367
  end
344
368
 
345
369
  it 'only calls puppet generate types on specified environment' do
346
- subject.instance_variable_set(:@argv, %w[first])
370
+ settings = subject.instance_variable_get(:@settings)
371
+ settings[:overrides][:environments][:requested_environments] = %w{first}
372
+ subject.instance_variable_set(:@settings, settings)
347
373
  expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
348
374
  if environment.dirname == 'first'
349
375
  expect(environment).to receive(:generate_types!)
@@ -356,8 +382,8 @@ describe R10K::Action::Deploy::Environment do
356
382
  end
357
383
 
358
384
  it 'does not call puppet generate types on puppetfile failure' do
359
- allow(subject).to receive(:visit_puppetfile) { subject.instance_variable_set(:@visit_ok, false) }
360
385
  expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
386
+ allow(environment).to receive(:deploy) { subject.instance_variable_set(:@visit_ok, false) }
361
387
  expect(environment).not_to receive(:generate_types!)
362
388
  original.call(environment, &block)
363
389
  end.twice
@@ -365,10 +391,11 @@ describe R10K::Action::Deploy::Environment do
365
391
  end
366
392
 
367
393
  it 'calls puppet generate types on previous puppetfile failure' do
368
- allow(subject).to receive(:visit_puppetfile) do |puppetfile|
369
- subject.instance_variable_set(:@visit_ok, false) if puppetfile.environment.dirname == 'first'
370
- end
371
394
  expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
395
+ allow(environment).to receive(:deploy) do
396
+ subject.instance_variable_set(:@visit_ok, false) if environment.dirname == 'first'
397
+ end
398
+
372
399
  if environment.dirname == 'second'
373
400
  expect(environment).to receive(:generate_types!)
374
401
  else
@@ -388,12 +415,13 @@ describe R10K::Action::Deploy::Environment do
388
415
  modules: true,
389
416
  'generate-types': false
390
417
  },
391
- %w[first]
418
+ %w[first],
419
+ {}
392
420
  )
393
421
  end
394
422
 
395
423
  it 'generate_types is false' do
396
- expect(subject.instance_variable_get(:@generate_types)).to eq(false)
424
+ expect(subject.settings[:overrides][:environments][:generate_types]).to eq(false)
397
425
  end
398
426
 
399
427
  it 'does not call puppet generate types' do
@@ -408,7 +436,7 @@ describe R10K::Action::Deploy::Environment do
408
436
 
409
437
  describe 'with puppet-path' do
410
438
 
411
- subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-path': '/nonexistent' }, []) }
439
+ subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-path': '/nonexistent' }, [], {}) }
412
440
 
413
441
  it 'sets puppet_path' do
414
442
  expect(subject.instance_variable_get(:@puppet_path)).to eq('/nonexistent')
@@ -417,7 +445,7 @@ describe R10K::Action::Deploy::Environment do
417
445
 
418
446
  describe 'with puppet-conf' do
419
447
 
420
- subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-conf': '/nonexistent' }, []) }
448
+ subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-conf': '/nonexistent' }, [], {}) }
421
449
 
422
450
  it 'sets puppet_conf' do
423
451
  expect(subject.instance_variable_get(:@puppet_conf)).to eq('/nonexistent')
@@ -426,7 +454,7 @@ describe R10K::Action::Deploy::Environment do
426
454
 
427
455
  describe 'with private-key' do
428
456
 
429
- subject { described_class.new({ config: '/some/nonexistent/path', 'private-key': '/nonexistent' }, []) }
457
+ subject { described_class.new({ config: '/some/nonexistent/path', 'private-key': '/nonexistent' }, [], {}) }
430
458
 
431
459
  it 'sets private_key' do
432
460
  expect(subject.instance_variable_get(:@private_key)).to eq('/nonexistent')
@@ -435,7 +463,7 @@ describe R10K::Action::Deploy::Environment do
435
463
 
436
464
  describe 'with oauth-token' do
437
465
 
438
- subject { described_class.new({ config: '/some/nonexistent/path', 'oauth-token': '/nonexistent' }, []) }
466
+ subject { described_class.new({ config: '/some/nonexistent/path', 'oauth-token': '/nonexistent' }, [], {}) }
439
467
 
440
468
  it 'sets oauth_token' do
441
469
  expect(subject.instance_variable_get(:@oauth_token)).to eq('/nonexistent')
@@ -453,7 +481,7 @@ describe R10K::Action::Deploy::Environment do
453
481
  def initialize(path, info)
454
482
  @path = path
455
483
  @info = info
456
- @puppetfile = R10K::Puppetfile.new
484
+ @puppetfile = R10K::Puppetfile.new("", {})
457
485
  end
458
486
  end
459
487
 
@@ -4,51 +4,51 @@ require 'r10k/action/deploy/module'
4
4
 
5
5
  describe R10K::Action::Deploy::Module do
6
6
 
7
- subject { described_class.new({config: "/some/nonexistent/path"}, []) }
7
+ subject { described_class.new({config: "/some/nonexistent/path"}, [], {}) }
8
8
 
9
9
  it_behaves_like "a deploy action that requires a config file"
10
10
  it_behaves_like "a deploy action that can be write locked"
11
11
 
12
12
  describe "initializing" do
13
13
  it "accepts an environment option" do
14
- described_class.new({environment: "production"}, [])
14
+ described_class.new({environment: "production"}, [], {})
15
15
  end
16
16
 
17
17
  it "can accept a no-force option" do
18
- described_class.new({:'no-force' => true}, [])
18
+ described_class.new({:'no-force' => true}, [], {})
19
19
  end
20
20
 
21
21
  it 'can accept a generate-types option' do
22
- described_class.new({ 'generate-types': true }, [])
22
+ described_class.new({ 'generate-types': true }, [], {})
23
23
  end
24
24
 
25
25
  it 'can accept a puppet-path option' do
26
- described_class.new({ 'puppet-path': '/nonexistent' }, [])
26
+ described_class.new({ 'puppet-path': '/nonexistent' }, [], {})
27
27
  end
28
28
 
29
29
  it 'can accept a puppet-conf option' do
30
- described_class.new({ 'puppet-conf': '/nonexistent' }, [])
30
+ described_class.new({ 'puppet-conf': '/nonexistent' }, [], {})
31
31
  end
32
32
 
33
33
  it 'can accept a cachedir option' do
34
- described_class.new({ cachedir: '/nonexistent' }, [])
34
+ described_class.new({ cachedir: '/nonexistent' }, [], {})
35
35
  end
36
36
 
37
37
  it 'can accept a private-key option' do
38
- described_class.new({ 'private-key': '/nonexistent' }, [])
38
+ described_class.new({ 'private-key': '/nonexistent' }, [], {})
39
39
  end
40
40
 
41
41
  it 'can accept a token option' do
42
- described_class.new({ 'oauth-token': '/nonexistent' }, [])
42
+ described_class.new({ 'oauth-token': '/nonexistent' }, [], {})
43
43
  end
44
44
  end
45
45
 
46
46
  describe "with no-force" do
47
47
 
48
- subject { described_class.new({ config: "/some/nonexistent/path", :'no-force' => true}, [] )}
48
+ subject { described_class.new({ config: "/some/nonexistent/path", :'no-force' => true}, [], {}) }
49
49
 
50
50
  it "tries to preserve local modifications" do
51
- expect(subject.force).to equal(false)
51
+ expect(subject.settings[:overrides][:modules][:force]).to equal(false)
52
52
  end
53
53
  end
54
54
 
@@ -76,33 +76,33 @@ describe R10K::Action::Deploy::Module do
76
76
  config: '/some/nonexistent/path',
77
77
  'generate-types': true
78
78
  },
79
- %w[first]
79
+ %w[first],
80
+ {}
80
81
  )
81
82
  end
82
83
 
83
84
  before do
85
+ @modules = []
84
86
  allow(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
85
- expect(environment.puppetfile).to receive(:modules).and_return(
86
- [R10K::Module::Local.new(environment.name, '/fakedir', [], environment)]
87
- )
87
+ mod = R10K::Module::Local.new(environment.name, '/fakedir', {}, environment)
88
+ if mod.name == 'first'
89
+ expect(environment).to receive(:generate_types!)
90
+ else
91
+ expect(environment).not_to receive(:generate_types!)
92
+ end
93
+ @modules << mod
94
+ expect(environment.puppetfile).to receive(:modules).and_return([mod]).twice
88
95
  original.call(environment, &block)
89
96
  end
90
97
  end
91
98
 
92
99
  it 'generate_types is true' do
93
- expect(subject.instance_variable_get(:@generate_types)).to eq(true)
100
+ expect(subject.settings[:overrides][:environments][:generate_types]).to eq(true)
94
101
  end
95
102
 
96
103
  it 'only calls puppet generate types on environments with specified module' do
97
- expect(subject).to receive(:visit_module).and_wrap_original do |original, mod, &block|
98
- if mod.name == 'first'
99
- expect(mod.environment).to receive(:generate_types!)
100
- else
101
- expect(mod.environment).not_to receive(:generate_types!)
102
- end
103
- original.call(mod, &block)
104
- end.twice
105
104
  subject.call
105
+ expect(@modules.length).to be(2)
106
106
  end
107
107
  end
108
108
 
@@ -113,12 +113,13 @@ describe R10K::Action::Deploy::Module do
113
113
  config: '/some/nonexistent/path',
114
114
  'generate-types': false
115
115
  },
116
- %w[first]
116
+ %w[first],
117
+ {}
117
118
  )
118
119
  end
119
120
 
120
121
  it 'generate_types is false' do
121
- expect(subject.instance_variable_get(:@generate_types)).to eq(false)
122
+ expect(subject.settings[:overrides][:environments][:generate_types]).to eq(false)
122
123
  end
123
124
 
124
125
  it 'does not call puppet generate types' do |it|
@@ -133,7 +134,7 @@ describe R10K::Action::Deploy::Module do
133
134
 
134
135
  describe 'with puppet-path' do
135
136
 
136
- subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-path': '/nonexistent' }, []) }
137
+ subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-path': '/nonexistent' }, [], {}) }
137
138
 
138
139
  it 'sets puppet_path' do
139
140
  expect(subject.instance_variable_get(:@puppet_path)).to eq('/nonexistent')
@@ -142,7 +143,7 @@ describe R10K::Action::Deploy::Module do
142
143
 
143
144
  describe 'with puppet-conf' do
144
145
 
145
- subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-conf': '/nonexistent' }, []) }
146
+ subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-conf': '/nonexistent' }, [], {}) }
146
147
 
147
148
  it 'sets puppet_conf' do
148
149
  expect(subject.instance_variable_get(:@puppet_conf)).to eq('/nonexistent')
@@ -151,7 +152,7 @@ describe R10K::Action::Deploy::Module do
151
152
 
152
153
  describe 'with cachedir' do
153
154
 
154
- subject { described_class.new({ config: '/some/nonexistent/path', cachedir: '/nonexistent' }, []) }
155
+ subject { described_class.new({ config: '/some/nonexistent/path', cachedir: '/nonexistent' }, [], {}) }
155
156
 
156
157
  it 'sets cachedir' do
157
158
  expect(subject.instance_variable_get(:@cachedir)).to eq('/nonexistent')
@@ -160,7 +161,7 @@ describe R10K::Action::Deploy::Module do
160
161
 
161
162
  describe 'with private-key' do
162
163
 
163
- subject { described_class.new({ config: '/some/nonexistent/path', 'private-key': '/nonexistent' }, []) }
164
+ subject { described_class.new({ config: '/some/nonexistent/path', 'private-key': '/nonexistent' }, [], {}) }
164
165
 
165
166
  it 'sets private_key' do
166
167
  expect(subject.instance_variable_get(:@private_key)).to eq('/nonexistent')
@@ -169,10 +170,117 @@ describe R10K::Action::Deploy::Module do
169
170
 
170
171
  describe 'with oauth-token' do
171
172
 
172
- subject { described_class.new({ config: '/some/nonexistent/path', 'oauth-token': '/nonexistent' }, []) }
173
+ subject { described_class.new({ config: '/some/nonexistent/path', 'oauth-token': '/nonexistent' }, [], {}) }
173
174
 
174
175
  it 'sets token_path' do
175
176
  expect(subject.instance_variable_get(:@oauth_token)).to eq('/nonexistent')
176
177
  end
177
178
  end
179
+
180
+ describe 'with modules' do
181
+
182
+ subject { described_class.new({ config: '/some/nonexistent/path' }, ['mod1', 'mod2'], {}) }
183
+
184
+ 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') }
186
+
187
+ it 'does not sync modules not given' do
188
+ allow(R10K::Deployment).to receive(:new).and_wrap_original do |original, settings, &block|
189
+ original.call(settings.merge({
190
+ sources: {
191
+ main: {
192
+ remote: 'git://not/a/remote',
193
+ basedir: '/not/a/basedir',
194
+ type: 'git'
195
+ }
196
+ }
197
+ }))
198
+ end
199
+
200
+ allow(R10K::Git::StatefulRepository).to receive(:new).and_return(repo)
201
+ allow(R10K::Git).to receive_message_chain(:cache, :generate).and_return(cache)
202
+ allow_any_instance_of(R10K::Source::Git).to receive(:branch_names).and_return([R10K::Environment::Name.new('first', {})])
203
+
204
+ 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' })
210
+ end
211
+
212
+ pf.modules.each do |mod|
213
+ if ['mod1', 'mod2'].include?(mod.name)
214
+ expect(mod.should_sync?).to be(true)
215
+ else
216
+ expect(mod.should_sync?).to be(false)
217
+ end
218
+ expect(mod).to receive(:sync).and_call_original
219
+ end
220
+
221
+ original.call(environment, &block)
222
+ end
223
+
224
+ expect(repo).to receive(:sync).twice
225
+
226
+ subject.call
227
+ end
228
+ end
229
+
230
+ describe 'with environments' do
231
+ subject { described_class.new({ config: '/some/nonexistent/path', environment: 'first' }, ['mod1'], {}) }
232
+
233
+ 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') }
235
+
236
+ it 'only syncs to the given environments' do
237
+ allow(R10K::Deployment).to receive(:new).and_wrap_original do |original, settings, &block|
238
+ original.call(settings.merge({
239
+ sources: {
240
+ main: {
241
+ remote: 'git://not/a/remote',
242
+ basedir: '/not/a/basedir',
243
+ type: 'git'
244
+ }
245
+ }
246
+ }))
247
+ end
248
+
249
+ allow(R10K::Git::StatefulRepository).to receive(:new).and_return(repo)
250
+ allow(R10K::Git).to receive_message_chain(:cache, :generate).and_return(cache)
251
+ allow_any_instance_of(R10K::Source::Git).to receive(:branch_names).and_return([R10K::Environment::Name.new('first', {}),
252
+ R10K::Environment::Name.new('second', {})])
253
+
254
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
255
+ pf = environment.puppetfile
256
+
257
+ 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' })
261
+ end
262
+
263
+ pf.modules.each do |mod|
264
+ if mod.name == 'mod1'
265
+ expect(mod.should_sync?).to be(true)
266
+ else
267
+ expect(mod.should_sync?).to be(false)
268
+ end
269
+ expect(mod).to receive(:sync).and_call_original
270
+ end
271
+ else
272
+ expect(pf).not_to receive(:load)
273
+ end
274
+
275
+ original.call(environment, &block)
276
+ end.twice
277
+
278
+ expect(repo).to receive(:sync).once
279
+ expect(subject.logger).to receive(:debug1).with(/Updating modules.*in environment.*first/i)
280
+ expect(subject.logger).to receive(:debug1).with(/skipping environment.*second/i)
281
+
282
+ subject.call
283
+ end
284
+ end
178
285
  end
286
+