simp-beaker-helpers 1.18.8
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 +7 -0
- data/.fixtures.yml +8 -0
- data/.gitignore +8 -0
- data/.gitlab-ci.yml +163 -0
- data/.rspec +4 -0
- data/.rubocop.yml +546 -0
- data/.travis.yml +36 -0
- data/CHANGELOG.md +231 -0
- data/Gemfile +51 -0
- data/LICENSE +27 -0
- data/README.md +543 -0
- data/Rakefile +151 -0
- data/files/pki/clean.sh +1 -0
- data/files/pki/make.sh +101 -0
- data/files/pki/template_ca.cnf +259 -0
- data/files/pki/template_host.cnf +263 -0
- data/files/puppet-agent-versions.yaml +46 -0
- data/lib/simp/beaker_helpers.rb +1231 -0
- data/lib/simp/beaker_helpers/constants.rb +25 -0
- data/lib/simp/beaker_helpers/inspec.rb +328 -0
- data/lib/simp/beaker_helpers/snapshot.rb +156 -0
- data/lib/simp/beaker_helpers/ssg.rb +383 -0
- data/lib/simp/beaker_helpers/version.rb +5 -0
- data/lib/simp/beaker_helpers/windows.rb +16 -0
- data/lib/simp/rake/beaker.rb +269 -0
- data/simp-beaker-helpers.gemspec +38 -0
- data/spec/acceptance/nodesets/default.yml +32 -0
- data/spec/acceptance/suites/default/check_puppet_version_spec.rb +23 -0
- data/spec/acceptance/suites/default/enable_fips_spec.rb +23 -0
- data/spec/acceptance/suites/default/fixture_modules_spec.rb +22 -0
- data/spec/acceptance/suites/default/install_simp_deps_repo_spec.rb +43 -0
- data/spec/acceptance/suites/default/nodesets +1 -0
- data/spec/acceptance/suites/default/pki_tests_spec.rb +55 -0
- data/spec/acceptance/suites/default/set_hieradata_on_spec.rb +33 -0
- data/spec/acceptance/suites/default/write_hieradata_to_spec.rb +33 -0
- data/spec/acceptance/suites/fips_from_fixtures/00_default_spec.rb +63 -0
- data/spec/acceptance/suites/fips_from_fixtures/metadata.yml +2 -0
- data/spec/acceptance/suites/fips_from_fixtures/nodesets +1 -0
- data/spec/acceptance/suites/offline/00_default_spec.rb +165 -0
- data/spec/acceptance/suites/offline/README +2 -0
- data/spec/acceptance/suites/offline/nodesets/default.yml +26 -0
- data/spec/acceptance/suites/puppet_collections/00_default_spec.rb +25 -0
- data/spec/acceptance/suites/puppet_collections/metadata.yml +2 -0
- data/spec/acceptance/suites/puppet_collections/nodesets/default.yml +30 -0
- data/spec/acceptance/suites/snapshot/00_snapshot_test_spec.rb +82 -0
- data/spec/acceptance/suites/snapshot/10_general_usage_spec.rb +56 -0
- data/spec/acceptance/suites/snapshot/nodesets +1 -0
- data/spec/acceptance/suites/windows/00_default_spec.rb +119 -0
- data/spec/acceptance/suites/windows/metadata.yml +2 -0
- data/spec/acceptance/suites/windows/nodesets/default.yml +33 -0
- data/spec/acceptance/suites/windows/nodesets/win2016.yml +35 -0
- data/spec/acceptance/suites/windows/nodesets/win2019.yml +34 -0
- data/spec/lib/simp/beaker_helpers_spec.rb +216 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/spec_helper_acceptance.rb +25 -0
- metadata +243 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
module Simp; end
|
2
|
+
|
3
|
+
module Simp::BeakerHelpers
|
4
|
+
# This is the *oldest* puppet-agent version that the latest release of SIMP supports
|
5
|
+
#
|
6
|
+
# This is done so that we know if some new thing that we're using breaks the
|
7
|
+
# oldest system that we support
|
8
|
+
DEFAULT_PUPPET_AGENT_VERSION = '~> 5.0'
|
9
|
+
|
10
|
+
SSG_REPO_URL = ENV['BEAKER_ssg_repo'] || 'https://github.com/ComplianceAsCode/content.git'
|
11
|
+
|
12
|
+
if ['true','yes'].include?(ENV['BEAKER_online'])
|
13
|
+
ONLINE = true
|
14
|
+
elsif ['false','no'].include?(ENV['BEAKER_online'])
|
15
|
+
ONLINE = false
|
16
|
+
else
|
17
|
+
require 'open-uri'
|
18
|
+
|
19
|
+
begin
|
20
|
+
ONLINE = true if open('http://google.com')
|
21
|
+
rescue
|
22
|
+
ONLINE = false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,328 @@
|
|
1
|
+
module Simp::BeakerHelpers
|
2
|
+
require 'simp/beaker_helpers/constants'
|
3
|
+
|
4
|
+
# Helpers for working with Inspec
|
5
|
+
class Inspec
|
6
|
+
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
attr_reader :profile
|
10
|
+
attr_reader :profile_dir
|
11
|
+
attr_reader :deps_root
|
12
|
+
|
13
|
+
# Create a new Inspec helper for the specified host against the specified profile
|
14
|
+
#
|
15
|
+
# @param sut
|
16
|
+
# The SUT against which to run
|
17
|
+
#
|
18
|
+
# @param profile
|
19
|
+
# The name of the profile against which to run
|
20
|
+
#
|
21
|
+
def initialize(sut, profile)
|
22
|
+
@inspec_version = ENV['BEAKER_inspec_version'] || 'latest'
|
23
|
+
|
24
|
+
@sut = sut
|
25
|
+
|
26
|
+
@sut.install_package('git')
|
27
|
+
|
28
|
+
if @inspec_version == 'latest'
|
29
|
+
@sut.install_package('inspec')
|
30
|
+
else
|
31
|
+
@sut.install_package("inspec-#{@inspec_version}")
|
32
|
+
end
|
33
|
+
|
34
|
+
os = fact_on(@sut, 'operatingsystem')
|
35
|
+
os_rel = fact_on(@sut, 'operatingsystemmajrelease')
|
36
|
+
|
37
|
+
@profile = "#{os}-#{os_rel}-#{profile}"
|
38
|
+
@profile_dir = '/tmp/inspec/inspec_profiles'
|
39
|
+
@deps_root = '/tmp/inspec'
|
40
|
+
|
41
|
+
@test_dir = @profile_dir + "/#{@profile}"
|
42
|
+
|
43
|
+
sut.mkdir_p(@profile_dir)
|
44
|
+
|
45
|
+
output_dir = File.absolute_path('sec_results/inspec')
|
46
|
+
|
47
|
+
unless File.directory?(output_dir)
|
48
|
+
FileUtils.mkdir_p(output_dir)
|
49
|
+
end
|
50
|
+
|
51
|
+
local_profile = File.join(fixtures_path, 'inspec_profiles', %(#{os}-#{os_rel}-#{profile}))
|
52
|
+
local_deps = File.join(fixtures_path, 'inspec_deps')
|
53
|
+
|
54
|
+
@result_file = File.join(output_dir, "#{@sut.hostname}-inspec-#{Time.now.to_i}")
|
55
|
+
|
56
|
+
copy_to(@sut, local_profile, @profile_dir)
|
57
|
+
|
58
|
+
if File.exist?(local_deps)
|
59
|
+
copy_to(@sut, local_deps, @deps_root)
|
60
|
+
end
|
61
|
+
|
62
|
+
# The results of the inspec scan in Hash form
|
63
|
+
@results = {}
|
64
|
+
end
|
65
|
+
|
66
|
+
# Run the inspec tests and record the results
|
67
|
+
def run
|
68
|
+
sut_inspec_results = '/tmp/inspec_results.json'
|
69
|
+
|
70
|
+
inspec_version = Gem::Version.new(on(@sut, 'inspec --version').output.lines.first.strip)
|
71
|
+
|
72
|
+
# See: https://github.com/inspec/inspec/pull/3935
|
73
|
+
if inspec_version <= Gem::Version.new('3.9.0')
|
74
|
+
inspec_cmd = "inspec exec '#{@test_dir}' --reporter json > #{sut_inspec_results}"
|
75
|
+
else
|
76
|
+
inspec_cmd = "inspec exec '#{@test_dir}' --chef-license accept --reporter json > #{sut_inspec_results}"
|
77
|
+
end
|
78
|
+
|
79
|
+
result = on(@sut, inspec_cmd, :accept_all_exit_codes => true)
|
80
|
+
|
81
|
+
tmpdir = Dir.mktmpdir
|
82
|
+
begin
|
83
|
+
Dir.chdir(tmpdir) do
|
84
|
+
if @sut[:hypervisor] == 'docker'
|
85
|
+
# Work around for breaking changes in beaker-docker
|
86
|
+
if @sut.host_hash[:docker_container]
|
87
|
+
container_id = @sut.host_hash[:docker_container].id
|
88
|
+
else
|
89
|
+
container_id = @sut.host_hash[:docker_container_id]
|
90
|
+
end
|
91
|
+
|
92
|
+
%x(docker cp "#{container_id}:#{sut_inspec_results}" .)
|
93
|
+
else
|
94
|
+
scp_from(@sut, sut_inspec_results, '.')
|
95
|
+
end
|
96
|
+
|
97
|
+
local_inspec_results = File.basename(sut_inspec_results)
|
98
|
+
|
99
|
+
if File.exist?(local_inspec_results)
|
100
|
+
begin
|
101
|
+
# The output is occasionally broken from past experience. Need to
|
102
|
+
# fetch the line that actually looks like JSON
|
103
|
+
inspec_json = File.read(local_inspec_results).lines.find do |line|
|
104
|
+
line.strip!
|
105
|
+
|
106
|
+
line.start_with?('{') && line.end_with?('}')
|
107
|
+
end
|
108
|
+
|
109
|
+
@results = JSON.load(inspec_json) if inspec_json
|
110
|
+
rescue JSON::ParserError, JSON::GeneratorError
|
111
|
+
@results = nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
ensure
|
116
|
+
FileUtils.remove_entry_secure tmpdir
|
117
|
+
end
|
118
|
+
|
119
|
+
if @results.nil? || @results.empty?
|
120
|
+
File.open(@result_file + '.err', 'w') do |fh|
|
121
|
+
fh.puts(result.stderr.strip)
|
122
|
+
end
|
123
|
+
|
124
|
+
err_msg = ["Error running inspec command #{inspec_cmd}"]
|
125
|
+
err_msg << "Error captured in #{@result_file}" + '.err'
|
126
|
+
|
127
|
+
fail(err_msg.join("\n"))
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Output the report
|
132
|
+
#
|
133
|
+
# @param report
|
134
|
+
# The inspec results Hash
|
135
|
+
#
|
136
|
+
def write_report(report)
|
137
|
+
File.open(@result_file + '.json', 'w') do |fh|
|
138
|
+
fh.puts(JSON.pretty_generate(@results))
|
139
|
+
end
|
140
|
+
|
141
|
+
File.open(@result_file + '.report', 'w') do |fh|
|
142
|
+
fh.puts(report[:report].uncolor)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def process_inspec_results
|
147
|
+
self.class.process_inspec_results(@results)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Process the results of an InSpec run
|
151
|
+
#
|
152
|
+
# @return [Hash] A Hash of statistics and a formatted report
|
153
|
+
#
|
154
|
+
def self.process_inspec_results(results)
|
155
|
+
require 'highline'
|
156
|
+
|
157
|
+
HighLine.colorize_strings
|
158
|
+
|
159
|
+
stats = {
|
160
|
+
# Legacy metrics counters for backwards compatibility
|
161
|
+
:failed => 0,
|
162
|
+
:passed => 0,
|
163
|
+
:skipped => 0,
|
164
|
+
:overridden => 0,
|
165
|
+
# End legacy stuff
|
166
|
+
:global => {
|
167
|
+
:failed => [],
|
168
|
+
:passed => [],
|
169
|
+
:skipped => [],
|
170
|
+
:overridden => []
|
171
|
+
},
|
172
|
+
:score => 0,
|
173
|
+
:report => nil,
|
174
|
+
:profiles => {}
|
175
|
+
}
|
176
|
+
|
177
|
+
if results.is_a?(String)
|
178
|
+
if File.readable?(results)
|
179
|
+
profiles = JSON.load(File.read(results))['profiles']
|
180
|
+
else
|
181
|
+
fail("Error: Could not read results file at #{results}")
|
182
|
+
end
|
183
|
+
elsif results.is_a?(Hash)
|
184
|
+
profiles = results['profiles']
|
185
|
+
else
|
186
|
+
fail("Error: first argument must be a String path to a file or a Hash")
|
187
|
+
end
|
188
|
+
|
189
|
+
if !profiles || profiles.empty?
|
190
|
+
fail("Error: Could not find 'profiles' in the passed results")
|
191
|
+
end
|
192
|
+
|
193
|
+
profiles.each do |profile|
|
194
|
+
profile_name = profile['name']
|
195
|
+
|
196
|
+
next unless profile_name
|
197
|
+
|
198
|
+
stats[:profiles][profile_name] = {
|
199
|
+
:controls => {}
|
200
|
+
}
|
201
|
+
|
202
|
+
profile['controls'].each do |control|
|
203
|
+
title = control['title']
|
204
|
+
|
205
|
+
next unless title
|
206
|
+
|
207
|
+
base_title = title.scan(/.{1,60}\W|.{1,60}/).map(&:strip).join("\n ")
|
208
|
+
|
209
|
+
if control['results'] && (control['results'].size > 1)
|
210
|
+
control['results'].each do |result|
|
211
|
+
control_title = " => { #{result['code_desc']} }"
|
212
|
+
|
213
|
+
full_title = title + control_title
|
214
|
+
formatted_title = base_title + control_title
|
215
|
+
|
216
|
+
stats[:profiles][profile_name][:controls][full_title] = {}
|
217
|
+
|
218
|
+
stats[:profiles][profile_name][:controls][full_title][:formatted_title] = formatted_title
|
219
|
+
|
220
|
+
if result['status'] =~ /^fail/
|
221
|
+
status = :failed
|
222
|
+
color = 'red'
|
223
|
+
else
|
224
|
+
status = :passed
|
225
|
+
color = 'green'
|
226
|
+
end
|
227
|
+
|
228
|
+
stats[:global][status] << formatted_title.color
|
229
|
+
|
230
|
+
stats[:profiles][profile_name][:controls][full_title][:status] = status
|
231
|
+
stats[:profiles][profile_name][:controls][full_title][:source] = control['source_location']['ref']
|
232
|
+
end
|
233
|
+
else
|
234
|
+
formatted_title = base_title
|
235
|
+
|
236
|
+
stats[:profiles][profile_name][:controls][title] = {}
|
237
|
+
|
238
|
+
stats[:profiles][profile_name][:controls][title][:formatted_title] = formatted_title
|
239
|
+
|
240
|
+
if control['results'] && !control['results'].empty?
|
241
|
+
status = :passed
|
242
|
+
color = 'green'
|
243
|
+
|
244
|
+
control['results'].each do |result|
|
245
|
+
if results['status'] =~ /^fail/
|
246
|
+
status = :failed
|
247
|
+
color = 'red'
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
else
|
252
|
+
status = :skipped
|
253
|
+
end
|
254
|
+
|
255
|
+
stats[:global][status] << formatted_title.color
|
256
|
+
|
257
|
+
stats[:profiles][profile_name][:controls][title][:status] = status
|
258
|
+
stats[:profiles][profile_name][:controls][title][:source] = control['source_location']['ref']
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
valid_checks = stats[:global][:failed] + stats[:global][:passed]
|
264
|
+
stats[:global][:skipped].dup.each do |skipped|
|
265
|
+
if valid_checks.include?(skipped)
|
266
|
+
stats[:global][:overridden] << skipped
|
267
|
+
stats[:global][:skipped].delete(skipped)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
status_colors = {
|
272
|
+
:failed => 'red',
|
273
|
+
:passed => 'green',
|
274
|
+
:skipped => 'yellow',
|
275
|
+
:overridden => 'white'
|
276
|
+
}
|
277
|
+
|
278
|
+
report = []
|
279
|
+
|
280
|
+
stats[:profiles].keys.each do |profile|
|
281
|
+
report << "Profile: #{profile}"
|
282
|
+
|
283
|
+
stats[:profiles][profile][:controls].each do |control|
|
284
|
+
control_info = control.last
|
285
|
+
|
286
|
+
report << "\n Control: #{control_info[:formatted_title]}"
|
287
|
+
|
288
|
+
if control_info[:status] == :skipped && stats[:global][:overridden].include?(control.first)
|
289
|
+
control_info[:status] = :overridden
|
290
|
+
end
|
291
|
+
|
292
|
+
report << " Status: #{control_info[:status].to_s.send(status_colors[control_info[:status]])}"
|
293
|
+
report << " File: #{control_info[:source]}" if control_info[:source]
|
294
|
+
end
|
295
|
+
|
296
|
+
report << "\n"
|
297
|
+
end
|
298
|
+
|
299
|
+
num_passed = stats[:global][:passed].count
|
300
|
+
num_failed = stats[:global][:failed].count
|
301
|
+
num_skipped = stats[:global][:skipped].count
|
302
|
+
num_overridden = stats[:global][:overridden].count
|
303
|
+
|
304
|
+
# Backwards compat values
|
305
|
+
stats[:passed] = num_passed
|
306
|
+
stats[:failed] = num_failed
|
307
|
+
stats[:skipped] = num_skipped
|
308
|
+
stats[:overridden] = num_overridden
|
309
|
+
|
310
|
+
report << "Statistics:"
|
311
|
+
report << " * Passed: #{num_passed.to_s.green}"
|
312
|
+
report << " * Failed: #{num_failed.to_s.red}"
|
313
|
+
report << " * Skipped: #{num_skipped.to_s.yellow}"
|
314
|
+
|
315
|
+
score = 0
|
316
|
+
if (stats[:global][:passed].count + stats[:global][:failed].count) > 0
|
317
|
+
score = ((stats[:global][:passed].count.to_f/(stats[:global][:passed].count + stats[:global][:failed].count)) * 100.0).round(0)
|
318
|
+
end
|
319
|
+
|
320
|
+
report << "\n Score: #{score}%"
|
321
|
+
|
322
|
+
stats[:score] = score
|
323
|
+
stats[:report] = report.join("\n")
|
324
|
+
|
325
|
+
return stats
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Simp::BeakerHelpers
|
2
|
+
# Helpers for managing Vagrant snapshots
|
3
|
+
class Snapshot
|
4
|
+
# The name of the base snapshot that is created if no snapshots currently exist
|
5
|
+
BASE_NAME = '_simp_beaker_base'
|
6
|
+
|
7
|
+
# Save a snapshot
|
8
|
+
#
|
9
|
+
# @param host [Beaker::Host]
|
10
|
+
# The SUT to work on
|
11
|
+
#
|
12
|
+
# @param snapshot_name [String]
|
13
|
+
# The string to add to the snapshot
|
14
|
+
#
|
15
|
+
def self.save(host, snapshot_name)
|
16
|
+
if enabled?
|
17
|
+
vdir = vagrant_dir(host)
|
18
|
+
|
19
|
+
if vdir
|
20
|
+
Dir.chdir(vdir) do
|
21
|
+
save(host, BASE_NAME) unless exist?(host, BASE_NAME)
|
22
|
+
|
23
|
+
snap = "#{host.name}_#{snapshot_name}"
|
24
|
+
|
25
|
+
output = %x(vagrant snapshot save --force #{host.name} "#{snap}")
|
26
|
+
|
27
|
+
logger.notify(output)
|
28
|
+
|
29
|
+
retry_on(
|
30
|
+
host,
|
31
|
+
%(echo "saving snapshot '#{snap}'" > /dev/null),
|
32
|
+
:max_retries => 30,
|
33
|
+
:retry_interval => 1
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Whether or not a named snapshot exists
|
41
|
+
#
|
42
|
+
# @param host [Beaker::Host]
|
43
|
+
# The SUT to work on
|
44
|
+
#
|
45
|
+
# @param snapshot_name [String]
|
46
|
+
# The string to add to the snapshot
|
47
|
+
#
|
48
|
+
# @return [Boolean]
|
49
|
+
def self.exist?(host, name)
|
50
|
+
list(host).include?(name)
|
51
|
+
end
|
52
|
+
|
53
|
+
# List all snapshots for the given host
|
54
|
+
#
|
55
|
+
# @parma host [Beaker::Host]
|
56
|
+
# The SUT to work on
|
57
|
+
#
|
58
|
+
# @return [Array[String]]
|
59
|
+
# A list of snapshot names for the host
|
60
|
+
def self.list(host)
|
61
|
+
output = []
|
62
|
+
vdir = vagrant_dir(host)
|
63
|
+
|
64
|
+
if vdir
|
65
|
+
Dir.chdir(vdir) do
|
66
|
+
output = %x(vagrant snapshot list #{host.name}).lines
|
67
|
+
output.map! do |x|
|
68
|
+
x.split(/^#{host.name}_/).last.split(':').first.delete('==>').strip
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
output
|
74
|
+
end
|
75
|
+
|
76
|
+
# Restore a snapshot
|
77
|
+
#
|
78
|
+
# @param host [Beaker::Host]
|
79
|
+
# The SUT to work on
|
80
|
+
#
|
81
|
+
# @param snapshot_name [String]
|
82
|
+
# The name that was added to the snapshot
|
83
|
+
#
|
84
|
+
def self.restore(host, snapshot_name)
|
85
|
+
if enabled?
|
86
|
+
vdir = vagrant_dir(host)
|
87
|
+
|
88
|
+
if vdir
|
89
|
+
Dir.chdir(vdir) do
|
90
|
+
snap = "#{host.name}_#{snapshot_name}"
|
91
|
+
|
92
|
+
output = %x(vagrant snapshot restore #{host.name} "#{snap}" 2>&1)
|
93
|
+
|
94
|
+
if (output =~ /error/i) && (output =~ /child/)
|
95
|
+
raise output
|
96
|
+
end
|
97
|
+
|
98
|
+
if (output =~ /snapshot.*not found/)
|
99
|
+
raise output
|
100
|
+
end
|
101
|
+
|
102
|
+
logger.notify(output)
|
103
|
+
|
104
|
+
retry_on(
|
105
|
+
host,
|
106
|
+
%(echo "restoring snapshot '#{snap}'" > /dev/null),
|
107
|
+
:max_retries => 30,
|
108
|
+
:retry_interval => 1
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Restore all the way back to the base image
|
116
|
+
#
|
117
|
+
# @param host [Beaker::Host]
|
118
|
+
# The SUT to work on
|
119
|
+
#
|
120
|
+
def self.restore_to_base(host)
|
121
|
+
if exist?(host, BASE_NAME)
|
122
|
+
restore(host, BASE_NAME)
|
123
|
+
else
|
124
|
+
save(host, BASE_NAME)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def self.enabled?
|
131
|
+
enabled = ENV['BEAKER_simp_snapshot'] == 'yes'
|
132
|
+
|
133
|
+
unless enabled
|
134
|
+
logger.warn('Snapshotting not enabled, set BEAKER_simp_snapshot=yes to enable')
|
135
|
+
end
|
136
|
+
|
137
|
+
return enabled
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.vagrant_dir(host)
|
141
|
+
tgt_dir = nil
|
142
|
+
|
143
|
+
if host && host.options && host.options[:hosts_file]
|
144
|
+
vdir = File.join('.vagrant', 'beaker_vagrant_files', File.basename(host.options[:hosts_file]))
|
145
|
+
|
146
|
+
if File.directory?(vdir)
|
147
|
+
tgt_dir = vdir
|
148
|
+
else
|
149
|
+
logger.notify("Could not find local vagrant dir at #{vdir}")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
return tgt_dir
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|