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