r10k 3.11.0 → 3.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/docker.yml +1 -1
- data/.github/workflows/rspec_tests.yml +2 -2
- data/.travis.yml +1 -1
- data/CHANGELOG.mkd +34 -0
- data/doc/dynamic-environments/configuration.mkd +35 -7
- data/doc/dynamic-environments/usage.mkd +26 -0
- data/doc/puppetfile.mkd +16 -4
- data/integration/tests/basic_functionality/basic_deployment.rb +176 -0
- data/lib/r10k/action/base.rb +1 -1
- data/lib/r10k/action/deploy/deploy_helpers.rb +4 -0
- data/lib/r10k/action/deploy/display.rb +1 -1
- data/lib/r10k/action/deploy/environment.rb +13 -8
- data/lib/r10k/action/deploy/module.rb +14 -10
- data/lib/r10k/action/puppetfile/check.rb +7 -5
- data/lib/r10k/action/puppetfile/install.rb +22 -16
- data/lib/r10k/action/puppetfile/purge.rb +12 -9
- data/lib/r10k/action/runner.rb +6 -0
- data/lib/r10k/action/visitor.rb +3 -0
- data/lib/r10k/cli/deploy.rb +1 -0
- data/lib/r10k/cli/puppetfile.rb +0 -1
- data/lib/r10k/content_synchronizer.rb +16 -4
- data/lib/r10k/environment/bare.rb +4 -7
- data/lib/r10k/environment/base.rb +64 -11
- data/lib/r10k/environment/name.rb +14 -9
- data/lib/r10k/environment/plain.rb +16 -0
- data/lib/r10k/environment/tarball.rb +78 -0
- data/lib/r10k/environment/with_modules.rb +6 -10
- data/lib/r10k/environment.rb +2 -0
- data/lib/r10k/errors.rb +5 -0
- data/lib/r10k/forge/module_release.rb +2 -1
- data/lib/r10k/git/cache.rb +4 -13
- data/lib/r10k/git/rugged/base_repository.rb +12 -1
- data/lib/r10k/git/rugged/cache.rb +8 -0
- data/lib/r10k/git/stateful_repository.rb +9 -0
- data/lib/r10k/initializers.rb +21 -7
- data/lib/r10k/logging.rb +78 -1
- data/lib/r10k/module/base.rb +5 -1
- data/lib/r10k/module/definition.rb +64 -0
- data/lib/r10k/module/forge.rb +10 -2
- data/lib/r10k/module/git.rb +22 -1
- data/lib/r10k/module/local.rb +6 -3
- data/lib/r10k/module/svn.rb +10 -0
- data/lib/r10k/module/tarball.rb +101 -0
- data/lib/r10k/module.rb +21 -2
- data/lib/r10k/module_loader/puppetfile/dsl.rb +8 -3
- data/lib/r10k/module_loader/puppetfile.rb +109 -30
- data/lib/r10k/puppetfile.rb +1 -2
- data/lib/r10k/settings.rb +46 -0
- data/lib/r10k/source/git.rb +18 -18
- data/lib/r10k/source/yaml.rb +1 -1
- data/lib/r10k/tarball.rb +183 -0
- data/lib/r10k/util/cacheable.rb +31 -0
- data/lib/r10k/util/downloader.rb +134 -0
- data/lib/r10k/util/purgeable.rb +6 -2
- data/lib/r10k/util/setopts.rb +2 -0
- data/lib/r10k/util/subprocess.rb +1 -0
- data/lib/r10k/version.rb +1 -1
- data/locales/r10k.pot +119 -71
- data/r10k.gemspec +2 -2
- data/r10k.yaml.example +28 -0
- data/spec/fixtures/tarball/tarball.tar.gz +0 -0
- data/spec/fixtures/unit/action/r10k_logging.yaml +12 -0
- data/spec/fixtures/unit/puppetfile/forge-override/Puppetfile +8 -0
- data/spec/fixtures/unit/puppetfile/various-modules/Puppetfile +10 -0
- data/spec/fixtures/unit/puppetfile/various-modules/Puppetfile.new +10 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_symlink_file +1 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/{managed_subdir_2 → subdir_allowlisted_2}/ignored_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/unmanaged_symlink_dir +1 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_symlink_dir +1 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/unmanaged_symlink_file +1 -0
- data/spec/integration/git/rugged/cache_spec.rb +33 -0
- data/spec/integration/util/purageable_spec.rb +41 -0
- data/spec/r10k-mocks/mock_env.rb +3 -0
- data/spec/r10k-mocks/mock_source.rb +7 -3
- data/spec/shared-contexts/tarball.rb +32 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/action/deploy/environment_spec.rb +80 -30
- data/spec/unit/action/deploy/module_spec.rb +52 -64
- data/spec/unit/action/puppetfile/check_spec.rb +17 -5
- data/spec/unit/action/puppetfile/install_spec.rb +42 -36
- data/spec/unit/action/puppetfile/purge_spec.rb +15 -17
- data/spec/unit/action/runner_spec.rb +52 -9
- data/spec/unit/environment/bare_spec.rb +13 -0
- data/spec/unit/environment/base_spec.rb +30 -17
- data/spec/unit/environment/git_spec.rb +2 -2
- data/spec/unit/environment/name_spec.rb +18 -0
- data/spec/unit/environment/plain_spec.rb +8 -0
- data/spec/unit/environment/svn_spec.rb +4 -3
- data/spec/unit/environment/tarball_spec.rb +45 -0
- data/spec/unit/environment/with_modules_spec.rb +3 -2
- data/spec/unit/git/cache_spec.rb +2 -15
- data/spec/unit/git/rugged/cache_spec.rb +19 -0
- data/spec/unit/module/base_spec.rb +8 -8
- data/spec/unit/module/forge_spec.rb +32 -4
- data/spec/unit/module/git_spec.rb +51 -10
- data/spec/unit/module/svn_spec.rb +18 -6
- data/spec/unit/module/tarball_spec.rb +70 -0
- data/spec/unit/module_loader/puppetfile_spec.rb +96 -31
- data/spec/unit/puppetfile_spec.rb +2 -2
- data/spec/unit/settings_spec.rb +25 -2
- data/spec/unit/tarball_spec.rb +57 -0
- data/spec/unit/util/cacheable_spec.rb +23 -0
- data/spec/unit/util/downloader_spec.rb +98 -0
- data/spec/unit/util/purgeable_spec.rb +22 -11
- metadata +44 -17
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'r10k/module_loader/puppetfile'
|
3
|
+
require 'tmpdir'
|
3
4
|
|
4
5
|
describe R10K::ModuleLoader::Puppetfile do
|
5
6
|
describe 'initial parameters' do
|
@@ -7,7 +8,6 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
7
8
|
let(:options) do
|
8
9
|
{
|
9
10
|
basedir: '/test/basedir/env',
|
10
|
-
forge: 'localforge.internal.corp',
|
11
11
|
overrides: { modules: { deploy_modules: true } },
|
12
12
|
environment: R10K::Environment::Git.new('env',
|
13
13
|
'/test/basedir/',
|
@@ -47,10 +47,6 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
it 'the forge' do
|
51
|
-
expect(subject.instance_variable_get(:@forge)).to eq('localforge.internal.corp')
|
52
|
-
end
|
53
|
-
|
54
50
|
it 'the overrides' do
|
55
51
|
expect(subject.instance_variable_get(:@overrides)).to eq({ modules: { deploy_modules: true }})
|
56
52
|
end
|
@@ -71,10 +67,6 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
71
67
|
expect(subject.instance_variable_get(:@puppetfile_path)).to eq('/test/basedir/Puppetfile')
|
72
68
|
end
|
73
69
|
|
74
|
-
it 'uses the public forge' do
|
75
|
-
expect(subject.instance_variable_get(:@forge)).to eq('forgeapi.puppetlabs.com')
|
76
|
-
end
|
77
|
-
|
78
70
|
it 'creates an empty overrides' do
|
79
71
|
expect(subject.instance_variable_get(:@overrides)).to eq({})
|
80
72
|
end
|
@@ -91,14 +83,14 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
91
83
|
subject { R10K::ModuleLoader::Puppetfile.new(basedir: basedir) }
|
92
84
|
|
93
85
|
it 'should transform Forge modules with a string arg to have a version key' do
|
94
|
-
expect(R10K::Module).to receive(:
|
86
|
+
expect(R10K::Module).to receive(:from_metadata).with('puppet/test_module', subject.moduledir, hash_including(version: '1.2.3'), anything).and_call_original
|
95
87
|
|
96
88
|
expect { subject.add_module('puppet/test_module', '1.2.3') }.to change { subject.modules }
|
97
89
|
expect(subject.modules.collect(&:name)).to include('test_module')
|
98
90
|
end
|
99
91
|
|
100
92
|
it 'should not accept Forge modules with a version comparison' do
|
101
|
-
expect(R10K::Module).to receive(:
|
93
|
+
expect(R10K::Module).to receive(:from_metadata).with('puppet/test_module', subject.moduledir, hash_including(version: '< 1.2.0'), anything).and_call_original
|
102
94
|
|
103
95
|
expect {
|
104
96
|
subject.add_module('puppet/test_module', '< 1.2.0')
|
@@ -122,7 +114,7 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
122
114
|
it 'should accept non-Forge modules with a hash arg' do
|
123
115
|
module_opts = { git: 'git@example.com:puppet/test_module.git' }
|
124
116
|
|
125
|
-
expect(R10K::Module).to receive(:
|
117
|
+
expect(R10K::Module).to receive(:from_metadata).with('puppet/test_module', subject.moduledir, module_opts, anything).and_call_original
|
126
118
|
|
127
119
|
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
128
120
|
expect(subject.modules.collect(&:name)).to include('test_module')
|
@@ -134,7 +126,7 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
134
126
|
git: 'git@example.com:puppet/test_module.git',
|
135
127
|
}
|
136
128
|
|
137
|
-
expect(R10K::Module).to receive(:
|
129
|
+
expect(R10K::Module).to receive(:from_metadata).with('puppet/test_module', File.join(basedir, 'vendor'), module_opts, anything).and_call_original
|
138
130
|
|
139
131
|
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
140
132
|
expect(subject.modules.collect(&:name)).to include('test_module')
|
@@ -148,7 +140,7 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
148
140
|
git: 'git@example.com:puppet/test_module.git',
|
149
141
|
}
|
150
142
|
|
151
|
-
expect(R10K::Module).to receive(:
|
143
|
+
expect(R10K::Module).to receive(:from_metadata).with('puppet/test_module', install_path, module_opts, anything).and_call_original
|
152
144
|
|
153
145
|
expect { subject.add_module('puppet/test_module', module_opts) }.to change { subject.modules }
|
154
146
|
expect(subject.modules.collect(&:name)).to include('test_module')
|
@@ -175,11 +167,12 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
175
167
|
it 'should disable and not add modules that conflict with the environment' do
|
176
168
|
env = instance_double('R10K::Environment::Base')
|
177
169
|
mod = instance_double('R10K::Module::Base', name: 'conflict', origin: :puppetfile, 'origin=': nil)
|
170
|
+
allow(env).to receive(:name).and_return('conflict')
|
178
171
|
loader = R10K::ModuleLoader::Puppetfile.new(basedir: basedir, environment: env)
|
179
172
|
allow(env).to receive(:'module_conflicts?').with(mod).and_return(true)
|
180
173
|
allow(mod).to receive(:spec_deletable=)
|
181
174
|
|
182
|
-
expect(R10K::Module).to receive(:
|
175
|
+
expect(R10K::Module).to receive(:from_metadata).with('conflict', anything, anything, anything).and_return(mod)
|
183
176
|
expect { loader.add_module('conflict', {}) }.not_to change { loader.modules }
|
184
177
|
end
|
185
178
|
end
|
@@ -195,7 +188,9 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
195
188
|
context 'when belonging to an environment' do
|
196
189
|
let(:env_contents) { ['env1', 'env2' ] }
|
197
190
|
let(:env) { double(:environment, desired_contents: env_contents) }
|
198
|
-
|
191
|
+
before {
|
192
|
+
allow(env).to receive(:name).and_return('env1')
|
193
|
+
}
|
199
194
|
subject { R10K::ModuleLoader::Puppetfile.new(basedir: '/test/basedir', environment: env) }
|
200
195
|
|
201
196
|
it "includes environment's desired_contents" do
|
@@ -214,9 +209,9 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
214
209
|
end
|
215
210
|
|
216
211
|
it 'returns an array of paths that #purge! will operate within' do
|
217
|
-
expect(R10K::Module).to receive(:
|
212
|
+
expect(R10K::Module).to receive(:from_metadata).with('puppet/test_module', subject.moduledir, hash_including(version: '1.2.3'), anything).and_call_original
|
218
213
|
subject.add_module('puppet/test_module', '1.2.3')
|
219
|
-
subject.load
|
214
|
+
subject.load!
|
220
215
|
|
221
216
|
expect(subject.modules.length).to be 1
|
222
217
|
expect(subject.managed_directories).to match_array([subject.moduledir])
|
@@ -226,9 +221,9 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
226
221
|
it "basedir isn't in the list of paths to purge" do
|
227
222
|
module_opts = { install_path: '', git: 'git@example.com:puppet/test_module.git' }
|
228
223
|
|
229
|
-
expect(R10K::Module).to receive(:
|
224
|
+
expect(R10K::Module).to receive(:from_metadata).with('puppet/test_module', basedir, module_opts, anything).and_call_original
|
230
225
|
subject.add_module('puppet/test_module', module_opts)
|
231
|
-
subject.load
|
226
|
+
subject.load!
|
232
227
|
|
233
228
|
expect(subject.modules.length).to be 1
|
234
229
|
expect(subject.managed_directories).to be_empty
|
@@ -249,7 +244,7 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
249
244
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'invalid-syntax')
|
250
245
|
pf_path = File.join(@path, 'Puppetfile')
|
251
246
|
expect {
|
252
|
-
subject.load
|
247
|
+
subject.load!
|
253
248
|
}.to raise_error do |e|
|
254
249
|
expect_wrapped_error(e, pf_path, SyntaxError)
|
255
250
|
end
|
@@ -259,7 +254,7 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
259
254
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'load-error')
|
260
255
|
pf_path = File.join(@path, 'Puppetfile')
|
261
256
|
expect {
|
262
|
-
subject.load
|
257
|
+
subject.load!
|
263
258
|
}.to raise_error do |e|
|
264
259
|
expect_wrapped_error(e, pf_path, LoadError)
|
265
260
|
end
|
@@ -269,17 +264,38 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
269
264
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'argument-error')
|
270
265
|
pf_path = File.join(@path, 'Puppetfile')
|
271
266
|
expect {
|
272
|
-
subject.load
|
267
|
+
subject.load!
|
273
268
|
}.to raise_error do |e|
|
274
269
|
expect_wrapped_error(e, pf_path, ArgumentError)
|
275
270
|
end
|
276
271
|
end
|
277
272
|
|
273
|
+
describe 'forge declaration' do
|
274
|
+
before(:each) do
|
275
|
+
PuppetForge.host = ""
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'is respected if `allow_puppetfile_override` is true' do
|
279
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'forge-override')
|
280
|
+
puppetfile = R10K::ModuleLoader::Puppetfile.new(basedir: @path, overrides: { forge: { allow_puppetfile_override: true } })
|
281
|
+
puppetfile.load!
|
282
|
+
expect(PuppetForge.host).to eq("my.custom.forge.com/")
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'is ignored if `allow_puppetfile_override` is false' do
|
286
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'forge-override')
|
287
|
+
puppetfile = R10K::ModuleLoader::Puppetfile.new(basedir: @path, overrides: { forge: { allow_puppetfile_override: false } })
|
288
|
+
expect(PuppetForge).not_to receive(:host=).with("my.custom.forge.com")
|
289
|
+
puppetfile.load!
|
290
|
+
expect(PuppetForge.host).to eq("/")
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
278
294
|
it 'rejects Puppetfiles with duplicate module names' do
|
279
295
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'duplicate-module-error')
|
280
296
|
pf_path = File.join(@path, 'Puppetfile')
|
281
297
|
expect {
|
282
|
-
subject.load
|
298
|
+
subject.load!
|
283
299
|
}.to raise_error(R10K::Error, /Puppetfiles cannot contain duplicate module names/i)
|
284
300
|
end
|
285
301
|
|
@@ -287,7 +303,7 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
287
303
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'name-error')
|
288
304
|
pf_path = File.join(@path, 'Puppetfile')
|
289
305
|
expect {
|
290
|
-
subject.load
|
306
|
+
subject.load!
|
291
307
|
}.to raise_error do |e|
|
292
308
|
expect_wrapped_error(e, pf_path, NameError)
|
293
309
|
end
|
@@ -296,21 +312,21 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
296
312
|
it 'accepts a forge module with a version' do
|
297
313
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
298
314
|
pf_path = File.join(@path, 'Puppetfile')
|
299
|
-
expect { subject.load }.not_to raise_error
|
315
|
+
expect { subject.load! }.not_to raise_error
|
300
316
|
end
|
301
317
|
|
302
318
|
describe 'setting a custom moduledir' do
|
303
319
|
it 'allows setting an absolute moduledir' do
|
304
320
|
@path = '/fake/basedir'
|
305
321
|
allow(subject).to receive(:puppetfile_content).and_return('moduledir "/fake/moduledir"')
|
306
|
-
subject.load
|
322
|
+
subject.load!
|
307
323
|
expect(subject.instance_variable_get(:@moduledir)).to eq('/fake/moduledir')
|
308
324
|
end
|
309
325
|
|
310
326
|
it 'roots relative moduledirs in the basedir' do
|
311
327
|
@path = '/fake/basedir'
|
312
328
|
allow(subject).to receive(:puppetfile_content).and_return('moduledir "my/moduledir"')
|
313
|
-
subject.load
|
329
|
+
subject.load!
|
314
330
|
expect(subject.instance_variable_get(:@moduledir)).to eq(File.join(@path, 'my/moduledir'))
|
315
331
|
end
|
316
332
|
end
|
@@ -318,13 +334,13 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
318
334
|
it 'accepts a forge module without a version' do
|
319
335
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-without-version')
|
320
336
|
pf_path = File.join(@path, 'Puppetfile')
|
321
|
-
expect { subject.load }.not_to raise_error
|
337
|
+
expect { subject.load! }.not_to raise_error
|
322
338
|
end
|
323
339
|
|
324
340
|
it 'creates a git module and applies the default branch specified in the Puppetfile' do
|
325
341
|
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'default-branch-override')
|
326
342
|
pf_path = File.join(@path, 'Puppetfile')
|
327
|
-
expect { subject.load }.not_to raise_error
|
343
|
+
expect { subject.load! }.not_to raise_error
|
328
344
|
git_module = subject.modules[0]
|
329
345
|
expect(git_module.default_ref).to eq 'here_lies_the_default_branch'
|
330
346
|
end
|
@@ -334,10 +350,59 @@ describe R10K::ModuleLoader::Puppetfile do
|
|
334
350
|
pf_path = File.join(@path, 'Puppetfile')
|
335
351
|
default_branch_override = 'default_branch_override_name'
|
336
352
|
subject.default_branch_override = default_branch_override
|
337
|
-
expect { subject.load }.not_to raise_error
|
353
|
+
expect { subject.load! }.not_to raise_error
|
338
354
|
git_module = subject.modules[0]
|
339
355
|
expect(git_module.default_override_ref).to eq default_branch_override
|
340
356
|
expect(git_module.default_ref).to eq 'here_lies_the_default_branch'
|
341
357
|
end
|
358
|
+
|
359
|
+
describe 'using module metadata' do
|
360
|
+
it 'properly loads module metadata' do
|
361
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'various-modules')
|
362
|
+
metadata = subject.load_metadata[:modules].map { |mod| [ mod.name, mod.version ] }.to_h
|
363
|
+
expect(metadata['apt']).to eq('2.1.1')
|
364
|
+
expect(metadata['stdlib']).to eq(nil)
|
365
|
+
expect(metadata['concat']).to eq(nil)
|
366
|
+
expect(metadata['rpm']).to eq('2.1.1-pre1')
|
367
|
+
expect(metadata['foo']).to eq(nil)
|
368
|
+
expect(metadata['bar']).to eq('v1.2.3')
|
369
|
+
expect(metadata['baz']).to eq('123abc456')
|
370
|
+
expect(metadata['fizz']).to eq('1234567890abcdef1234567890abcdef12345678')
|
371
|
+
expect(metadata['buzz']).to eq(nil)
|
372
|
+
expect(metadata['canary']).to eq('0.0.0')
|
373
|
+
end
|
374
|
+
|
375
|
+
it 'does not load module implementations for static versioned' do
|
376
|
+
@path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'various-modules')
|
377
|
+
subject.load_metadata
|
378
|
+
modules = subject.load[:modules].map { |mod| [ mod.name, mod ] }.to_h
|
379
|
+
expect(modules['apt']).to be_a_kind_of(R10K::Module::Definition)
|
380
|
+
expect(modules['stdlib']).to be_a_kind_of(R10K::Module::Forge)
|
381
|
+
expect(modules['concat']).to be_a_kind_of(R10K::Module::Forge)
|
382
|
+
expect(modules['rpm']).to be_a_kind_of(R10K::Module::Definition)
|
383
|
+
expect(modules['foo']).to be_a_kind_of(R10K::Module::Git)
|
384
|
+
expect(modules['bar']).to be_a_kind_of(R10K::Module::Definition)
|
385
|
+
expect(modules['baz']).to be_a_kind_of(R10K::Module::Definition)
|
386
|
+
expect(modules['fizz']).to be_a_kind_of(R10K::Module::Definition)
|
387
|
+
expect(modules['buzz']).to be_a_kind_of(R10K::Module::Git)
|
388
|
+
expect(modules['canary']).to be_a_kind_of(R10K::Module::Definition)
|
389
|
+
end
|
390
|
+
|
391
|
+
it 'loads module implementations whose static versions are different' do
|
392
|
+
fixture_path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'various-modules')
|
393
|
+
@path = Dir.mktmpdir
|
394
|
+
unsynced_pf_path = File.join(fixture_path, 'Puppetfile')
|
395
|
+
FileUtils.cp(unsynced_pf_path, @path)
|
396
|
+
|
397
|
+
subject.load_metadata
|
398
|
+
|
399
|
+
synced_pf_path = File.join(fixture_path, 'Puppetfile.new')
|
400
|
+
FileUtils.cp(synced_pf_path, File.join(@path, 'Puppetfile'))
|
401
|
+
|
402
|
+
modules = subject.load[:modules].map { |mod| [ mod.name, mod ] }.to_h
|
403
|
+
|
404
|
+
expect(modules['apt']).to be_a_kind_of(R10K::Module::Forge)
|
405
|
+
end
|
406
|
+
end
|
342
407
|
end
|
343
408
|
end
|
@@ -114,7 +114,7 @@ describe R10K::Puppetfile do
|
|
114
114
|
path = File.join(PROJECT_ROOT, 'spec', 'fixtures', 'unit', 'puppetfile', 'valid-forge-with-version')
|
115
115
|
subject = described_class.new(path, {})
|
116
116
|
|
117
|
-
expect(subject.loader).to receive(:load).and_call_original.once
|
117
|
+
expect(subject.loader).to receive(:load!).and_call_original.once
|
118
118
|
|
119
119
|
loaded_content1 = subject.load
|
120
120
|
expect(subject.loaded?).to be true
|
@@ -273,7 +273,7 @@ describe R10K::Puppetfile do
|
|
273
273
|
expect(subject).to receive(:modules).and_return([mod1, mod2])
|
274
274
|
|
275
275
|
expect(Thread).to receive(:new).exactly(pool_size).and_call_original
|
276
|
-
expect(Queue).to receive(:new).and_call_original
|
276
|
+
expect(Queue).to receive(:new).and_call_original.twice
|
277
277
|
|
278
278
|
subject.accept(visitor)
|
279
279
|
end
|
data/spec/unit/settings_spec.rb
CHANGED
@@ -90,6 +90,27 @@ describe R10K::Settings do
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
describe "allow_puppetfile_override" do
|
95
|
+
it 'is false by default' do
|
96
|
+
expect(subject.evaluate({})[:allow_puppetfile_override]).to eq(false)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'can be set to true' do
|
100
|
+
expect(subject.evaluate({"allow_puppetfile_override" => true})[:allow_puppetfile_override]).to eq(true)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "raises an error for non-boolean values" do
|
104
|
+
expect {
|
105
|
+
subject.evaluate({"allow_puppetfile_override" => 'invalid_string'})
|
106
|
+
}.to raise_error do |err|
|
107
|
+
expect(err.message).to match(/Validation failed for 'forge' settings group/)
|
108
|
+
expect(err.errors.size).to eq 1
|
109
|
+
expect(err.errors[:allow_puppetfile_override]).to be_a_kind_of(ArgumentError)
|
110
|
+
expect(err.errors[:allow_puppetfile_override].message).to match(/`allow_puppetfile_override` can only be a boolean value, not 'invalid_string'/)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
93
114
|
end
|
94
115
|
|
95
116
|
describe "deploy settings" do
|
@@ -270,10 +291,12 @@ describe R10K::Settings do
|
|
270
291
|
it "passes settings through to the forge settings" do
|
271
292
|
output = subject.evaluate("forge" => {"baseurl" => "https://forge.tessier-ashpool.freeside",
|
272
293
|
"proxy" => "https://proxy.tessier-ashpool.freesize:3128",
|
273
|
-
"authorization_token" => "faketoken"
|
294
|
+
"authorization_token" => "faketoken",
|
295
|
+
"allow_puppetfile_override" => true})
|
274
296
|
expect(output[:forge]).to eq(:baseurl => "https://forge.tessier-ashpool.freeside",
|
275
297
|
:proxy => "https://proxy.tessier-ashpool.freesize:3128",
|
276
|
-
:authorization_token => "faketoken"
|
298
|
+
:authorization_token => "faketoken",
|
299
|
+
:allow_puppetfile_override => true)
|
277
300
|
end
|
278
301
|
end
|
279
302
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/tarball'
|
3
|
+
|
4
|
+
describe R10K::Tarball do
|
5
|
+
include_context 'Tarball'
|
6
|
+
|
7
|
+
subject { described_class.new('fixture-tarball', fixture_tarball, checksum: fixture_checksum) }
|
8
|
+
|
9
|
+
describe 'initialization' do
|
10
|
+
it 'initializes' do
|
11
|
+
expect(subject).to be_kind_of(described_class)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'downloading and caching' do
|
16
|
+
it 'downloads the source to the cache' do
|
17
|
+
# No cache present initially
|
18
|
+
expect(File.exist?(subject.cache_path)).to be(false)
|
19
|
+
expect(subject.cache_valid?).to be(false)
|
20
|
+
|
21
|
+
subject.get
|
22
|
+
|
23
|
+
expect(subject.cache_valid?).to be(true)
|
24
|
+
expect(File.exist?(subject.cache_path)).to be(true)
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:raw_content) {[
|
28
|
+
'./',
|
29
|
+
'./Puppetfile',
|
30
|
+
'./metadata.json',
|
31
|
+
'./spec/',
|
32
|
+
'./environment.conf',
|
33
|
+
'./spec/1',
|
34
|
+
]}
|
35
|
+
|
36
|
+
let(:clean_content) {[
|
37
|
+
'Puppetfile',
|
38
|
+
'metadata.json',
|
39
|
+
'spec',
|
40
|
+
'environment.conf',
|
41
|
+
'spec/1',
|
42
|
+
]}
|
43
|
+
|
44
|
+
it 'returns clean paths when listing cached tarball content' do
|
45
|
+
iterator = allow(subject).to receive(:each_tarball_entry)
|
46
|
+
raw_content.each { |entry| iterator.and_yield(entry) }
|
47
|
+
|
48
|
+
expect(subject.paths).to eq(clean_content)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'http sources'
|
53
|
+
|
54
|
+
describe 'file sources'
|
55
|
+
|
56
|
+
describe 'syncing'
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/util/cacheable'
|
3
|
+
|
4
|
+
RSpec.describe R10K::Util::Cacheable do
|
5
|
+
|
6
|
+
subject { Object.new.extend(R10K::Util::Cacheable) }
|
7
|
+
|
8
|
+
describe "dirname sanitization" do
|
9
|
+
let(:input) { 'git://some/git/remote' }
|
10
|
+
|
11
|
+
it 'sanitizes URL to directory name' do
|
12
|
+
expect(subject.sanitized_dirname(input)).to eq('git---some-git-remote')
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with username and password' do
|
16
|
+
let(:input) { 'https://"user:pa$$w0rd:@authenticated/git/remote' }
|
17
|
+
|
18
|
+
it 'sanitizes authenticated URL to directory name' do
|
19
|
+
expect(subject.sanitized_dirname(input)).to eq('https---authenticated-git-remote')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/util/downloader'
|
3
|
+
|
4
|
+
describe R10K::Util::Downloader do
|
5
|
+
|
6
|
+
subject(:downloader) do
|
7
|
+
subj = Object.new
|
8
|
+
subj.extend(R10K::Util::Downloader)
|
9
|
+
subj.singleton_class.class_eval { public :download }
|
10
|
+
subj.singleton_class.class_eval { public :http_get }
|
11
|
+
subj.singleton_class.class_eval { public :file_digest }
|
12
|
+
subj
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:tmpdir) { Dir.mktmpdir }
|
16
|
+
after(:each) { FileUtils.remove_entry_secure(tmpdir) }
|
17
|
+
|
18
|
+
describe 'http_get' do
|
19
|
+
let(:src_url) { 'https://example.com' }
|
20
|
+
let(:dst_file) { File.join(tmpdir, 'test.out') }
|
21
|
+
let(:tarball_uri) { URI('http://tarball.example.com/tarball.tar.gz') }
|
22
|
+
let(:redirect_uri) { URI('http://redirect.example.com/redirect') }
|
23
|
+
let(:proxy_uri) { URI('http://user:password@proxy.example.com') }
|
24
|
+
|
25
|
+
it 'downloads a simple file' do
|
26
|
+
mock_session = instance_double('Net::HTTP', active?: true)
|
27
|
+
tarball_response = instance_double('Net::HTTPSuccess')
|
28
|
+
|
29
|
+
expect(Net::HTTP).to receive(:new).with(tarball_uri.host, any_args).and_return(mock_session)
|
30
|
+
expect(Net::HTTPSuccess).to receive(:===).with(tarball_response).and_return(true)
|
31
|
+
|
32
|
+
expect(mock_session).to receive(:request_get).and_yield(tarball_response)
|
33
|
+
expect(mock_session).to receive(:start).once
|
34
|
+
expect(mock_session).to receive(:finish).once
|
35
|
+
|
36
|
+
expect { |b| downloader.http_get(tarball_uri, &b) }.to yield_with_args(tarball_response)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'follows redirects' do
|
40
|
+
mock_session_1 = instance_double('Net::HTTP', active?: false)
|
41
|
+
mock_session_2 = instance_double('Net::HTTP', active?: true)
|
42
|
+
redirect_response = instance_double('Net::HTTPRedirection')
|
43
|
+
tarball_response = instance_double('Net::HTTPSuccess')
|
44
|
+
|
45
|
+
expect(Net::HTTP).to receive(:new).with(redirect_uri.host, any_args).and_return(mock_session_1).once
|
46
|
+
expect(Net::HTTP).to receive(:new).with(tarball_uri.host, any_args).and_return(mock_session_2).once
|
47
|
+
expect(Net::HTTPRedirection).to receive(:===).with(redirect_response).and_return(true)
|
48
|
+
expect(Net::HTTPSuccess).to receive(:===).with(tarball_response).and_return(true)
|
49
|
+
allow(Net::HTTPRedirection).to receive(:===).and_call_original
|
50
|
+
|
51
|
+
expect(mock_session_1).to receive(:request_get).and_yield(redirect_response)
|
52
|
+
expect(mock_session_2).to receive(:request_get).and_yield(tarball_response)
|
53
|
+
|
54
|
+
# The redirect response should be queried for the redirect location
|
55
|
+
expect(redirect_response).to receive(:[]).with('location').and_return(tarball_uri.to_s)
|
56
|
+
|
57
|
+
# Both sessions should start and finish cleanly
|
58
|
+
expect(mock_session_1).to receive(:start).once
|
59
|
+
expect(mock_session_1).to receive(:finish).once
|
60
|
+
expect(mock_session_2).to receive(:start).once
|
61
|
+
expect(mock_session_2).to receive(:finish).once
|
62
|
+
|
63
|
+
expect { |b| downloader.http_get(redirect_uri, &b) }.to yield_with_args(tarball_response)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'can use a proxy' do
|
67
|
+
mock_session = instance_double('Net::HTTP', active?: true)
|
68
|
+
|
69
|
+
expect(Net::HTTP).to receive(:new)
|
70
|
+
.with(tarball_uri.host,
|
71
|
+
tarball_uri.port,
|
72
|
+
proxy_uri.host,
|
73
|
+
proxy_uri.port,
|
74
|
+
proxy_uri.user,
|
75
|
+
proxy_uri.password,
|
76
|
+
any_args)
|
77
|
+
.and_return(mock_session)
|
78
|
+
|
79
|
+
expect(mock_session).to receive(:request_get).and_return(:not_yielded)
|
80
|
+
expect(mock_session).to receive(:start).once
|
81
|
+
expect(mock_session).to receive(:finish).once
|
82
|
+
|
83
|
+
downloader.http_get(tarball_uri, proxy: proxy_uri)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'checksums' do
|
88
|
+
let(:fixture_checksum) { '0bcea17aa0c5e868c18f0fa042feda770e47c1a4223229f82116ccb3ca33c6e3' }
|
89
|
+
let(:fixture_tarball) do
|
90
|
+
File.expand_path('spec/fixtures/integration/git/puppet-boolean-bare.tar', PROJECT_ROOT)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'checksums files' do
|
94
|
+
expect(downloader.file_digest(fixture_tarball)).to eql(fixture_checksum)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -15,8 +15,10 @@ RSpec.describe R10K::Util::Purgeable do
|
|
15
15
|
'spec/fixtures/unit/util/purgeable/managed_one/expected_1',
|
16
16
|
'spec/fixtures/unit/util/purgeable/managed_one/new_1',
|
17
17
|
'spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1',
|
18
|
+
'spec/fixtures/unit/util/purgeable/managed_one/managed_symlink_dir',
|
18
19
|
'spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_expected_1',
|
19
20
|
'spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_new_1',
|
21
|
+
'spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_symlink_file',
|
20
22
|
'spec/fixtures/unit/util/purgeable/managed_two/expected_2',
|
21
23
|
'spec/fixtures/unit/util/purgeable/managed_two/new_2',
|
22
24
|
'spec/fixtures/unit/util/purgeable/managed_two/.hidden',
|
@@ -30,7 +32,8 @@ RSpec.describe R10K::Util::Purgeable do
|
|
30
32
|
|
31
33
|
describe '#current_contents' do
|
32
34
|
it 'collects direct contents of all managed directories' do
|
33
|
-
expect(subject.current_contents(recurse)).to contain_exactly(/\/expected_1/, /\/expected_2/, /\/unmanaged_1/, /\/unmanaged_2/,
|
35
|
+
expect(subject.current_contents(recurse)).to contain_exactly(/\/expected_1/, /\/expected_2/, /\/unmanaged_1/, /\/unmanaged_2/,
|
36
|
+
/\/managed_subdir_1/, /\/managed_symlink_dir/, /\/unmanaged_symlink_file/)
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
@@ -46,7 +49,7 @@ RSpec.describe R10K::Util::Purgeable do
|
|
46
49
|
let(:whitelist) { [] }
|
47
50
|
|
48
51
|
it 'collects current_contents that should not exist' do
|
49
|
-
expect(subject.stale_contents(recurse, exclusions, whitelist)).to contain_exactly(/\/unmanaged_1/, /\/unmanaged_2/)
|
52
|
+
expect(subject.stale_contents(recurse, exclusions, whitelist)).to contain_exactly(/\/unmanaged_1/, /\/unmanaged_2/, /\/unmanaged_symlink_file/)
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
@@ -56,7 +59,7 @@ RSpec.describe R10K::Util::Purgeable do
|
|
56
59
|
|
57
60
|
it 'collects current_contents that should not exist except whitelisted items' do
|
58
61
|
expect(subject.logger).to receive(:debug).with(/unmanaged_1.*whitelist match/i)
|
59
|
-
expect(subject.stale_contents(recurse, exclusions, whitelist)).to contain_exactly(/\/unmanaged_2/)
|
62
|
+
expect(subject.stale_contents(recurse, exclusions, whitelist)).to contain_exactly(/\/unmanaged_2/, /\/unmanaged_symlink_file/)
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
@@ -66,7 +69,7 @@ RSpec.describe R10K::Util::Purgeable do
|
|
66
69
|
|
67
70
|
it 'collects current_contents that should not exist except excluded items' do
|
68
71
|
expect(subject.logger).to receive(:debug2).with(/unmanaged_2.*internal exclusion match/i)
|
69
|
-
expect(subject.stale_contents(recurse, exclusions, whitelist)).to contain_exactly(/\/unmanaged_1/)
|
72
|
+
expect(subject.stale_contents(recurse, exclusions, whitelist)).to contain_exactly(/\/unmanaged_1/, /\/unmanaged_symlink_file/)
|
70
73
|
end
|
71
74
|
end
|
72
75
|
end
|
@@ -102,9 +105,13 @@ RSpec.describe R10K::Util::Purgeable do
|
|
102
105
|
expect(subject.current_contents(recurse)).
|
103
106
|
to contain_exactly(/\/expected_1/, /\/expected_2/,
|
104
107
|
/\/unmanaged_1/, /\/unmanaged_2/,
|
108
|
+
/\/managed_symlink_dir/,
|
109
|
+
/\/unmanaged_symlink_file/,
|
105
110
|
/\/managed_subdir_1/,
|
106
111
|
/\/subdir_expected_1/, /\/subdir_unmanaged_1/,
|
107
|
-
/\/
|
112
|
+
/\/managed_symlink_file/,
|
113
|
+
/\/unmanaged_symlink_dir/,
|
114
|
+
/\/subdir_allowlisted_2/, /\/ignored_1/,
|
108
115
|
/\/\.hidden/)
|
109
116
|
end
|
110
117
|
end
|
@@ -122,7 +129,8 @@ RSpec.describe R10K::Util::Purgeable do
|
|
122
129
|
|
123
130
|
it 'collects current_contents that should not exist recursively' do
|
124
131
|
expect(subject.stale_contents(recurse, exclusions, whitelist)).
|
125
|
-
to contain_exactly(/\/unmanaged_1/, /\/unmanaged_2/, /\/
|
132
|
+
to contain_exactly(/\/unmanaged_1/, /\/unmanaged_2/, /\/unmanaged_symlink_file/, /\/subdir_unmanaged_1/,
|
133
|
+
/\/ignored_1/, /\/subdir_allowlisted_2/, /\/unmanaged_symlink_dir/)
|
126
134
|
end
|
127
135
|
end
|
128
136
|
|
@@ -134,7 +142,8 @@ RSpec.describe R10K::Util::Purgeable do
|
|
134
142
|
expect(subject.logger).to receive(:debug).with(/unmanaged_1.*whitelist match/i)
|
135
143
|
|
136
144
|
expect(subject.stale_contents(recurse, exclusions, whitelist)).
|
137
|
-
to contain_exactly(/\/unmanaged_2/, /\/subdir_unmanaged_1/, /\/ignored_1
|
145
|
+
to contain_exactly(/\/unmanaged_2/, /\/subdir_unmanaged_1/, /\/unmanaged_symlink_file/, /\/ignored_1/,
|
146
|
+
/\/subdir_allowlisted_2/, /\/unmanaged_symlink_dir/)
|
138
147
|
end
|
139
148
|
|
140
149
|
it 'does not collect contents that match recursive globbed whitelist items as intermediate values' do
|
@@ -142,7 +151,7 @@ RSpec.describe R10K::Util::Purgeable do
|
|
142
151
|
expect(subject.logger).not_to receive(:debug).with(/ignored_1/)
|
143
152
|
|
144
153
|
expect(subject.stale_contents(recurse, exclusions, recursive_whitelist)).
|
145
|
-
to contain_exactly(/\/unmanaged_2/, /\/managed_one\/unmanaged_1/)
|
154
|
+
to contain_exactly(/\/unmanaged_2/, /\/managed_one\/unmanaged_1/, /\/managed_one\/unmanaged_symlink_file/)
|
146
155
|
end
|
147
156
|
end
|
148
157
|
|
@@ -154,7 +163,8 @@ RSpec.describe R10K::Util::Purgeable do
|
|
154
163
|
expect(subject.logger).to receive(:debug2).with(/unmanaged_2.*internal exclusion match/i)
|
155
164
|
|
156
165
|
expect(subject.stale_contents(recurse, exclusions, whitelist)).
|
157
|
-
to contain_exactly(/\/unmanaged_1/, /\/subdir_unmanaged_1/, /\/ignored_1
|
166
|
+
to contain_exactly(/\/unmanaged_1/, /\/unmanaged_symlink_file/, /\/subdir_unmanaged_1/, /\/ignored_1/,
|
167
|
+
/\/subdir_allowlisted_2/, /\/unmanaged_symlink_dir/)
|
158
168
|
end
|
159
169
|
|
160
170
|
it 'does not collect contents that match recursive globbed exclusion items as intermediate values' do
|
@@ -162,7 +172,7 @@ RSpec.describe R10K::Util::Purgeable do
|
|
162
172
|
expect(subject.logger).not_to receive(:debug).with(/ignored_1/)
|
163
173
|
|
164
174
|
expect(subject.stale_contents(recurse, recursive_exclusions, whitelist)).
|
165
|
-
to contain_exactly(/\/unmanaged_2/, /\/managed_one\/unmanaged_1/)
|
175
|
+
to contain_exactly(/\/unmanaged_2/, /\/unmanaged_symlink_file/, /\/managed_one\/unmanaged_1/)
|
166
176
|
end
|
167
177
|
end
|
168
178
|
end
|
@@ -199,6 +209,7 @@ RSpec.describe R10K::Util::Purgeable do
|
|
199
209
|
it 'does not purge items matching glob at root level' do
|
200
210
|
allow(FileUtils).to receive(:rm_r)
|
201
211
|
expect(FileUtils).to_not receive(:rm_r).with(/\/unmanaged_[12]/, anything)
|
212
|
+
expect(FileUtils).to_not receive(:rm_r).with(/\/unmanaged_symlink_file/, anything)
|
202
213
|
expect(subject.logger).to receive(:debug).with(/whitelist match/i).at_least(:once)
|
203
214
|
|
204
215
|
subject.purge!(purge_opts)
|
@@ -209,7 +220,7 @@ RSpec.describe R10K::Util::Purgeable do
|
|
209
220
|
context "recursive whitelist glob" do
|
210
221
|
let(:whitelist) do
|
211
222
|
managed_directories.flat_map do |dir|
|
212
|
-
[File.join(dir, "**", "*unmanaged*"), File.join(dir, "**", "
|
223
|
+
[File.join(dir, "**", "*unmanaged*"), File.join(dir, "**", "subdir_allowlisted_2")]
|
213
224
|
end
|
214
225
|
end
|
215
226
|
let(:purge_opts) { { recurse: true, whitelist: whitelist } }
|