r10k 3.5.2 → 3.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +4 -1
  3. data/.github/workflows/docker.yml +4 -1
  4. data/.github/workflows/release.yml +3 -2
  5. data/.github/workflows/rspec_tests.yml +81 -0
  6. data/.github/workflows/stale.yml +19 -0
  7. data/.travis.yml +8 -1
  8. data/CHANGELOG.mkd +43 -1
  9. data/CODEOWNERS +2 -2
  10. data/README.mkd +13 -4
  11. data/doc/common-patterns.mkd +1 -0
  12. data/doc/dynamic-environments/configuration.mkd +149 -45
  13. data/doc/dynamic-environments/usage.mkd +12 -11
  14. data/doc/puppetfile.mkd +23 -3
  15. data/docker/Gemfile +1 -1
  16. data/docker/Makefile +7 -4
  17. data/docker/docker-compose.yml +18 -0
  18. data/docker/r10k/Dockerfile +4 -3
  19. data/docker/r10k/docker-entrypoint.sh +0 -1
  20. data/docker/r10k/release.Dockerfile +3 -2
  21. data/docker/spec/dockerfile_spec.rb +26 -32
  22. data/integration/tests/git_source/git_source_repeated_remote.rb +68 -0
  23. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module.rb +2 -1
  24. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module_static.rb +2 -1
  25. data/integration/tests/user_scenario/basic_workflow/multi_source_custom_forge_git_module.rb +1 -1
  26. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_git_module.rb +2 -1
  27. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +1 -1
  28. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +1 -1
  29. data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +1 -1
  30. data/lib/r10k/action/base.rb +8 -1
  31. data/lib/r10k/action/deploy/display.rb +46 -10
  32. data/lib/r10k/action/deploy/environment.rb +98 -50
  33. data/lib/r10k/action/deploy/module.rb +51 -29
  34. data/lib/r10k/action/puppetfile/check.rb +3 -1
  35. data/lib/r10k/action/puppetfile/install.rb +20 -23
  36. data/lib/r10k/action/puppetfile/purge.rb +8 -2
  37. data/lib/r10k/action/runner.rb +34 -0
  38. data/lib/r10k/cli/deploy.rb +14 -7
  39. data/lib/r10k/cli/puppetfile.rb +5 -5
  40. data/lib/r10k/content_synchronizer.rb +83 -0
  41. data/lib/r10k/deployment.rb +1 -1
  42. data/lib/r10k/environment/base.rb +30 -3
  43. data/lib/r10k/environment/git.rb +17 -5
  44. data/lib/r10k/environment/name.rb +22 -4
  45. data/lib/r10k/environment/svn.rb +11 -4
  46. data/lib/r10k/environment/with_modules.rb +46 -30
  47. data/lib/r10k/git.rb +1 -0
  48. data/lib/r10k/git/cache.rb +12 -4
  49. data/lib/r10k/git/rugged/credentials.rb +39 -2
  50. data/lib/r10k/git/stateful_repository.rb +4 -0
  51. data/lib/r10k/initializers.rb +2 -0
  52. data/lib/r10k/module.rb +1 -1
  53. data/lib/r10k/module/base.rb +25 -1
  54. data/lib/r10k/module/forge.rb +29 -11
  55. data/lib/r10k/module/git.rb +54 -27
  56. data/lib/r10k/module/local.rb +2 -1
  57. data/lib/r10k/module/svn.rb +24 -18
  58. data/lib/r10k/puppetfile.rb +75 -72
  59. data/lib/r10k/settings.rb +30 -3
  60. data/lib/r10k/source/base.rb +9 -0
  61. data/lib/r10k/source/git.rb +40 -9
  62. data/lib/r10k/source/hash.rb +5 -5
  63. data/lib/r10k/source/svn.rb +5 -3
  64. data/lib/r10k/util/cleaner.rb +21 -0
  65. data/lib/r10k/util/setopts.rb +33 -12
  66. data/lib/r10k/version.rb +1 -1
  67. data/locales/r10k.pot +103 -83
  68. data/r10k.gemspec +1 -1
  69. data/spec/fixtures/unit/action/r10k_creds.yaml +9 -0
  70. data/spec/r10k-mocks/mock_source.rb +1 -1
  71. data/spec/shared-examples/puppetfile-action.rb +7 -7
  72. data/spec/shared-examples/subprocess-runner.rb +11 -5
  73. data/spec/unit/action/deploy/display_spec.rb +35 -5
  74. data/spec/unit/action/deploy/environment_spec.rb +207 -37
  75. data/spec/unit/action/deploy/module_spec.rb +173 -26
  76. data/spec/unit/action/puppetfile/check_spec.rb +2 -2
  77. data/spec/unit/action/puppetfile/install_spec.rb +32 -10
  78. data/spec/unit/action/puppetfile/purge_spec.rb +25 -5
  79. data/spec/unit/action/runner_spec.rb +48 -1
  80. data/spec/unit/environment/git_spec.rb +19 -2
  81. data/spec/unit/environment/name_spec.rb +28 -0
  82. data/spec/unit/environment/svn_spec.rb +12 -0
  83. data/spec/unit/environment/with_modules_spec.rb +74 -0
  84. data/spec/unit/git/cache_spec.rb +10 -0
  85. data/spec/unit/git/rugged/credentials_spec.rb +79 -2
  86. data/spec/unit/git_spec.rb +3 -3
  87. data/spec/unit/module/forge_spec.rb +21 -13
  88. data/spec/unit/module/git_spec.rb +64 -1
  89. data/spec/unit/module_spec.rb +60 -10
  90. data/spec/unit/puppetfile_spec.rb +98 -30
  91. data/spec/unit/settings_spec.rb +12 -0
  92. data/spec/unit/source/git_spec.rb +49 -1
  93. data/spec/unit/util/purgeable_spec.rb +2 -8
  94. data/spec/unit/util/setopts_spec.rb +25 -1
  95. metadata +12 -11
  96. data/azure-pipelines.yml +0 -86
