r10k 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +1 -1
  3. data/.github/workflows/rspec_tests.yml +1 -1
  4. data/.github/workflows/stale.yml +19 -0
  5. data/CHANGELOG.mkd +24 -0
  6. data/doc/dynamic-environments/configuration.mkd +13 -6
  7. data/integration/Rakefile +1 -1
  8. data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +3 -9
  9. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +8 -14
  10. data/lib/r10k/action/base.rb +10 -0
  11. data/lib/r10k/action/deploy/display.rb +42 -9
  12. data/lib/r10k/action/deploy/environment.rb +70 -41
  13. data/lib/r10k/action/deploy/module.rb +51 -29
  14. data/lib/r10k/action/puppetfile/check.rb +3 -1
  15. data/lib/r10k/action/puppetfile/install.rb +20 -23
  16. data/lib/r10k/action/puppetfile/purge.rb +8 -2
  17. data/lib/r10k/action/runner.rb +11 -6
  18. data/lib/r10k/content_synchronizer.rb +83 -0
  19. data/lib/r10k/deployment.rb +1 -1
  20. data/lib/r10k/environment/base.rb +21 -1
  21. data/lib/r10k/environment/git.rb +0 -3
  22. data/lib/r10k/environment/svn.rb +4 -6
  23. data/lib/r10k/environment/with_modules.rb +18 -10
  24. data/lib/r10k/git/cache.rb +1 -1
  25. data/lib/r10k/initializers.rb +7 -0
  26. data/lib/r10k/module.rb +1 -1
  27. data/lib/r10k/module/base.rb +17 -1
  28. data/lib/r10k/module/forge.rb +29 -19
  29. data/lib/r10k/module/git.rb +23 -14
  30. data/lib/r10k/module/local.rb +1 -0
  31. data/lib/r10k/module/svn.rb +12 -9
  32. data/lib/r10k/module_loader/puppetfile.rb +195 -0
  33. data/lib/r10k/module_loader/puppetfile/dsl.rb +37 -0
  34. data/lib/r10k/puppetfile.rb +111 -202
  35. data/lib/r10k/settings.rb +3 -0
  36. data/lib/r10k/source/base.rb +14 -0
  37. data/lib/r10k/source/git.rb +19 -6
  38. data/lib/r10k/source/hash.rb +1 -3
  39. data/lib/r10k/source/svn.rb +4 -2
  40. data/lib/r10k/util/cleaner.rb +21 -0
  41. data/lib/r10k/util/purgeable.rb +70 -8
  42. data/lib/r10k/version.rb +1 -1
  43. data/locales/r10k.pot +67 -71
  44. data/spec/fixtures/unit/action/r10k_forge_auth.yaml +4 -0
  45. data/spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml +3 -0
  46. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_subdir_2/ignored_1 +0 -0
  47. data/spec/fixtures/unit/util/purgeable/managed_two/.hidden/unmanaged_3 +0 -0
  48. data/spec/r10k-mocks/mock_source.rb +1 -1
  49. data/spec/shared-examples/puppetfile-action.rb +7 -7
  50. data/spec/unit/action/deploy/display_spec.rb +32 -6
  51. data/spec/unit/action/deploy/environment_spec.rb +85 -48
  52. data/spec/unit/action/deploy/module_spec.rb +163 -31
  53. data/spec/unit/action/puppetfile/check_spec.rb +2 -2
  54. data/spec/unit/action/puppetfile/install_spec.rb +31 -10
  55. data/spec/unit/action/puppetfile/purge_spec.rb +25 -5
  56. data/spec/unit/action/runner_spec.rb +49 -25
  57. data/spec/unit/git/cache_spec.rb +14 -0
  58. data/spec/unit/module/forge_spec.rb +23 -14
  59. data/spec/unit/module/git_spec.rb +8 -8
  60. data/spec/unit/module_loader/puppetfile_spec.rb +330 -0
  61. data/spec/unit/module_spec.rb +22 -5
  62. data/spec/unit/puppetfile_spec.rb +123 -203
  63. data/spec/unit/settings_spec.rb +6 -2
  64. data/spec/unit/util/purgeable_spec.rb +40 -14
  65. metadata +12 -2
