r10k 3.9.0 → 3.9.1

Sign up to get free protection for your applications and to get access to all the features.
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
+