data/r10k.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.license = 'Apache-2.0'
24
24
 
25
25
  s.add_dependency 'colored2', '3.1.2'
26
- s.add_dependency 'cri', ['>= 2.15.10', '< 3.0.0']
26
+ s.add_dependency 'cri', '2.15.10'
27
27
 
28
28
  s.add_dependency 'log4r', '1.1.10'
29
29
  s.add_dependency 'multi_json', '~> 1.10'
@@ -0,0 +1,9 @@
1
+ ---
2
+ git:
3
+ private_key: '/global/config/private/key'
4
+ oauth_token: '/global/config/oauth/token'
5
+ repositories:
6
+ - remote: 'git@myfakegitserver.com:user/repo.git'
7
+ private_key: '/config/private/key'
8
+ - remote: 'https://myfakegitserver.com/user/repo.git'
9
+ oauth_token: '/config/oauth/token'
@@ -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
@@ -32,23 +32,29 @@ shared_examples_for "a subprocess runner" do |fixture_root|
32
32
  end
33
33
  end
34
34
 
35
- describe "running 'ls' with a different working directory" do
35
+ describe "running 'ls' or 'dir' with a different working directory" do
36
36
  subject do
37
- described_class.new(%w[ls]).tap do |o|
38
- o.cwd = fixture_root
37
+ if R10K::Util::Platform.windows?
38
+ described_class.new(%w[cmd /c dir]).tap do |o|
39
+ o.cwd = fixture_root
40
+ end
41
+ else
42
+ described_class.new(%w[ls]).tap do |o|
43
+ o.cwd = fixture_root
44
+ end
39
45
  end
40
46
  end
41
47
 
42
48
  it "returns the contents of the given working directory" do
43
49
  result = subject.run
44
- expect(result.stdout).to eq 'no-execute.sh'
50
+ expect(result.stdout).to match('no-execute.sh')
45
51
  end