@@ -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,141 @@ 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', tracked_paths: []) }
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
+ # For this test we want to have realistic Modules and access to
206
+ # their internal Repos to validate the sync. Unfortunately, to
207
+ # do so we do some invasive mocking, effectively implementing
208
+ # our own R10K::Puppetfile#load. We directly update the Puppetfile's
209
+ # internal ModuleLoader and then call `load` on it so it will create
210
+ # the correct loaded_content.
211
+ puppetfile = environment.puppetfile
212
+ loader = puppetfile.loader
213
+ expect(puppetfile).to receive(:load) do
214
+ loader.add_module('mod1', { git: 'git://remote' })
215
+ loader.add_module('mod2', { git: 'git://remote' })
216
+ loader.add_module('mod3', { git: 'git://remote' })
217
+
218
+ allow(loader).to receive(:puppetfile_content).and_return('')
219
+ loaded_content = loader.load
220
+ puppetfile.instance_variable_set(:@loaded_content, loaded_content)
221
+ puppetfile.instance_variable_set(:@loaded, true)
222
+ end
223
+
224
+ puppetfile.modules.each do |mod|
225
+ if ['mod1', 'mod2'].include?(mod.name)
226
+ expect(mod.should_sync?).to be(true)
227
+ else
228
+ expect(mod.should_sync?).to be(false)
229
+ end
230
+ expect(mod).to receive(:sync).and_call_original
231
+ end
232
+
233
+ original.call(environment, &block)
234
+ end
235
+
236
+ expect(repo).to receive(:sync).twice
237
+
238
+ subject.call
239
+ end
240
+ end
241
+
242
+ describe 'with environments' do
243
+ subject { described_class.new({ config: '/some/nonexistent/path', environment: 'first' }, ['mod1'], {}) }
244
+
245
+ let(:cache) { instance_double("R10K::Git::Cache", 'sanitized_dirname' => 'foo', 'cached?' => true, 'sync' => true) }
246
+ let(:repo) { instance_double("R10K::Git::StatefulRepository", cache: cache, resolve: 'main', tracked_paths: []) }
247
+
248
+ it 'only syncs to the given environments' do
249
+ allow(R10K::Deployment).to receive(:new).and_wrap_original do |original, settings, &block|
250
+ original.call(settings.merge({
251
+ sources: {
252
+ main: {
253
+ remote: 'git://not/a/remote',
254
+ basedir: '/not/a/basedir',
255
+ type: 'git'
256
+ }
257
+ }
258
+ }))
259
+ end
260
+
261
+ allow(R10K::Git::StatefulRepository).to receive(:new).and_return(repo)
262
+ allow(R10K::Git).to receive_message_chain(:cache, :generate).and_return(cache)
263
+ allow_any_instance_of(R10K::Source::Git).to receive(:branch_names).and_return([R10K::Environment::Name.new('first', {}),
264
+ R10K::Environment::Name.new('second', {})])
265
+
266
+ expect(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
267
+ puppetfile = environment.puppetfile
268
+
269
+ if environment.name == 'first'
270
+ # For this test we want to have realistic Modules and access to
271
+ # their internal Repos to validate the sync. Unfortunately, to
272
+ # do so we do some invasive mocking, effectively implementing
273
+ # our own R10K::Puppetfile#load. We directly update the Puppetfile's
274
+ # internal ModuleLoader and then call `load` on it so it will create
275
+ # the correct loaded_content.
276
+ loader = puppetfile.loader
277
+ expect(puppetfile).to receive(:load) do
278
+ loader.add_module('mod1', { git: 'git://remote' })
279
+ loader.add_module('mod2', { git: 'git://remote' })
280
+
281
+ allow(loader).to receive(:puppetfile_content).and_return('')
282
+ loaded_content = loader.load
283
+ puppetfile.instance_variable_set(:@loaded_content, loaded_content)
284
+ puppetfile.instance_variable_set(:@loaded, true)
285
+ end
286
+
287
+ puppetfile.modules.each do |mod|
288
+ if mod.name == 'mod1'
289
+ expect(mod.should_sync?).to be(true)
290
+ else
291
+ expect(mod.should_sync?).to be(false)
292
+ end
293
+ expect(mod).to receive(:sync).and_call_original
294
+ end
295
+ else
296
+ expect(puppetfile).not_to receive(:load)
297
+ end
298
+
299
+ original.call(environment, &block)
300
+ end.twice
301
+
302
+ expect(repo).to receive(:sync).once
303
+ expect(subject.logger).to receive(:debug1).with(/Updating modules.*in environment.*first/i)
304
+ expect(subject.logger).to receive(:debug1).with(/skipping environment.*second/i)
305
+
306
+ subject.call
307
+ end
308
+ end
178
309
  end
310
+
@@ -11,7 +11,7 @@ describe R10K::Action::Puppetfile::Check do
11
11
  end
12
12
 
13
13
  before(:each) do
14
- allow(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, nil).and_return(puppetfile)
14
+ allow(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", {moduledir: nil, puppetfile_path: nil}).and_return(puppetfile)
15
15
  end
16
16
 
17
17
  it_behaves_like "a puppetfile action"
@@ -34,7 +34,7 @@ describe R10K::Action::Puppetfile::Check do
34
34
  it "respects --puppetfile option" do
35
35
  allow($stderr).to receive(:puts)
36
36
 
37
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, "/custom/puppetfile/path").and_return(puppetfile)
37
+ expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", {moduledir: nil, puppetfile_path: "/custom/puppetfile/path"}).and_return(puppetfile)
38
38
 
39
39
  checker({puppetfile: "/custom/puppetfile/path"}).call
40
40
  end
@@ -2,8 +2,11 @@ require 'spec_helper'
2
2
  require 'r10k/action/puppetfile/install'
3
3
 
4
4
  describe R10K::Action::Puppetfile::Install do
5
- let(:default_opts) { {root: "/some/nonexistent/path"} }
6
- let(:puppetfile) { R10K::Puppetfile.new('/some/nonexistent/path', nil, nil) }
5
+ let(:default_opts) { { root: "/some/nonexistent/path" } }
6
+ let(:puppetfile) {
7
+ R10K::Puppetfile.new('/some/nonexistent/path',
8
+ {:moduledir => nil, :puppetfile_path => nil, :force => false})
9
+ }
7
10
 
8
11
  def installer(opts = {}, argv = [], settings = {})
9
12
  opts = default_opts.merge(opts)
@@ -12,7 +15,10 @@ describe R10K::Action::Puppetfile::Install do
12
15
 
13
16
  before(:each) do
14
17
  allow(puppetfile).to receive(:load!).and_return(nil)
15
- allow(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, nil, nil, nil).and_return(puppetfile)
18
+ allow(R10K::Puppetfile).to receive(:new).
19
+ with("/some/nonexistent/path",
20
+ {:moduledir => nil, :puppetfile_path => nil, :force => false}).
21
+ and_return(puppetfile)
16
22
  end
17
23
 
18
24
  it_behaves_like "a puppetfile install action"
@@ -20,12 +26,11 @@ describe R10K::Action::Puppetfile::Install do
20
26
  describe "installing modules" do
21
27
  let(:modules) do
22
28
  (1..4).map do |idx|
23
- R10K::Module::Base.new("author/modname#{idx}", "/some/nonexistent/path/modname#{idx}", nil)
29
+ R10K::Module::Base.new("author/modname#{idx}", "/some/nonexistent/path/modname#{idx}", {})
24
30
  end
25
31
  end
26
32
 
27
33
  before do
28
- allow(puppetfile).to receive(:purge!)
29
34
  allow(puppetfile).to receive(:modules).and_return(modules)
30
35
  allow(puppetfile).to receive(:modules_by_vcs_cachedir).and_return({none: modules})
31
36
  end
@@ -50,7 +55,15 @@ describe R10K::Action::Puppetfile::Install do
50
55
  end
51
56
 
52
57
  it "purges the moduledir after installation" do
53
- expect(puppetfile).to receive(:purge!)
58
+ mock_cleaner = double("cleaner")
59
+ allow(puppetfile).to receive(:desired_contents).and_return(["root/foo"])
60
+ allow(puppetfile).to receive(:managed_directories).and_return(["root"])
61
+ allow(puppetfile).to receive(:purge_exclusions).and_return(["root/**/**.rb"])
62
+
63
+ expect(R10K::Util::Cleaner).to receive(:new).
64
+ with(["root"], ["root/foo"], ["root/**/**.rb"]).
65
+ and_return(mock_cleaner)
66
+ expect(mock_cleaner).to receive(:purge!)
54
67
 
55
68
  installer.call
56
69
  end
@@ -58,13 +71,19 @@ describe R10K::Action::Puppetfile::Install do
58
71
 
59
72
  describe "using custom paths" do
60
73
  it "can use a custom puppetfile path" do
61
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, "/some/other/path/Puppetfile", nil, nil).and_return(puppetfile)
74
+ expect(R10K::Puppetfile).to receive(:new).
75
+ with("/some/nonexistent/path",
76
+ {:moduledir => nil, :force => false, puppetfile_path: "/some/other/path/Puppetfile"}).
77
+ and_return(puppetfile)
62
78
 
