r10k 3.9.0 → 3.10.0

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