46
52
  end
47
53
 
48
54
  describe "running 'false'" do
49
55
  subject { described_class.new(%w[false]) }
50
56
 
51
- it "sets the exit code to 1" do
57
+ it "sets the exit code to 1", unless: R10K::Util::Platform.windows? do
52
58
  result = subject.run
53
59
  expect(result.exit_code).to eq 1
54
60
  end
@@ -5,27 +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
+ end
10
+
11
+ it "accepts a modules option" do
12
+ described_class.new({modules: true}, [], {})
9
13
  end
10
14
 
11
15
  it "accepts a detail option" do
12
- described_class.new({detail: true}, [])
16
+ described_class.new({detail: true}, [], {})
13
17
  end
14
18
 
15
19
  it "accepts a format option" do
16
- described_class.new({format: "json"}, [])
20
+ described_class.new({format: "json"}, [], {})
17
21
  end
18
22
 
19
23
  it "accepts a fetch option" do
20
- described_class.new({fetch: true}, [])
24
+ described_class.new({fetch: true}, [], {})
21
25
  end
22
26
  end
23
27
 
24
- subject { described_class.new({config: "/some/nonexistent/path"}, []) }
28
+ subject { described_class.new({config: "/some/nonexistent/path"}, [], {}) }
25
29
 
26
30
  before do
27
31
  allow(subject).to receive(:puts)
28
32
  end
29
33
 
30
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
31
61
  end
@@ -5,37 +5,58 @@ 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
+ end
21
+
22
+ it "can accept a modules option" do
23
+ described_class.new({modules: true}, [], {})
20
24
  end
21
25
 
22
26
  it "can accept a default_branch_override option" do
23
- described_class.new({:'default-branch-override' => 'default_branch_override_name'}, [])
27
+ described_class.new({:'default-branch-override' => 'default_branch_override_name'}, [], {})
24
28
  end
25
29
 
26
30
  it "can accept a no-force option" do
27
- described_class.new({:'no-force' => true}, [])
31
+ described_class.new({:'no-force' => true}, [], {})
28
32
  end
29
33
 
30
- it "normalizes environment names in the arg vector"
31
-
32
34
  it 'can accept a generate-types option' do
33
- described_class.new({ 'generate-types': true }, [])
35
+ described_class.new({ 'generate-types': true }, [], {})
34
36
  end
35
37
 
36
38
  it 'can accept a puppet-path option' do
37
- described_class.new({ 'puppet-path': '/nonexistent' }, [])
39
+ described_class.new({ 'puppet-path': '/nonexistent' }, [], {})
40
+ end
41
+
42
+ it 'can accept a private-key option' do
43
+ described_class.new({ 'private-key': '/nonexistent' }, [], {})
44
+ end
45
+
46
+ it 'can accept a token option' do
47
+ described_class.new({ 'oauth-token': '/nonexistent' }, [], {})
48
+ end
49
+
50
+ describe "initializing errors" do
51
+ let (:settings) { { deploy: { purge_levels: [:environment],
52
+ purge_whitelist: ['coolfile', 'coolfile2'],
53
+ purge_allowlist: ['anothercoolfile']}}}
54
+
55
+ subject { described_class.new({config: "/some/nonexistent/path"}, [], settings)}
56
+ it 'errors out when both purge_whitelist and purge_allowlist are set' do
57
+ expect{subject}.to raise_error(R10K::Error, /Values found for both purge_whitelist and purge_allowlist./)
38
58
  end
59
+ end
39
60
  end
40
61
 
41
62
  describe "when called" do
@@ -52,6 +73,29 @@ describe R10K::Action::Deploy::Environment do
52
73
  )
53
74
  end
54
75
 