63
79
  installer({puppetfile: "/some/other/path/Puppetfile"}).call
64
80
  end
65
81
 
66
82
  it "can use a custom moduledir path" do
67
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", "/some/other/path/site-modules", nil, nil, nil).and_return(puppetfile)
83
+ expect(R10K::Puppetfile).to receive(:new).
84
+ with("/some/nonexistent/path",
85
+ {:puppetfile_path => nil, :force => false, moduledir: "/some/other/path/site-modules"}).
86
+ and_return(puppetfile)
68
87
 
69
88
  installer({moduledir: "/some/other/path/site-modules"}).call
70
89
  end
@@ -76,8 +95,10 @@ describe R10K::Action::Puppetfile::Install do
76
95
  end
77
96
 
78
97
  it "can use the force overwrite option" do
79
- subject = described_class.new({root: "/some/nonexistent/path", force: true}, [])
80
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, nil, nil, true).and_return(puppetfile)
98
+ subject = described_class.new({root: "/some/nonexistent/path", force: true}, [], {})
99
+ expect(R10K::Puppetfile).to receive(:new).
100
+ with("/some/nonexistent/path", {:moduledir => nil, :puppetfile_path => nil, :force => true}).
101
+ and_return(puppetfile)
81
102
  subject.call
82
103
  end
