puppetlabs_spec_helper 2.7.0 → 3.0.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 +5 -5
- data/.rspec +1 -1
- data/.rubocop.yml +114 -463
- data/.rubocop_todo.yml +119 -0
- data/.travis.yml +17 -16
- data/CHANGELOG.md +212 -5
- data/CODEOWNERS +2 -0
- data/Gemfile +32 -12
- data/HISTORY.md +498 -0
- data/README.md +81 -98
- data/Rakefile +37 -7
- data/lib/puppetlabs_spec_helper/module_spec_helper.rb +41 -0
- data/lib/puppetlabs_spec_helper/puppet_spec_helper.rb +12 -11
- data/lib/puppetlabs_spec_helper/puppetlabs_spec/files.rb +5 -3
- data/lib/puppetlabs_spec_helper/puppetlabs_spec/fixtures.rb +14 -10
- data/lib/puppetlabs_spec_helper/puppetlabs_spec/matchers.rb +12 -13
- data/lib/puppetlabs_spec_helper/puppetlabs_spec/puppet_internals.rb +20 -17
- data/lib/puppetlabs_spec_helper/puppetlabs_spec_helper.rb +3 -1
- data/lib/puppetlabs_spec_helper/rake_tasks.rb +250 -117
- data/lib/puppetlabs_spec_helper/tasks/beaker.rb +20 -16
- data/lib/puppetlabs_spec_helper/tasks/check_symlinks.rb +52 -0
- data/lib/puppetlabs_spec_helper/tasks/fixtures.rb +301 -167
- data/lib/puppetlabs_spec_helper/version.rb +3 -1
- data/puppet_spec_helper.rb +3 -1
- data/puppetlabs_spec_helper.gemspec +24 -22
- data/puppetlabs_spec_helper.rb +3 -1
- metadata +67 -26
|
@@ -1,58 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'yaml'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'json'
|
|
2
6
|
|
|
3
7
|
module PuppetlabsSpecHelper; end
|
|
4
8
|
module PuppetlabsSpecHelper::Tasks; end
|
|
9
|
+
|
|
5
10
|
module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
6
11
|
# This is a helper for the self-symlink entry of fixtures.yml
|
|
7
12
|
def source_dir
|
|
8
13
|
Dir.pwd
|
|
9
14
|
end
|
|
10
15
|
|
|
11
|
-
#
|
|
16
|
+
# @return [String] - the name of current module
|
|
17
|
+
def module_name
|
|
18
|
+
raise ArgumentError unless File.file?('metadata.json') && File.readable?('metadata.json')
|
|
19
|
+
|
|
20
|
+
metadata = JSON.parse(File.read('metadata.json'))
|
|
21
|
+
metadata_name = metadata.fetch('name', nil) || ''
|
|
22
|
+
|
|
23
|
+
raise ArgumentError if metadata_name.empty?
|
|
24
|
+
|
|
25
|
+
metadata_name.split('-').last
|
|
26
|
+
rescue JSON::ParserError, ArgumentError
|
|
27
|
+
File.basename(Dir.pwd).split('-').last
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def module_version(path)
|
|
31
|
+
metadata_path = File.join(path, 'metadata.json')
|
|
32
|
+
raise ArgumentError unless File.file?(metadata_path) && File.readable?(metadata_path)
|
|
33
|
+
|
|
34
|
+
metadata = JSON.parse(File.read(metadata_path))
|
|
35
|
+
metadata.fetch('version', nil) || '0.0.1'
|
|
36
|
+
rescue JSON::ParserError, ArgumentError
|
|
37
|
+
logger.warn "Failed to find module version at path #{path}"
|
|
38
|
+
'0.0.1'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Hash] - returns a hash of all the fixture repositories
|
|
42
|
+
# @example
|
|
43
|
+
# {"puppetlabs-stdlib"=>{"target"=>"https://gitlab.com/puppetlabs/puppet-stdlib.git",
|
|
44
|
+
# "ref"=>nil, "branch"=>"master", "scm"=>nil,
|
|
45
|
+
# }}
|
|
12
46
|
def repositories
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
47
|
+
@repositories ||= fixtures('repositories') || {}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Hash] - returns a hash of all the fixture forge modules
|
|
51
|
+
# @example
|
|
52
|
+
# {"puppetlabs-stdlib"=>{"target"=>"spec/fixtures/modules/stdlib",
|
|
53
|
+
# "ref"=>nil, "branch"=>nil, "scm"=>nil,
|
|
54
|
+
# "flags"=>"--module_repository=https://myforge.example.com/", "subdir"=>nil}}
|
|
55
|
+
def forge_modules
|
|
56
|
+
@forge_modules ||= fixtures('forge_modules') || {}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @return [Hash] - a hash of symlinks specified in the fixtures file
|
|
60
|
+
def symlinks
|
|
61
|
+
@symlinks ||= fixtures('symlinks') || {}
|
|
17
62
|
end
|
|
18
63
|
|
|
64
|
+
# @return [Hash] - returns a hash with the module name and the source directory
|
|
19
65
|
def auto_symlink
|
|
20
|
-
{
|
|
66
|
+
{ module_name => "\#{source_dir}" }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @return [Boolean] - true if the os is a windows system
|
|
70
|
+
def windows?
|
|
71
|
+
!!File::ALT_SEPARATOR
|
|
21
72
|
end
|
|
22
73
|
|
|
23
74
|
def fixtures(category)
|
|
24
|
-
if ENV['FIXTURES_YML']
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
75
|
+
fixtures_yaml = if ENV['FIXTURES_YML']
|
|
76
|
+
ENV['FIXTURES_YML']
|
|
77
|
+
elsif File.exist?('.fixtures.yml')
|
|
78
|
+
'.fixtures.yml'
|
|
79
|
+
elsif File.exist?('.fixtures.yaml')
|
|
80
|
+
'.fixtures.yaml'
|
|
81
|
+
else
|
|
82
|
+
false
|
|
83
|
+
end
|
|
33
84
|
|
|
34
85
|
begin
|
|
35
|
-
if fixtures_yaml
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
86
|
+
fixtures = if fixtures_yaml
|
|
87
|
+
YAML.load_file(fixtures_yaml) || { 'fixtures' => {} }
|
|
88
|
+
else
|
|
89
|
+
{ 'fixtures' => {} }
|
|
90
|
+
end
|
|
40
91
|
rescue Errno::ENOENT
|
|
41
|
-
|
|
92
|
+
raise("Fixtures file not found: '#{fixtures_yaml}'")
|
|
42
93
|
rescue Psych::SyntaxError => e
|
|
43
|
-
|
|
94
|
+
raise("Found malformed YAML in '#{fixtures_yaml}' on line #{e.line} column #{e.column}: #{e.problem}")
|
|
44
95
|
end
|
|
45
96
|
|
|
46
97
|
unless fixtures.include?('fixtures')
|
|
47
98
|
# File is non-empty, but does not specify fixtures
|
|
48
|
-
|
|
99
|
+
raise("No 'fixtures' entries found in '#{fixtures_yaml}'; required")
|
|
49
100
|
end
|
|
50
101
|
|
|
51
|
-
if fixtures.include? 'defaults'
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
102
|
+
fixture_defaults = if fixtures.include? 'defaults'
|
|
103
|
+
fixtures['defaults']
|
|
104
|
+
else
|
|
105
|
+
{}
|
|
106
|
+
end
|
|
56
107
|
|
|
57
108
|
fixtures = fixtures['fixtures']
|
|
58
109
|
|
|
@@ -61,9 +112,8 @@ module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
|
61
112
|
end
|
|
62
113
|
|
|
63
114
|
result = {}
|
|
64
|
-
if fixtures.include?
|
|
65
|
-
|
|
66
|
-
defaults = { "target" => "spec/fixtures/modules" }
|
|
115
|
+
if fixtures.include?(category) && !fixtures[category].nil?
|
|
116
|
+
defaults = { 'target' => 'spec/fixtures/modules' }
|
|
67
117
|
|
|
68
118
|
# load defaults from the `.fixtures.yml` `defaults` section
|
|
69
119
|
# for the requested category and merge them into my defaults
|
|
@@ -75,25 +125,56 @@ module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
|
75
125
|
# convert a simple string fixture to a hash, by
|
|
76
126
|
# using the string fixture as the `repo` option of the hash.
|
|
77
127
|
if opts.instance_of?(String)
|
|
78
|
-
opts = {
|
|
128
|
+
opts = { 'repo' => opts }
|
|
79
129
|
end
|
|
80
130
|
# there should be a warning or something if it's not a hash...
|
|
81
|
-
|
|
82
|
-
# merge our options into the defaults to get the
|
|
83
|
-
# final option list
|
|
84
|
-
opts = defaults.merge(opts)
|
|
131
|
+
next unless opts.instance_of?(Hash)
|
|
85
132
|
|
|
86
|
-
|
|
87
|
-
|
|
133
|
+
# merge our options into the defaults to get the
|
|
134
|
+
# final option list
|
|
135
|
+
opts = defaults.merge(opts)
|
|
88
136
|
|
|
89
|
-
|
|
90
|
-
|
|
137
|
+
next unless include_repo?(opts['puppet_version'])
|
|
138
|
+
|
|
139
|
+
real_target = eval("\"#{opts['target']}\"", binding, __FILE__, __LINE__) # evaluating target reference in this context (see auto_symlink)
|
|
140
|
+
real_source = eval("\"#{opts['repo']}\"", binding, __FILE__, __LINE__) # evaluating repo reference in this context (see auto_symlink)
|
|
141
|
+
|
|
142
|
+
result[real_source] = validate_fixture_hash!(
|
|
143
|
+
'target' => File.join(real_target, fixture),
|
|
144
|
+
'ref' => opts['ref'] || opts['tag'],
|
|
145
|
+
'branch' => opts['branch'],
|
|
146
|
+
'scm' => opts['scm'],
|
|
147
|
+
'flags' => opts['flags'],
|
|
148
|
+
'subdir' => opts['subdir'],
|
|
149
|
+
)
|
|
91
150
|
end
|
|
92
151
|
end
|
|
93
|
-
|
|
152
|
+
result
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def validate_fixture_hash!(hash)
|
|
156
|
+
# Can only validate git based scm
|
|
157
|
+
return hash unless hash['scm'] == 'git'
|
|
158
|
+
|
|
159
|
+
# Forward slashes in the ref aren't allowed. And is probably a branch name.
|
|
160
|
+
raise ArgumentError, "The ref for #{hash['target']} is invalid (Contains a forward slash). If this is a branch name, please use the 'branch' setting instead." if hash['ref'] =~ %r{/}
|
|
161
|
+
|
|
162
|
+
hash
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def include_repo?(version_range)
|
|
166
|
+
if version_range && defined?(SemanticPuppet)
|
|
167
|
+
puppet_spec = Gem::Specification.find_by_name('puppet')
|
|
168
|
+
puppet_version = SemanticPuppet::Version.parse(puppet_spec.version.to_s)
|
|
169
|
+
|
|
170
|
+
constraint = SemanticPuppet::VersionRange.parse(version_range)
|
|
171
|
+
constraint.include?(puppet_version)
|
|
172
|
+
else
|
|
173
|
+
true
|
|
174
|
+
end
|
|
94
175
|
end
|
|
95
176
|
|
|
96
|
-
def clone_repo(scm, remote, target,
|
|
177
|
+
def clone_repo(scm, remote, target, _subdir = nil, ref = nil, branch = nil, flags = nil)
|
|
97
178
|
args = []
|
|
98
179
|
case scm
|
|
99
180
|
when 'hg'
|
|
@@ -108,15 +189,34 @@ module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
|
108
189
|
args.push(flags) if flags
|
|
109
190
|
args.push(remote, target)
|
|
110
191
|
else
|
|
111
|
-
|
|
192
|
+
raise "Unfortunately #{scm} is not supported yet"
|
|
112
193
|
end
|
|
113
194
|
result = system("#{scm} #{args.flatten.join ' '}")
|
|
114
|
-
unless File
|
|
115
|
-
|
|
195
|
+
unless File.exist?(target)
|
|
196
|
+
raise "Failed to clone #{scm} repository #{remote} into #{target}"
|
|
116
197
|
end
|
|
198
|
+
|
|
117
199
|
result
|
|
118
200
|
end
|
|
119
201
|
|
|
202
|
+
def update_repo(scm, target)
|
|
203
|
+
args = case scm
|
|
204
|
+
when 'hg'
|
|
205
|
+
['pull']
|
|
206
|
+
when 'git'
|
|
207
|
+
['fetch'].tap do |git_args|
|
|
208
|
+
git_args << '--unshallow' if shallow_git_repo?
|
|
209
|
+
end
|
|
210
|
+
else
|
|
211
|
+
raise "Unfortunately #{scm} is not supported yet"
|
|
212
|
+
end
|
|
213
|
+
system("#{scm} #{args.flatten.join(' ')}", chdir: target)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def shallow_git_repo?
|
|
217
|
+
File.file?(File.join('.git', 'shallow'))
|
|
218
|
+
end
|
|
219
|
+
|
|
120
220
|
def revision(scm, target, ref)
|
|
121
221
|
args = []
|
|
122
222
|
case scm
|
|
@@ -125,18 +225,35 @@ module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
|
125
225
|
when 'git'
|
|
126
226
|
args.push('reset', '--hard', ref)
|
|
127
227
|
else
|
|
128
|
-
|
|
228
|
+
raise "Unfortunately #{scm} is not supported yet"
|
|
129
229
|
end
|
|
130
|
-
system("
|
|
230
|
+
result = system("#{scm} #{args.flatten.join ' '}", chdir: target)
|
|
231
|
+
raise "Invalid ref #{ref} for #{target}" unless result
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def valid_repo?(scm, target, remote)
|
|
235
|
+
return false unless File.directory?(target)
|
|
236
|
+
return true if scm == 'hg'
|
|
237
|
+
|
|
238
|
+
return true if git_remote_url(target) == remote
|
|
239
|
+
|
|
240
|
+
warn "Git remote for #{target} has changed, recloning repository"
|
|
241
|
+
FileUtils.rm_rf(target)
|
|
242
|
+
false
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def git_remote_url(target)
|
|
246
|
+
output, status = Open3.capture2e('git', '--git-dir', File.join(target, '.git'), 'ls-remote', '--get-url', 'origin')
|
|
247
|
+
status.success? ? output.strip : nil
|
|
131
248
|
end
|
|
132
249
|
|
|
133
250
|
def remove_subdirectory(target, subdir)
|
|
134
251
|
unless subdir.nil?
|
|
135
|
-
Dir.mktmpdir
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
252
|
+
Dir.mktmpdir do |tmpdir|
|
|
253
|
+
FileUtils.mv(Dir.glob("#{target}/#{subdir}/{.[^\.]*,*}"), tmpdir)
|
|
254
|
+
FileUtils.rm_rf("#{target}/#{subdir}")
|
|
255
|
+
FileUtils.mv(Dir.glob("#{tmpdir}/{.[^\.]*,*}"), target.to_s)
|
|
256
|
+
end
|
|
140
257
|
end
|
|
141
258
|
end
|
|
142
259
|
|
|
@@ -144,12 +261,12 @@ module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
|
144
261
|
def logger
|
|
145
262
|
unless @logger
|
|
146
263
|
require 'logger'
|
|
147
|
-
if ENV['ENABLE_LOGGER']
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
@logger = Logger.new(
|
|
264
|
+
level = if ENV['ENABLE_LOGGER']
|
|
265
|
+
Logger::DEBUG
|
|
266
|
+
else
|
|
267
|
+
Logger::INFO
|
|
268
|
+
end
|
|
269
|
+
@logger = Logger.new($stderr)
|
|
153
270
|
@logger.level = level
|
|
154
271
|
end
|
|
155
272
|
@logger
|
|
@@ -159,14 +276,15 @@ module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
|
159
276
|
# The problem with the relative path is that PMT doesn't expand the path properly and so passing in a relative path here
|
|
160
277
|
# becomes something like C:\somewhere\backslashes/spec/fixtures/work-dir on Windows, and then PMT barfs itself.
|
|
161
278
|
# This has been reported as https://tickets.puppetlabs.com/browse/PUP-4884
|
|
162
|
-
File.expand_path(ENV['MODULE_WORKING_DIR']
|
|
279
|
+
File.expand_path(ENV['MODULE_WORKING_DIR'] || 'spec/fixtures/work-dir')
|
|
163
280
|
end
|
|
164
281
|
|
|
165
282
|
# returns the current thread count that is currently active
|
|
166
283
|
# a status of false or nil means the thread completed
|
|
167
284
|
# so when anything else we count that as a active thread
|
|
285
|
+
# @return [Integer] - current thread count
|
|
168
286
|
def current_thread_count(items)
|
|
169
|
-
active_threads = items.find_all do |
|
|
287
|
+
active_threads = items.find_all do |_item, opts|
|
|
170
288
|
if opts[:thread]
|
|
171
289
|
opts[:thread].status
|
|
172
290
|
else
|
|
@@ -177,152 +295,168 @@ module PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
|
177
295
|
active_threads.count
|
|
178
296
|
end
|
|
179
297
|
|
|
180
|
-
#
|
|
181
|
-
#
|
|
298
|
+
# @summary Set a limit on the amount threads used, defaults to 10
|
|
299
|
+
# MAX_FIXTURE_THREAD_COUNT can be used to set this limit
|
|
300
|
+
# @return [Integer] - returns the max_thread_count
|
|
182
301
|
def max_thread_limit
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
302
|
+
@max_thread_limit ||= (ENV['MAX_FIXTURE_THREAD_COUNT'] || 10).to_i
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# @param items [Hash] - a hash of either repositories or forge modules
|
|
306
|
+
# @param [Block] - the method you wish to use to download the item
|
|
307
|
+
def download_items(items)
|
|
308
|
+
items.each do |remote, opts|
|
|
309
|
+
# get the current active threads that are alive
|
|
310
|
+
count = current_thread_count(items)
|
|
311
|
+
if count < max_thread_limit
|
|
312
|
+
logger.debug "New Thread started for #{remote}"
|
|
313
|
+
# start up a new thread and store it in the opts hash
|
|
314
|
+
opts[:thread] = Thread.new do
|
|
315
|
+
yield(remote, opts)
|
|
316
|
+
end
|
|
188
317
|
else
|
|
189
|
-
|
|
318
|
+
# the last thread started should be the longest wait
|
|
319
|
+
item, item_opts = items.find_all { |_i, o| o.key?(:thread) }.last
|
|
320
|
+
logger.debug "Waiting on #{item}"
|
|
321
|
+
item_opts[:thread].join # wait for the thread to finish
|
|
322
|
+
# now that we waited lets try again
|
|
323
|
+
redo
|
|
190
324
|
end
|
|
191
325
|
end
|
|
192
|
-
|
|
326
|
+
# wait for all the threads to finish
|
|
327
|
+
items.each { |_remote, opts| opts[:thread].join }
|
|
193
328
|
end
|
|
194
329
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
330
|
+
# @param target [String] - the target directory
|
|
331
|
+
# @param link [String] - the name of the link you wish to create
|
|
332
|
+
# works on windows and linux
|
|
333
|
+
def setup_symlink(target, link)
|
|
334
|
+
link = link['target']
|
|
335
|
+
return if File.symlink?(link)
|
|
198
336
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
337
|
+
logger.info("Creating symlink from #{link} to #{target}")
|
|
338
|
+
if windows?
|
|
339
|
+
target = File.join(File.dirname(link), target) unless Pathname.new(target).absolute?
|
|
340
|
+
if Dir.respond_to?(:create_junction)
|
|
341
|
+
Dir.create_junction(link, target)
|
|
342
|
+
else
|
|
343
|
+
system("call mklink /J \"#{link.tr('/', '\\')}\" \"#{target.tr('/', '\\')}\"")
|
|
204
344
|
end
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
results
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
include PuppetlabsSpecHelper::Tasks::FixtureHelpers
|
|
211
|
-
|
|
212
|
-
desc "Create the fixtures directory"
|
|
213
|
-
task :spec_prep do
|
|
214
|
-
# Ruby only sets File::ALT_SEPARATOR on Windows and Rubys standard library
|
|
215
|
-
# uses this to check for Windows
|
|
216
|
-
is_windows = !!File::ALT_SEPARATOR
|
|
217
|
-
if is_windows
|
|
218
|
-
begin
|
|
219
|
-
require 'win32/dir'
|
|
220
|
-
rescue LoadError
|
|
221
|
-
$stderr.puts "win32-dir gem not installed, falling back to executing mklink directly"
|
|
345
|
+
else
|
|
346
|
+
FileUtils.ln_sf(target, link)
|
|
222
347
|
end
|
|
223
348
|
end
|
|
224
349
|
|
|
225
|
-
#
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
350
|
+
# @return [Boolean] - returns true if the module was downloaded successfully, false otherwise
|
|
351
|
+
# @param [String] - the remote url or namespace/name of the module to download
|
|
352
|
+
# @param [Hash] - list of options such as version, branch, ref
|
|
353
|
+
def download_repository(remote, opts)
|
|
229
354
|
scm = 'git'
|
|
230
|
-
target = opts[
|
|
231
|
-
subdir = opts[
|
|
232
|
-
ref = opts[
|
|
233
|
-
scm = opts[
|
|
234
|
-
branch = opts[
|
|
235
|
-
flags = opts[
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if count < max_thread_limit
|
|
239
|
-
logger.debug "New Thread started for #{remote}"
|
|
240
|
-
# start up a new thread and store it in the opts hash
|
|
241
|
-
opts[:thread] = Thread.new do
|
|
242
|
-
clone_repo(scm, remote, target, subdir, ref, branch, flags)
|
|
243
|
-
revision(scm, target, ref) if ref
|
|
244
|
-
remove_subdirectory(target, subdir) if subdir
|
|
245
|
-
end
|
|
355
|
+
target = opts['target']
|
|
356
|
+
subdir = opts['subdir']
|
|
357
|
+
ref = opts['ref']
|
|
358
|
+
scm = opts['scm'] if opts['scm']
|
|
359
|
+
branch = opts['branch'] if opts['branch']
|
|
360
|
+
flags = opts['flags']
|
|
361
|
+
if valid_repo?(scm, target, remote)
|
|
362
|
+
update_repo(scm, target)
|
|
246
363
|
else
|
|
247
|
-
|
|
248
|
-
item, item_opts = repositories.find_all {|i,o| o.has_key?(:thread)}.last
|
|
249
|
-
logger.debug "Waiting on #{item}"
|
|
250
|
-
item_opts[:thread].join # wait for the thread to finish
|
|
251
|
-
# now that we waited lets try again
|
|
252
|
-
redo
|
|
364
|
+
clone_repo(scm, remote, target, subdir, ref, branch, flags)
|
|
253
365
|
end
|
|
366
|
+
revision(scm, target, ref) if ref
|
|
367
|
+
remove_subdirectory(target, subdir) if subdir
|
|
254
368
|
end
|
|
255
369
|
|
|
256
|
-
#
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
fixtures("symlinks").each do |target, link|
|
|
260
|
-
link = link['target']
|
|
261
|
-
unless File.symlink?(link)
|
|
262
|
-
logger.info("Creating symlink from #{link} to #{target}")
|
|
263
|
-
if is_windows
|
|
264
|
-
target = File.join(File.dirname(link), target) unless Pathname.new(target).absolute?
|
|
265
|
-
if Dir.respond_to?(:create_junction)
|
|
266
|
-
Dir.create_junction(link, target)
|
|
267
|
-
else
|
|
268
|
-
system("call mklink /J \"#{link.gsub('/', '\\')}\" \"#{target.gsub('/', '\\')}\"")
|
|
269
|
-
end
|
|
270
|
-
else
|
|
271
|
-
FileUtils::ln_sf(target, link)
|
|
272
|
-
end
|
|
273
|
-
end
|
|
370
|
+
# @return [String] - the spec/fixtures/modules directory in the module root folder
|
|
371
|
+
def module_target_dir
|
|
372
|
+
@module_target_dir ||= File.expand_path('spec/fixtures/modules')
|
|
274
373
|
end
|
|
275
374
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
375
|
+
# @return [Boolean] - returns true if the module was downloaded successfully, false otherwise
|
|
376
|
+
# @param [String] - the remote url or namespace/name of the module to download
|
|
377
|
+
# @param [Hash] - list of options such as version
|
|
378
|
+
def download_module(remote, opts)
|
|
379
|
+
ref = ''
|
|
380
|
+
flags = ''
|
|
279
381
|
if opts.instance_of?(String)
|
|
280
382
|
target = opts
|
|
281
383
|
elsif opts.instance_of?(Hash)
|
|
282
|
-
target = opts[
|
|
283
|
-
ref = " --version #{opts['ref']}"
|
|
384
|
+
target = opts['target']
|
|
385
|
+
ref = " --version #{opts['ref']}" unless opts['ref'].nil?
|
|
284
386
|
flags = " #{opts['flags']}" if opts['flags']
|
|
285
387
|
end
|
|
286
|
-
next if File::exists?(target)
|
|
287
388
|
|
|
288
|
-
|
|
289
|
-
target_dir = File.expand_path('spec/fixtures/modules')
|
|
389
|
+
return false if File.directory?(target) && (ref.empty? || opts['ref'] == module_version(target))
|
|
290
390
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
391
|
+
# The PMT cannot handle multi threaded runs due to cache directory collisons
|
|
392
|
+
# so we randomize the directory instead.
|
|
393
|
+
# Does working_dir even need to be passed?
|
|
394
|
+
Dir.mktmpdir do |working_dir|
|
|
395
|
+
command = "puppet module install#{ref}#{flags} --ignore-dependencies" \
|
|
396
|
+
' --force' \
|
|
294
397
|
" --module_working_dir \"#{working_dir}\"" \
|
|
295
|
-
" --target-dir \"#{
|
|
398
|
+
" --target-dir \"#{module_target_dir}\" \"#{remote}\""
|
|
296
399
|
|
|
297
|
-
|
|
298
|
-
|
|
400
|
+
unless system(command)
|
|
401
|
+
raise "Failed to install module #{remote} to #{module_target_dir}"
|
|
402
|
+
end
|
|
299
403
|
end
|
|
404
|
+
$CHILD_STATUS.success?
|
|
300
405
|
end
|
|
406
|
+
end
|
|
301
407
|
|
|
302
|
-
|
|
303
|
-
|
|
408
|
+
include PuppetlabsSpecHelper::Tasks::FixtureHelpers # DSL include # rubocop:disable Style/MixinUsage
|
|
409
|
+
|
|
410
|
+
desc 'Create the fixtures directory'
|
|
411
|
+
task :spec_prep do
|
|
412
|
+
# Ruby only sets File::ALT_SEPARATOR on Windows and Rubys standard library
|
|
413
|
+
# uses this to check for Windows
|
|
414
|
+
if windows?
|
|
415
|
+
begin
|
|
416
|
+
require 'win32/dir'
|
|
417
|
+
rescue LoadError
|
|
418
|
+
warn 'win32-dir gem not installed, falling back to executing mklink directly'
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# git has a race condition creating that directory, that would lead to aborted clone operations
|
|
423
|
+
FileUtils.mkdir_p('spec/fixtures/modules')
|
|
424
|
+
|
|
425
|
+
symlinks.each { |target, link| setup_symlink(target, link) }
|
|
426
|
+
|
|
427
|
+
download_items(repositories) { |remote, opts| download_repository(remote, opts) }
|
|
428
|
+
|
|
429
|
+
download_items(forge_modules) { |remote, opts| download_module(remote, opts) }
|
|
430
|
+
|
|
431
|
+
FileUtils.mkdir_p('spec/fixtures/manifests')
|
|
432
|
+
FileUtils.touch('spec/fixtures/manifests/site.pp')
|
|
304
433
|
end
|
|
305
434
|
|
|
306
|
-
desc
|
|
435
|
+
desc 'Clean up the fixtures directory'
|
|
307
436
|
task :spec_clean do
|
|
308
|
-
|
|
309
|
-
target = opts[
|
|
310
|
-
FileUtils
|
|
437
|
+
repositories.each do |_remote, opts|
|
|
438
|
+
target = opts['target']
|
|
439
|
+
FileUtils.rm_rf(target)
|
|
311
440
|
end
|
|
312
441
|
|
|
313
|
-
|
|
314
|
-
target = opts[
|
|
315
|
-
FileUtils
|
|
442
|
+
forge_modules.each do |_remote, opts|
|
|
443
|
+
target = opts['target']
|
|
444
|
+
FileUtils.rm_rf(target)
|
|
316
445
|
end
|
|
317
446
|
|
|
318
|
-
FileUtils
|
|
447
|
+
FileUtils.rm_rf(module_working_directory)
|
|
319
448
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
449
|
+
Rake::Task[:spec_clean_symlinks].invoke
|
|
450
|
+
|
|
451
|
+
if File.zero?('spec/fixtures/manifests/site.pp')
|
|
452
|
+
FileUtils.rm_f('spec/fixtures/manifests/site.pp')
|
|
323
453
|
end
|
|
454
|
+
end
|
|
324
455
|
|
|
325
|
-
|
|
326
|
-
|
|
456
|
+
desc 'Clean up any fixture symlinks'
|
|
457
|
+
task :spec_clean_symlinks do
|
|
458
|
+
fixtures('symlinks').each do |_source, opts|
|
|
459
|
+
target = opts['target']
|
|
460
|
+
FileUtils.rm_f(target)
|
|
327
461
|
end
|
|
328
462
|
end
|
data/puppet_spec_helper.rb
CHANGED