76
+ describe "with puppetfile or modules flag" do
77
+ let(:deployment) { R10K::Deployment.new(mock_config) }
78
+ let(:puppetfile) { instance_double("R10K::Puppetfile", modules: []).as_null_object }
79
+
80
+ before do
81
+ expect(R10K::Deployment).to receive(:new).and_return(deployment)
82
+ expect(R10K::Puppetfile).to receive(:new).and_return(puppetfile).at_least(:once)
83
+ end
84
+
85
+ it "syncs the puppetfile when given the puppetfile flag" do
86
+ expect(puppetfile).to receive(:sync)
87
+ action = described_class.new({config: "/some/nonexistent/path", puppetfile: true}, [], {})
88
+ action.call
89
+ end
90
+
91
+ it "syncs the puppetfile when given the modules flag" do
92
+ expect(puppetfile).to receive(:sync)
93
+ action = described_class.new({config: "/some/nonexistent/path", modules: true}, [], {})
94
+ action.call
95
+ end
96
+
97
+ end
98
+
55
99
  describe "with an environment that doesn't exist" do
56
100
  let(:deployment) do
57
101
  R10K::Deployment.new(mock_config)
@@ -61,7 +105,7 @@ describe R10K::Action::Deploy::Environment do
61
105
  expect(R10K::Deployment).to receive(:new).and_return(deployment)
62
106
  end
63
107
 
64
- 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], {}) }
65
109
 
66
110
  it "logs that the environments can't be deployed and returns false" do
67
111
  expect(subject.logger).to receive(:error).with("Environment(s) 'not_an_environment' cannot be found in any source and will not be deployed.")
@@ -71,10 +115,10 @@ describe R10K::Action::Deploy::Environment do
71
115
  end
72
116
 
73
117
  describe "with no-force" do
74
- subject { described_class.new({ config: "/some/nonexistent/path", puppetfile: true, :'no-force' => true}, %w[first]) }
118
+ subject { described_class.new({ config: "/some/nonexistent/path", modules: true, :'no-force' => true}, %w[first], {}) }
75
119
 
76
120
  it "tries to preserve local modifications" do
77
- expect(subject.force).to equal(false)
121
+ expect(subject.settings[:overrides][:modules][:force]).to equal(false)
78
122
  end
79
123
  end
80
124
 
@@ -162,26 +206,73 @@ describe R10K::Action::Deploy::Environment do
162
206
  end
163
207
  end
164
208
 
209
+ describe "Purging white/allowlist" do
210
+
211
+ let(:settings) { { deploy: { purge_levels: [:environment], purge_allowlist: ['coolfile', 'coolfile2'] } } }
212
+ let(:overrides) { { environments: {}, modules: {}, purging: { purge_levels: [:environment], purge_allowlist: ['coolfile', 'coolfile2'] } } }
213
+ let(:deployment) do
214
+ R10K::Deployment.new(mock_config.merge(overrides))
215
+ end
216
+ before do
217
+ expect(R10K::Deployment).to receive(:new).and_return(deployment)
218
+ end
219
+
220
+ subject { described_class.new({ config: "/some/nonexistent/path", modules: true }, %w[PREFIX_first], settings) }
221
+
222
+ it "reads in the purge_allowlist setting and purges accordingly" do
223
+ expect(subject.logger).to receive(:debug).with(/purging unmanaged content for environment/i)
224
+ expect(subject.settings[:overrides][:purging][:purge_allowlist]).to eq(['coolfile', 'coolfile2'])
225
+ subject.call
226
+ end
227
+
228
+ describe "purge_whitelist" do
229
+ let (:settings) { { deploy: { purge_levels: [:environment], purge_whitelist: ['coolfile', 'coolfile2'] } } }
230
+
231
+ it "reads in the purge_whitelist setting and still sets it to purge_allowlist and purges accordingly" do
232
+ expect(subject.logger).to receive(:debug).with(/purging unmanaged content for environment/i)
233
+ expect(subject.settings[:overrides][:purging][:purge_allowlist]).to eq(['coolfile', 'coolfile2'])
234
+ subject.call
235
+ end
236
+ end
237
+ end
238
+
165
239
  describe "purge_levels" do
166
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
167
254
 