83
104
 
@@ -3,7 +3,13 @@ require 'r10k/action/puppetfile/purge'
3
3
 
4
4
  describe R10K::Action::Puppetfile::Purge do
5
5
  let(:default_opts) { {root: "/some/nonexistent/path"} }
6
- let(:puppetfile) { instance_double('R10K::Puppetfile', :load! => nil) }
6
+ let(:puppetfile) do
7
+ instance_double('R10K::Puppetfile',
8
+ :load! => nil,
9
+ :managed_directories => %w{foo},
10
+ :desired_contents => %w{bar},
11
+ :purge_exclusions => %w{baz})
12
+ end
7
13
 
8
14
  def purger(opts = {}, argv = [], settings = {})
9
15
  opts = default_opts.merge(opts)
@@ -11,13 +17,21 @@ describe R10K::Action::Puppetfile::Purge do
11
17
  end
12
18
 
13
19
  before(:each) do
14
- allow(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, nil).and_return(puppetfile)
20
+ allow(R10K::Puppetfile).to receive(:new).
21
+ with("/some/nonexistent/path", {moduledir: nil, puppetfile_path: nil}).
22
+ and_return(puppetfile)
15
23
  end
16
24
 
17
25
  it_behaves_like "a puppetfile action"
18
26
 
19
27
  it "purges unmanaged entries in the Puppetfile moduledir" do
20
- expect(puppetfile).to receive(:purge!)
28
+ mock_cleaner = double("cleaner")
29
+
30
+ expect(R10K::Util::Cleaner).to receive(:new).
31
+ with(["foo"], ["bar"], ["baz"]).
32
+ and_return(mock_cleaner)
33
+
34
+ expect(mock_cleaner).to receive(:purge!)
21
35
 
22
36
  purger.call
23
37
  end
@@ -28,13 +42,19 @@ describe R10K::Action::Puppetfile::Purge do
28
42
  end
29
43
 
30
44
  it "can use a custom puppetfile path" do
31
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, "/some/other/path/Puppetfile").and_return(puppetfile)
45
+ expect(R10K::Puppetfile).to receive(:new).
46
+ with("/some/nonexistent/path",
47
+ {moduledir: nil, puppetfile_path: "/some/other/path/Puppetfile"}).
48
+ and_return(puppetfile)
32
49
 
33
50
  purger({puppetfile: "/some/other/path/Puppetfile"}).call
34
51
  end
35
52
 
36
53
  it "can use a custom moduledir path" do
37
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", "/some/other/path/site-modules", nil).and_return(puppetfile)
54
+ expect(R10K::Puppetfile).to receive(:new).
55
+ with("/some/nonexistent/path",
56
+ {moduledir: "/some/other/path/site-modules", puppetfile_path: nil}).
57
+ and_return(puppetfile)
38
58
 
39
59
  purger({moduledir: "/some/other/path/site-modules"}).call
40
60
  end