r10k 3.9.3 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/rspec_tests.yml +1 -1
- data/CHANGELOG.mkd +9 -0
- data/doc/dynamic-environments/configuration.mkd +7 -0
- data/integration/Rakefile +1 -1
- data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +3 -9
- data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +8 -14
- data/lib/r10k/action/deploy/environment.rb +3 -0
- data/lib/r10k/action/runner.rb +11 -6
- data/lib/r10k/git/cache.rb +1 -1
- data/lib/r10k/initializers.rb +7 -0
- data/lib/r10k/module/forge.rb +5 -1
- data/lib/r10k/module_loader/puppetfile.rb +195 -0
- data/lib/r10k/module_loader/puppetfile/dsl.rb +37 -0
- data/lib/r10k/puppetfile.rb +77 -153
- data/lib/r10k/settings.rb +3 -0
- data/lib/r10k/source/base.rb +10 -0
- data/lib/r10k/source/git.rb +5 -0
- data/lib/r10k/source/svn.rb +4 -0
- data/lib/r10k/util/purgeable.rb +70 -8
- data/lib/r10k/version.rb +1 -1
- data/locales/r10k.pot +37 -33
- data/spec/fixtures/unit/action/r10k_forge_auth.yaml +4 -0
- data/spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml +3 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_subdir_2/ignored_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_two/.hidden/unmanaged_3 +0 -0
- data/spec/unit/action/deploy/environment_spec.rb +9 -0
- data/spec/unit/action/deploy/module_spec.rb +38 -14
- data/spec/unit/action/runner_spec.rb +49 -25
- data/spec/unit/git/cache_spec.rb +14 -0
- data/spec/unit/module/forge_spec.rb +8 -1
- data/spec/unit/module_loader/puppetfile_spec.rb +330 -0
- data/spec/unit/puppetfile_spec.rb +99 -193
- data/spec/unit/settings_spec.rb +6 -2
- data/spec/unit/util/purgeable_spec.rb +38 -6
- metadata +10 -3
@@ -0,0 +1,330 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/module_loader/puppetfile'
|
3
|
+
|
4
|
+
describe R10K::ModuleLoader::Puppetfile do
|
5
|
+
describe 'initial parameters' do
|
6
|
+
describe 'honor' do
|
7
|
+
let(:options) do
|
8
|
+
{
|
9
|
+
basedir: '/test/basedir/env',
|
10
|
+
forge: 'localforge.internal.corp',
|
11
|
+
overrides: { modules: { deploy_modules: true } },
|
12
|
+
environment: R10K::Environment::Git.new('env',
|
13
|
+
'/test/basedir/',
|
14
|
+
'env',
|
15
|
+
{ remote: 'git://foo/remote',
|
16
|
+
ref: 'env' })
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
subject { R10K::ModuleLoader::Puppetfile.new(**options) }
|
21
|
+
|
22
|
+
describe 'the moduledir' do
|
23
|
+
it 'respects absolute paths' do
|
24
|
+
absolute_options = options.merge({moduledir: '/opt/puppetlabs/special/modules'})
|
25
|
+
puppetfile = R10K::ModuleLoader::Puppetfile.new(**absolute_options)
|
26
|
+
expect(puppetfile.instance_variable_get(:@moduledir)).to eq('/opt/puppetlabs/special/modules')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'roots the moduledir in the basepath if a relative path is specified' do
|
30
|
+
relative_options = options.merge({moduledir: 'my/special/modules'})
|
31
|
+
puppetfile = R10K::ModuleLoader::Puppetfile.new(**relative_options)
|
32
|
+
expect(puppetfile.instance_variable_get(:@moduledir)).to eq('/test/basedir/env/my/special/modules')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'the Puppetfile' do
|
37
|
+
it 'respects absolute paths' do
|
38
|
+
absolute_options = options.merge({puppetfile: '/opt/puppetlabs/special/Puppetfile'})
|
39
|
+
puppetfile = R10K::ModuleLoader::Puppetfile.new(**absolute_options)
|
40
|
+
expect(puppetfile.instance_variable_get(:@puppetfile)).to eq('/opt/puppetlabs/special/Puppetfile')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'roots the Puppetfile in the basepath if a relative path is specified' do
|
44
|
+
relative_options = options.merge({puppetfile: 'Puppetfile.global'})
|
45
|
+
puppetfile = R10K::ModuleLoader::Puppetfile.new(**relative_options)
|
46
|
+
expect(puppetfile.instance_variable_get(:@puppetfile)).to eq('/test/basedir/env/Puppetfile.global')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'the forge' do
|
51
|
+
expect(subject.instance_variable_get(:@forge)).to eq('localforge.internal.corp')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'the overrides' do
|
55
|
+
expect(subject.instance_variable_get(:@overrides)).to eq({ modules: { deploy_modules: true }})
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'the environment' do
|
59
|
+
expect(subject.instance_variable_get(:@environment).name).to eq('env')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'sane defaults' do
|
64
|
+
subject { R10K::ModuleLoader::Puppetfile.new(basedir: '/test/basedir') }
|
65
|
+
|
66
|
+
it 'has a moduledir rooted in the basedir' do
|
67
|
+
expect(subject.instance_variable_get(:@moduledir)).to eq('/test/basedir/modules')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'has a Puppetfile rooted in the basedir' do
|
71
|
+
expect(subject.instance_variable_get(:@puppetfile)).to eq('/test/basedir/Puppetfile')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'uses the public forge' do
|
75
|
+
expect(subject.instance_variable_get(:@forge)).to eq('forgeapi.puppetlabs.com')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'creates an empty overrides' do
|
79
|
+
expect(subject.instance_variable_get(:@overrides)).to eq({})
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'does not require an environment' do
|
83
|
+
expect(subject.instance_variable_get(:@environment)).to eq(nil)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'adding modules' do
|
89
|
+
let(:basedir) { '/test/basedir' }
|
90
|
+
|
91
|
+
subject { R10K::ModuleLoader::Puppetfile.new(basedir: basedir) }
|
92
|
+
|
93
|
+
it 'should transform Forge modules with a string arg to have a version key' do
|
94
|
+
expect(R10K::Module).to receive(:new).with('puppet/test_module', subject.moduledir, hash_including(version: '1.2.3'), anything).and_call_original
|
95
|
+
|
96
|
+
expect { subject.add_module('puppet/test_module', '1.2.3') }.to change { subject.modules }
|
97
|
+
expect(subject.modules.collect(&:name)).to include('test_module')
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should not accept Forge modules with a version comparison' do
|
101
|
+
expect(R10K::Module).to receive(:new).with('puppet/test_module', subject.moduledir, hash_including(version: '< 1.2.0'), anything).and_call_original
|
102
|
+
|
103
|
+
expect {
|
104
|
+
subject.add_module('puppet/test_module', '< 1.2.0')
|
105
|
+
}.to raise_error(RuntimeError, /module puppet\/test_module.*doesn't have an implementation/i)
|
106
|
+
|
107
|
+
expect(subject.modules.collect(&:name)).not_to include('test_module')
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should accept non-Forge modules with a hash arg' do
|
111
|
+
module_opts = { git: 'git@example.com:puppet/test_module.git' }
|
112
|
+
|
113
|
+
expect(R10K::Module).to receive(:new).with('puppet/test_module', subject.moduledir, module_opts, anything).and_call_original
|
114
|
+
|
115
|
+
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
116
|
+
expect(subject.modules.collect(&:name)).to include('test_module')
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should accept non-Forge modules with a valid relative :install_path option' do
|
120
|
+
module_opts = {
|
121
|
+
install_path: 'vendor',
|
122
|
+
git: 'git@example.com:puppet/test_module.git',
|
123
|
+
}
|
124
|
+
|
125
|
+
expect(R10K::Module).to receive(:new).with('puppet/test_module', File.join(basedir, 'vendor'), module_opts, anything).and_call_original
|
126
|
+
|
127
|
+
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
128
|
+
expect(subject.modules.collect(&:name)).to include('test_module')
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should accept non-Forge modules with a valid absolute :install_path option' do
|
132
|
+
install_path = File.join(basedir, 'vendor')
|
133
|
+
|
134
|
+
module_opts = {
|
135
|
+
install_path: install_path,
|
136
|
+
git: 'git@example.com:puppet/test_module.git',
|
137
|
+
}
|
138
|
+
|
139
|
+
expect(R10K::Module).to receive(:new).with('puppet/test_module', install_path, module_opts, anything).and_call_original
|
140
|
+
|
141
|
+
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
142
|
+
expect(subject.modules.collect(&:name)).to include('test_module')
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should reject non-Forge modules with an invalid relative :install_path option' do
|
146
|
+
module_opts = {
|
147
|
+
install_path: '../../vendor',
|
148
|
+
git: 'git@example.com:puppet/test_module.git',
|
149
|
+
}
|
150
|
+
|
151
|
+
expect { subject.add_module('puppet/test_module', module_opts) }.to raise_error(R10K::Error, /cannot manage content.*is not within/i).and not_change { subject.modules }
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should reject non-Forge modules with an invalid absolute :install_path option' do
|
155
|
+
module_opts = {
|
156
|
+
install_path: '/tmp/mydata/vendor',
|
157
|
+
git: 'git@example.com:puppet/test_module.git',
|
158
|
+
}
|
159
|
+
|
160
|
+
expect { subject.add_module('puppet/test_module', module_opts) }.to raise_error(R10K::Error, /cannot manage content.*is not within/i).and not_change { subject.modules }
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should disable and not add modules that conflict with the environment' do
|
164
|
+
env = instance_double('R10K::Environment::Base')
|
165
|
+
mod = instance_double('R10K::Module::Base', name: 'conflict', origin: :puppetfile, 'origin=': nil)
|
166
|
+
loader = R10K::ModuleLoader::Puppetfile.new(basedir: basedir, environment: env)
|
167
|
+
allow(env).to receive(:'module_conflicts?').with(mod).and_return(true)
|
168
|
+
|
169
|
+
expect(R10K::Module).to receive(:new).with('conflict', anything, anything, anything).and_return(mod)
|
170
|
+
expect { loader.add_module('conflict', {}) }.not_to change { loader.modules }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '#purge_exclusions' do
|
175
|
+
let(:managed_dirs) { ['dir1', 'dir2'] }
|
176
|
+
subject { R10K::ModuleLoader::Puppetfile.new(basedir: '/test/basedir') }
|
177
|
+
|
178
|
+
it 'includes managed_directories' do
|
179
|
+
expect(subject.send(:determine_purge_exclusions, managed_dirs)).to match_array(managed_dirs)
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'when belonging to an environment' do
|
183
|
+
let(:env_contents) { ['env1', 'env2' ] }
|
184
|
+
let(:env) { double(:environment, desired_contents: env_contents) }
|
185
|
+
|
186
|
+
subject { R10K::ModuleLoader::Puppetfile.new(basedir: '/test/basedir', environment: env) }
|
187
|
+
|
188
|
+
it "includes environment's desired_contents" do
|
189
|
+
expect(subject.send(:determine_purge_exclusions, managed_dirs)).to match_array(managed_dirs + env_contents)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe '#managed_directories' do
|
195
|
+
|
196
|
+
let(:basedir) { '/test/basedir' }
|
197
|
+
subject { R10K::ModuleLoader::Puppetfile.new(basedir: basedir) }
|
198
|
+
|
199
|
+
before do
|
200
|
+
allow(subject).to receive(:puppetfile_content).and_return('')
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'returns an array of paths that #purge! will operate within' do
|
204
|
+
expect(R10K::Module).to receive(:new).with('puppet/test_module', subject.moduledir, hash_including(version: '1.2.3'), anything).and_call_original
|
205
|
+
subject.add_module('puppet/test_module', '1.2.3')
|
206
|
+
subject.load
|
207
|
+
|
208
|
+
expect(subject.modules.length).to be 1
|
209
|
+
expect(subject.managed_directories).to match_array([subject.moduledir])
|
210
|
+
end
|
211
|
+
|
212
|
+
context "with a module with install_path == ''" do
|
213
|
+
it "basedir isn't in the list of paths to purge" do
|
214
|
+
module_opts = { install_path: '', git: 'git@example.com:puppet/test_module.git' }
|
215
|
+
|
216
|
+
expect(R10K::Module).to receive(:new).with('puppet/test_module', basedir, module_opts, anything).and_call_original
|
217
|
+
subject.add_module('puppet/test_module', module_opts)
|
218
|
+
subject.load
|
219
|
+
|
220
|
+
expect(subject.modules.length).to be 1
|
221
|
+
expect(subject.managed_directories).to be_empty
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe 'evaluating a Puppetfile' do
|
227
|
+
def expect_wrapped_error(error, pf_path, error_type)
|
228
|
+
expect(error).to be_a_kind_of(R10K::Error)
|
229
|
+
expect(error.message).to eq("Failed to evaluate #{pf_path}")
|
230
|
+
expect(error.original).to be_a_kind_of(error_type)
|
231
|
+
end
|
232
|
+
|
233
|
+
subject { described_class.new(basedir: @path) }
|
234
|
+
|
235
|
+
it 'wraps and re-raises syntax errors' do
|
236
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'invalid-syntax')
|
237
|
+
pf_path = File.join(@path, 'Puppetfile')
|
238
|
+
expect {
|
239
|
+
subject.load
|
240
|
+
}.to raise_error do |e|
|
241
|
+
expect_wrapped_error(e, pf_path, SyntaxError)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'wraps and re-raises load errors' do
|
246
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'load-error')
|
247
|
+
pf_path = File.join(@path, 'Puppetfile')
|
248
|
+
expect {
|
249
|
+
subject.load
|
250
|
+
}.to raise_error do |e|
|
251
|
+
expect_wrapped_error(e, pf_path, LoadError)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'wraps and re-raises argument errors' do
|
256
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'argument-error')
|
257
|
+
pf_path = File.join(@path, 'Puppetfile')
|
258
|
+
expect {
|
259
|
+
subject.load
|
260
|
+
}.to raise_error do |e|
|
261
|
+
expect_wrapped_error(e, pf_path, ArgumentError)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'rejects Puppetfiles with duplicate module names' do
|
266
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'duplicate-module-error')
|
267
|
+
pf_path = File.join(@path, 'Puppetfile')
|
268
|
+
expect {
|
269
|
+
subject.load
|
270
|
+
}.to raise_error(R10K::Error, /Puppetfiles cannot contain duplicate module names/i)
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'wraps and re-raises name errors' do
|
274
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'name-error')
|
275
|
+
pf_path = File.join(@path, 'Puppetfile')
|
276
|
+
expect {
|
277
|
+
subject.load
|
278
|
+
}.to raise_error do |e|
|
279
|
+
expect_wrapped_error(e, pf_path, NameError)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'accepts a forge module with a version' do
|
284
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
285
|
+
pf_path = File.join(@path, 'Puppetfile')
|
286
|
+
expect { subject.load }.not_to raise_error
|
287
|
+
end
|
288
|
+
|
289
|
+
describe 'setting a custom moduledir' do
|
290
|
+
it 'allows setting an absolute moduledir' do
|
291
|
+
@path = '/fake/basedir'
|
292
|
+
allow(subject).to receive(:puppetfile_content).and_return('moduledir "/fake/moduledir"')
|
293
|
+
subject.load
|
294
|
+
expect(subject.instance_variable_get(:@moduledir)).to eq('/fake/moduledir')
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'roots relative moduledirs in the basedir' do
|
298
|
+
@path = '/fake/basedir'
|
299
|
+
allow(subject).to receive(:puppetfile_content).and_return('moduledir "my/moduledir"')
|
300
|
+
subject.load
|
301
|
+
expect(subject.instance_variable_get(:@moduledir)).to eq(File.join(@path, 'my/moduledir'))
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'accepts a forge module without a version' do
|
306
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-without-version')
|
307
|
+
pf_path = File.join(@path, 'Puppetfile')
|
308
|
+
expect { subject.load }.not_to raise_error
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'creates a git module and applies the default branch specified in the Puppetfile' do
|
312
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'default-branch-override')
|
313
|
+
pf_path = File.join(@path, 'Puppetfile')
|
314
|
+
expect { subject.load }.not_to raise_error
|
315
|
+
git_module = subject.modules[0]
|
316
|
+
expect(git_module.default_ref).to eq 'here_lies_the_default_branch'
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'creates a git module and applies the provided default_branch_override' do
|
320
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'default-branch-override')
|
321
|
+
pf_path = File.join(@path, 'Puppetfile')
|
322
|
+
default_branch_override = 'default_branch_override_name'
|
323
|
+
subject.default_branch_override = default_branch_override
|
324
|
+
expect { subject.load }.not_to raise_error
|
325
|
+
git_module = subject.modules[0]
|
326
|
+
expect(git_module.default_override_ref).to eq default_branch_override
|
327
|
+
expect(git_module.default_ref).to eq 'here_lies_the_default_branch'
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
@@ -67,230 +67,136 @@ describe R10K::Puppetfile do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
describe "
|
71
|
-
|
72
|
-
|
70
|
+
describe "loading a Puppetfile" do
|
71
|
+
context 'using load' do
|
72
|
+
it "returns the loaded content" do
|
73
|
+
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
74
|
+
subject = described_class.new(path, {})
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should not accept Forge modules with a version comparison" do
|
79
|
-
allow(R10K::Module).to receive(:new).with('puppet/test_module', subject.moduledir, hash_including(version: '< 1.2.0'), anything).and_call_original
|
80
|
-
|
81
|
-
expect {
|
82
|
-
subject.add_module('puppet/test_module', '< 1.2.0')
|
83
|
-
}.to raise_error(RuntimeError, /module puppet\/test_module.*doesn't have an implementation/i)
|
84
|
-
|
85
|
-
expect(subject.modules.collect(&:name)).not_to include('test_module')
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should accept non-Forge modules with a hash arg" do
|
89
|
-
module_opts = { git: 'git@example.com:puppet/test_module.git' }
|
90
|
-
|
91
|
-
allow(R10K::Module).to receive(:new).with('puppet/test_module', subject.moduledir, module_opts, anything).and_call_original
|
92
|
-
|
93
|
-
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
94
|
-
expect(subject.modules.collect(&:name)).to include('test_module')
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should accept non-Forge modules with a valid relative :install_path option" do
|
98
|
-
module_opts = {
|
99
|
-
install_path: 'vendor',
|
100
|
-
git: 'git@example.com:puppet/test_module.git',
|
101
|
-
}
|
102
|
-
|
103
|
-
allow(R10K::Module).to receive(:new).with('puppet/test_module', File.join(subject.basedir, 'vendor'), module_opts, anything).and_call_original
|
104
|
-
|
105
|
-
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
106
|
-
expect(subject.modules.collect(&:name)).to include('test_module')
|
107
|
-
end
|
76
|
+
loaded_content = subject.load
|
77
|
+
expect(loaded_content).to be_an_instance_of(Hash)
|
108
78
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
module_opts = {
|
113
|
-
install_path: install_path,
|
114
|
-
git: 'git@example.com:puppet/test_module.git',
|
115
|
-
}
|
116
|
-
|
117
|
-
allow(R10K::Module).to receive(:new).with('puppet/test_module', install_path, module_opts, anything).and_call_original
|
118
|
-
|
119
|
-
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
120
|
-
expect(subject.modules.collect(&:name)).to include('test_module')
|
121
|
-
end
|
122
|
-
|
123
|
-
it "should reject non-Forge modules with an invalid relative :install_path option" do
|
124
|
-
module_opts = {
|
125
|
-
install_path: '../../vendor',
|
126
|
-
git: 'git@example.com:puppet/test_module.git',
|
127
|
-
}
|
128
|
-
|
129
|
-
allow(R10K::Module).to receive(:new).with('puppet/test_module', File.join(subject.basedir, 'vendor'), module_opts, anything).and_call_original
|
130
|
-
|
131
|
-
expect { subject.add_module('puppet/test_module', module_opts) }.to raise_error(R10K::Error, /cannot manage content.*is not within/i).and not_change { subject.modules }
|
132
|
-
end
|
133
|
-
|
134
|
-
it "should reject non-Forge modules with an invalid absolute :install_path option" do
|
135
|
-
module_opts = {
|
136
|
-
install_path: '/tmp/mydata/vendor',
|
137
|
-
git: 'git@example.com:puppet/test_module.git',
|
138
|
-
}
|
139
|
-
|
140
|
-
allow(R10K::Module).to receive(:new).with('puppet/test_module', File.join(subject.basedir, 'vendor'), module_opts, anything).and_call_original
|
79
|
+
has_some_data = loaded_content.values.none?(&:empty?)
|
80
|
+
expect(has_some_data).to be true
|
81
|
+
end
|
141
82
|
|
142
|
-
|
143
|
-
|
83
|
+
it "is idempotent" do
|
84
|
+
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
85
|
+
subject = described_class.new(path, {})
|
144
86
|
|
145
|
-
|
146
|
-
env = instance_double('R10K::Environment::Base')
|
147
|
-
mod = instance_double('R10K::Module::Base', name: 'conflict', origin: :puppetfile)
|
148
|
-
allow(mod).to receive(:origin=).and_return(nil)
|
149
|
-
allow(subject).to receive(:environment).and_return(env)
|
150
|
-
allow(env).to receive(:'module_conflicts?').with(mod).and_return(true)
|
87
|
+
expect(subject.loader).to receive(:load).and_call_original.once
|
151
88
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
89
|
+
loaded_content1 = subject.load
|
90
|
+
expect(subject.loaded?).to be true
|
91
|
+
loaded_content2 = subject.load
|
156
92
|
|
157
|
-
|
158
|
-
|
93
|
+
expect(loaded_content2).to eq(loaded_content1)
|
94
|
+
end
|
159
95
|
|
160
|
-
|
161
|
-
|
96
|
+
it "returns nil if Puppetfile doesn't exist" do
|
97
|
+
path = '/rando/path/that/wont/exist'
|
98
|
+
subject = described_class.new(path, {})
|
99
|
+
expect(subject.load).to eq nil
|
100
|
+
end
|
162
101
|
end
|
163
102
|
|
164
|
-
|
165
|
-
|
166
|
-
|
103
|
+
context 'using load!' do
|
104
|
+
it "returns the loaded content" do
|
105
|
+
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
106
|
+
subject = described_class.new(path, {})
|
167
107
|
|
168
|
-
|
169
|
-
|
108
|
+
loaded_content = subject.load!
|
109
|
+
expect(loaded_content).to be_an_instance_of(Hash)
|
170
110
|
|
171
|
-
|
172
|
-
|
173
|
-
allow(subject).to receive(:environment).and_return(mock_env)
|
111
|
+
has_some_data = loaded_content.values.none?(&:empty?)
|
112
|
+
expect(has_some_data).to be true
|
174
113
|
end
|
175
114
|
|
176
|
-
it "
|
177
|
-
|
115
|
+
it "raises if Puppetfile doesn't exist" do
|
116
|
+
path = '/rando/path/that/wont/exist'
|
117
|
+
subject = described_class.new(path, {})
|
118
|
+
expect {
|
119
|
+
subject.load!
|
120
|
+
}.to raise_error(/No such file or directory.*\/rando\/path\/.*/)
|
178
121
|
end
|
179
122
|
end
|
180
123
|
end
|
181
124
|
|
182
|
-
describe '
|
183
|
-
it '
|
184
|
-
|
125
|
+
describe 'default_branch_override' do
|
126
|
+
it 'is passed correctly to module loader init' do
|
127
|
+
# This path doesn't matter so long as it has a Puppetfile within it
|
128
|
+
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
129
|
+
subject = described_class.new(path, {overrides: {environments: {default_branch_override: 'foo'}}})
|
185
130
|
|
186
|
-
|
187
|
-
|
188
|
-
|
131
|
+
repo = instance_double('R10K::Git::StatefulRepository')
|
132
|
+
allow(repo).to receive(:resolve).with('foo').and_return(true)
|
133
|
+
allow(R10K::Git::StatefulRepository).to receive(:new).and_return(repo)
|
189
134
|
|
190
|
-
|
191
|
-
|
192
|
-
|
135
|
+
allow(subject.loader).to receive(:puppetfile_content).and_return <<-EOPF
|
136
|
+
# Track control branch and fall-back to main if no matching branch.
|
137
|
+
mod 'hieradata',
|
138
|
+
:git => 'git@git.example.com:organization/hieradata.git',
|
139
|
+
:branch => :control_branch,
|
140
|
+
:default_branch => 'main'
|
141
|
+
EOPF
|
193
142
|
|
194
|
-
|
143
|
+
expect(subject.logger).not_to receive(:warn).
|
144
|
+
with(/Mismatch between passed and initialized.*preferring passed value/)
|
195
145
|
|
196
|
-
|
197
|
-
expect(subject.managed_directories).to be_empty
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
146
|
+
subject.load
|
201
147
|
|
202
|
-
|
203
|
-
|
204
|
-
expect(orig).to be_a_kind_of(R10K::Error)
|
205
|
-
expect(orig.message).to eq("Failed to evaluate #{pf_path}")
|
206
|
-
expect(orig.original).to be_a_kind_of(wrapped_error)
|
148
|
+
loaded_module = subject.modules.first
|
149
|
+
expect(loaded_module.version).to eq('foo')
|
207
150
|
end
|
208
151
|
|
209
|
-
it
|
210
|
-
|
211
|
-
|
212
|
-
subject = described_class.new(path, {})
|
213
|
-
expect {
|
214
|
-
subject.load!
|
215
|
-
}.to raise_error do |e|
|
216
|
-
expect_wrapped_error(e, pf_path, SyntaxError)
|
217
|
-
end
|
218
|
-
end
|
152
|
+
it 'overrides module loader init if needed' do
|
153
|
+
# This path doesn't matter so long as it has a Puppetfile within it
|
154
|
+
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
155
|
+
subject = described_class.new(path, {overrides: {environments: {default_branch_override: 'foo'}}})
|
219
156
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
subject = described_class.new(path, {})
|
224
|
-
expect {
|
225
|
-
subject.load!
|
226
|
-
}.to raise_error do |e|
|
227
|
-
expect_wrapped_error(e, pf_path, LoadError)
|
228
|
-
end
|
229
|
-
end
|
157
|
+
repo = instance_double('R10K::Git::StatefulRepository')
|
158
|
+
allow(repo).to receive(:resolve).with('bar').and_return(true)
|
159
|
+
allow(R10K::Git::StatefulRepository).to receive(:new).and_return(repo)
|
230
160
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
expect_wrapped_error(e, pf_path, ArgumentError)
|
239
|
-
end
|
240
|
-
end
|
161
|
+
allow(subject.loader).to receive(:puppetfile_content).and_return <<-EOPF
|
162
|
+
# Track control branch and fall-back to main if no matching branch.
|
163
|
+
mod 'hieradata',
|
164
|
+
:git => 'git@git.example.com:organization/hieradata.git',
|
165
|
+
:branch => :control_branch,
|
166
|
+
:default_branch => 'main'
|
167
|
+
EOPF
|
241
168
|
|
242
|
-
|
243
|
-
|
244
|
-
pf_path = File.join(path, 'Puppetfile')
|
245
|
-
subject = described_class.new(path, {})
|
246
|
-
expect {
|
247
|
-
subject.load!
|
248
|
-
}.to raise_error(R10K::Error, /Puppetfiles cannot contain duplicate module names/i)
|
249
|
-
end
|
169
|
+
expect(subject.logger).to receive(:warn).
|
170
|
+
with(/Mismatch between passed and initialized.*preferring passed value/)
|
250
171
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
subject = described_class.new(path, {})
|
255
|
-
expect {
|
256
|
-
subject.load!
|
257
|
-
}.to raise_error do |e|
|
258
|
-
expect_wrapped_error(e, pf_path, NameError)
|
259
|
-
end
|
172
|
+
subject.load('bar')
|
173
|
+
loaded_module = subject.modules.first
|
174
|
+
expect(loaded_module.version).to eq('bar')
|
260
175
|
end
|
261
176
|
|
262
|
-
it
|
177
|
+
it 'does not warn if passed and initialized default_branch_overrides match' do
|
178
|
+
# This path doesn't matter so long as it has a Puppetfile within it
|
263
179
|
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
it "creates a git module and applies the provided default_branch_override" do
|
286
|
-
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'default-branch-override')
|
287
|
-
pf_path = File.join(path, 'Puppetfile')
|
288
|
-
subject = described_class.new(path, {})
|
289
|
-
default_branch_override = 'default_branch_override_name'
|
290
|
-
expect { subject.load!(default_branch_override) }.not_to raise_error
|
291
|
-
git_module = subject.modules[0]
|
292
|
-
expect(git_module.default_override_ref).to eq default_branch_override
|
293
|
-
expect(git_module.default_ref).to eq "here_lies_the_default_branch"
|
180
|
+
subject = described_class.new(path, {overrides: {environments: {default_branch_override: 'foo'}}})
|
181
|
+
|
182
|
+
repo = instance_double('R10K::Git::StatefulRepository')
|
183
|
+
allow(repo).to receive(:resolve).with('foo').and_return(true)
|
184
|
+
allow(R10K::Git::StatefulRepository).to receive(:new).and_return(repo)
|
185
|
+
|
186
|
+
allow(subject.loader).to receive(:puppetfile_content).and_return <<-EOPF
|
187
|
+
# Track control branch and fall-back to main if no matching branch.
|
188
|
+
mod 'hieradata',
|
189
|
+
:git => 'git@git.example.com:organization/hieradata.git',
|
190
|
+
:branch => :control_branch,
|
191
|
+
:default_branch => 'main'
|
192
|
+
EOPF
|
193
|
+
|
194
|
+
expect(subject.logger).not_to receive(:warn).
|
195
|
+
with(/Mismatch between passed and initialized.*preferring passed value/)
|
196
|
+
|
197
|
+
subject.load('foo')
|
198
|
+
loaded_module = subject.modules.first
|
199
|
+
expect(loaded_module.version).to eq('foo')
|
294
200
|
end
|
295
201
|
end
|
296
202
|
|