168
255
  let(:deployment) do
169
- R10K::Deployment.new(mock_config.merge(settings))
256
+ R10K::Deployment.new(mock_config.merge({ overrides: overrides }))
170
257
  end
171
258
 
172
259
  before do
173
260
  expect(R10K::Deployment).to receive(:new).and_return(deployment)
174
261
  end
175
262
 
176
- subject { described_class.new({ config: "/some/nonexistent/path", puppetfile: true }, %w[PREFIX_first], settings) }
263
+ subject { described_class.new({ config: "/some/nonexistent/path", modules: true }, %w[PREFIX_first], settings) }
177
264
 
178
265
  describe "deployment purge level" do
179
266
  let(:purge_levels) { [:deployment] }
180
267
 
181
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
+
182
274
  expect(subject.logger).to receive(:debug).with(/purging unmanaged environments for deployment/i)
183
275
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged content for environment/i)
184
- expect(subject.logger).to_not receive(:debug).with(/purging unmanaged puppetfile content/i)
185
276
 
186
277
  subject.call
187
278
  end
@@ -191,15 +282,23 @@ describe R10K::Action::Deploy::Environment do
191
282
  let(:purge_levels) { [:environment] }
192
283
 
193
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)
194
289
  expect(subject.logger).to receive(:debug).with(/purging unmanaged content for environment/i)
195
290
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged environments for deployment/i)
196
- expect(subject.logger).to_not receive(:debug).with(/purging unmanaged puppetfile content/i)
197
291
 
198
292
  subject.call
199
293
  end
200
294
 
201
295
  it "logs that environment was not purged if deploy failed" do
202
- 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)
203
302
 
204
303
  expect(subject.logger).to receive(:debug).with(/not purging unmanaged content for environment/i)
205
304
 
@@ -211,7 +310,13 @@ describe R10K::Action::Deploy::Environment do
211
310
  let(:purge_levels) { [:puppetfile] }
212
311
 
213
312
  it "only logs about purging puppetfile" do
214
- 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
+
215
320
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged environments for deployment/i)
216
321
  expect(subject.logger).to_not receive(:debug).with(/purging unmanaged content for environment/i)
217
322
 
@@ -219,6 +324,7 @@ describe R10K::Action::Deploy::Environment do
219
324
  end
220
325
  end
221
326
  end
327
+
222
328
  describe "generate-types" do
223
329
  let(:deployment) do
224
330
  R10K::Deployment.new(
@@ -248,19 +354,22 @@ describe R10K::Action::Deploy::Environment do
248
354
  described_class.new(
249
355
  {
250
356
  config: '/some/nonexistent/path',
251
- puppetfile: true,
357
+ modules: true,
252
358
  'generate-types': true
253
359
  },
254
- %w[first second]
360
+ %w[first second],
361
+ {}
255
362
  )
256
363
  end
257
364
 
258
365
  it 'generate_types is true' do
259
- expect(subject.instance_variable_get(:@generate_types)).to eq(true)
366
+ expect(subject.settings[:overrides][:environments][:generate_types]).to eq(true)
260
367
  end
261
368
 
262
369
  it 'only calls puppet generate types on specified environment' do
263
- 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)
264
373
  expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
265
374
  if environment.dirname == 'first'
266
375
  expect(environment).to receive(:generate_types!)
@@ -273,8 +382,8 @@ describe R10K::Action::Deploy::Environment do
273
382
  end
274
383
 
275
384
  it 'does not call puppet generate types on puppetfile failure' do
276
- allow(subject).to receive(:visit_puppetfile) { subject.instance_variable_set(:@visit_ok, false) }
277
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) }
278
387
  expect(environment).not_to receive(:generate_types!)
279
388
  original.call(environment, &block)
280
389
  end.twice
@@ -282,10 +391,11 @@ describe R10K::Action::Deploy::Environment do
282
391
  end
283
392
 
284
393
  it 'calls puppet generate types on previous puppetfile failure' do
285
- allow(subject).to receive(:visit_puppetfile) do |puppetfile|
286
- subject.instance_variable_set(:@visit_ok, false) if puppetfile.environment.dirname == 'first'
287
- end
288
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
+
289
399
  if environment.dirname == 'second'
290
400
  expect(environment).to receive(:generate_types!)
291
401
  else
@@ -302,15 +412,16 @@ describe R10K::Action::Deploy::Environment do
302
412
  described_class.new(
303
413
  {
304
414
  config: '/some/nonexistent/path',
305
- puppetfile: true,
415
+ modules: true,
306
416
  'generate-types': false
307
417
  },
308
- %w[first]
418
+ %w[first],
419
+ {}
309
420
  )
310
421
  end
311
422
 
312
423
  it 'generate_types is false' do
313
- expect(subject.instance_variable_get(:@generate_types)).to eq(false)
424
+ expect(subject.settings[:overrides][:environments][:generate_types]).to eq(false)
314
425
  end
315
426
 
316
427
  it 'does not call puppet generate types' do
@@ -325,12 +436,39 @@ describe R10K::Action::Deploy::Environment do
325
436
 
326
437
  describe 'with puppet-path' do
327
438
 
328
- subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-path': '/nonexistent' }, []) }
439
+ subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-path': '/nonexistent' }, [], {}) }
329
440
 
330
441
  it 'sets puppet_path' do
331
442
  expect(subject.instance_variable_get(:@puppet_path)).to eq('/nonexistent')
332
443
  end
333
444
  end
445
+
446
+ describe 'with puppet-conf' do
447
+
448
+ subject { described_class.new({ config: '/some/nonexistent/path', 'puppet-conf': '/nonexistent' }, [], {}) }
449
+
450
+ it 'sets puppet_conf' do
451
+ expect(subject.instance_variable_get(:@puppet_conf)).to eq('/nonexistent')
452
+ end
453
+ end
454
+
455
+ describe 'with private-key' do
456
+
457
+ subject { described_class.new({ config: '/some/nonexistent/path', 'private-key': '/nonexistent' }, [], {}) }
458
+
459
+ it 'sets private_key' do
460
+ expect(subject.instance_variable_get(:@private_key)).to eq('/nonexistent')
461
+ end
462
+ end
463
+
464
+ describe 'with oauth-token' do
465
+
466
+ subject { described_class.new({ config: '/some/nonexistent/path', 'oauth-token': '/nonexistent' }, [], {}) }
467
+
468
+ it 'sets oauth_token' do
469
+ expect(subject.instance_variable_get(:@oauth_token)).to eq('/nonexistent')
470
+ end
471
+ end
334
472
  end
335
473
 
336
474
  describe "write_environment_info!" do
@@ -343,15 +481,31 @@ describe R10K::Action::Deploy::Environment do
343
481
  def initialize(path, info)
344
482
  @path = path
345
483
  @info = info
346
- @puppetfile = R10K::Puppetfile.new
484
+ @puppetfile = R10K::Puppetfile.new("", {})
347
485
  end
348
486
  end
349
487
 
350
488
  let(:mock_stateful_repo_1) { instance_double("R10K::Git::StatefulRepository", :head => "123456") }
351
489
  let(:mock_stateful_repo_2) { instance_double("R10K::Git::StatefulRepository", :head => "654321") }
352
- let(:mock_git_module_1) { instance_double("R10K::Module::Git", :name => "my_cool_module", :version => "1.0", :repo => mock_stateful_repo_1) }
353
- let(:mock_git_module_2) { instance_double("R10K::Module::Git", :name => "my_lame_module", :version => "0.0.1", :repo => mock_stateful_repo_2) }
354
- let(:mock_forge_module_1) { double(:name => "their_shiny_module", :version => "2.0.0") }
490
+ let(:mock_git_module_1) do
491
+ instance_double("R10K::Module::Git",
492
+ :name => "my_cool_module",
493
+ :properties => {
494
+ :type => :git,
495
+ :expected => "1.0",
496
+ :actual => mock_stateful_repo_1.head
497
+ })
498
+ end
499
+ let(:mock_git_module_2) do
500
+ instance_double("R10K::Module::Git",
501
+ :name => "my_uncool_module",
502
+ :properties => {
503
+ :type => :git,
504
+ :expected => "0.0.1",
505
+ :actual => mock_stateful_repo_2.head
506
+ })
507
+ end
508
+ let(:mock_forge_module_1) { double(:name => "their_shiny_module", :properties => { :expected => "2.0.0" }) }
355
509
  let(:mock_puppetfile) { instance_double("R10K::Puppetfile", :modules => [mock_git_module_1, mock_git_module_2, mock_forge_module_1]) }
356
510
 
357
511
  before(:all) do
@@ -364,9 +518,8 @@ describe R10K::Action::Deploy::Environment do
364
518
  Dir.delete(@tmp_path)
365
519
  end
366
520
 
367
- it "writes the .r10k-deploy file correctly" do
521
+ it "writes the .r10k-deploy file correctly if all goes well" do
368
522
  allow(R10K::Puppetfile).to receive(:new).and_return(mock_puppetfile)
369
- allow(mock_forge_module_1).to receive(:repo).and_raise(NoMethodError)
370
523
 
371
524
  fake_env = Fake_Environment.new(@tmp_path, {:name => "my_cool_environment", :signature => "pablo picasso"})
372
525
  allow(fake_env).to receive(:modules).and_return(mock_puppetfile.modules)
@@ -383,13 +536,30 @@ describe R10K::Action::Deploy::Environment do
383
536
  expect(r10k_deploy['module_deploys'][0]['name']).to eq("my_cool_module")
384
537
  expect(r10k_deploy['module_deploys'][0]['version']).to eq("1.0")
385
538
  expect(r10k_deploy['module_deploys'][0]['sha']).to eq("123456")
386
- expect(r10k_deploy['module_deploys'][1]['name']).to eq("my_lame_module")
539
+ expect(r10k_deploy['module_deploys'][1]['name']).to eq("my_uncool_module")
387
540
  expect(r10k_deploy['module_deploys'][1]['version']).to eq("0.0.1")
388
541
  expect(r10k_deploy['module_deploys'][1]['sha']).to eq("654321")
389
542
  expect(r10k_deploy['module_deploys'][2]['name']).to eq("their_shiny_module")
390
543
  expect(r10k_deploy['module_deploys'][2]['version']).to eq("2.0.0")
391
544
  expect(r10k_deploy['module_deploys'][2]['sha']).to eq(nil)
545
+ end
546
+
547
+ it "writes the .r10k-deploy file correctly if there's a failure" do
548
+ allow(R10K::Puppetfile).to receive(:new).and_return(mock_puppetfile)
549
+
550
+ fake_env = Fake_Environment.new(@tmp_path, {:name => "my_cool_environment", :signature => "pablo picasso"})
551
+ allow(fake_env).to receive(:modules).and_return(mock_puppetfile.modules)
552
+ allow(mock_forge_module_1).to receive(:properties).and_raise(StandardError)
553
+ subject.send(:write_environment_info!, fake_env, "2019-01-01 23:23:22 +0000", true)
554
+
555
+ file_contents = File.read("#{@tmp_path}/.r10k-deploy.json")
556
+ r10k_deploy = JSON.parse(file_contents)
392
557
 
558
+ expect(r10k_deploy['name']).to eq("my_cool_environment")
559
+ expect(r10k_deploy['signature']).to eq("pablo picasso")
560
+ expect(r10k_deploy['started_at']).to eq("2019-01-01 23:23:22 +0000")
561
+ expect(r10k_deploy['deploy_success']).to eq(true)
562
+ expect(r10k_deploy['module_deploys'].length).to eq(0)
393
563
  end
394
564
  end
395
565
  end