inspec 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -2
- data/bin/inspec +11 -9
- data/docs/matchers.rst +129 -0
- data/docs/resources.rst +64 -37
- data/inspec.gemspec +1 -1
- data/lib/bundles/inspec-compliance/cli.rb +1 -1
- data/lib/bundles/inspec-compliance/configuration.rb +1 -0
- data/lib/bundles/inspec-compliance/target.rb +16 -32
- data/lib/bundles/inspec-init/cli.rb +2 -0
- data/lib/bundles/inspec-supermarket.rb +13 -0
- data/lib/bundles/inspec-supermarket/api.rb +2 -0
- data/lib/bundles/inspec-supermarket/cli.rb +2 -2
- data/lib/bundles/inspec-supermarket/target.rb +11 -15
- data/lib/fetchers/local.rb +31 -0
- data/lib/fetchers/tar.rb +48 -0
- data/lib/fetchers/url.rb +100 -0
- data/lib/fetchers/zip.rb +47 -0
- data/lib/inspec.rb +2 -3
- data/lib/inspec/fetcher.rb +22 -0
- data/lib/inspec/metadata.rb +4 -2
- data/lib/inspec/plugins.rb +2 -0
- data/lib/inspec/plugins/fetcher.rb +97 -0
- data/lib/inspec/plugins/source_reader.rb +36 -0
- data/lib/inspec/profile.rb +92 -81
- data/lib/inspec/resource.rb +1 -0
- data/lib/inspec/runner.rb +15 -35
- data/lib/inspec/source_reader.rb +32 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +5 -6
- data/lib/resources/file.rb +8 -2
- data/lib/resources/passwd.rb +71 -45
- data/lib/resources/service.rb +13 -9
- data/lib/resources/shadow.rb +135 -0
- data/lib/source_readers/flat.rb +38 -0
- data/lib/source_readers/inspec.rb +78 -0
- data/lib/utils/base_cli.rb +2 -2
- data/lib/utils/parser.rb +1 -1
- data/lib/utils/plugin_registry.rb +93 -0
- data/test/docker_test.rb +1 -1
- data/test/helper.rb +62 -2
- data/test/integration/cookbooks/os_prepare/recipes/service.rb +4 -2
- data/test/integration/test/integration/default/compare_matcher_spec.rb +11 -0
- data/test/integration/test/integration/default/service_spec.rb +16 -1
- data/test/unit/fetchers.rb +61 -0
- data/test/unit/fetchers/local_test.rb +67 -0
- data/test/unit/fetchers/tar_test.rb +36 -0
- data/test/unit/fetchers/url_test.rb +152 -0
- data/test/unit/fetchers/zip_test.rb +36 -0
- data/test/unit/mock/files/passwd +1 -1
- data/test/unit/mock/files/shadow +2 -0
- data/test/unit/mock/profiles/complete-profile/libraries/testlib.rb +1 -0
- data/test/unit/plugin_test.rb +0 -1
- data/test/unit/profile_test.rb +32 -53
- data/test/unit/resources/passwd_test.rb +69 -14
- data/test/unit/resources/shadow_test.rb +67 -0
- data/test/unit/source_reader_test.rb +17 -0
- data/test/unit/source_readers/flat_test.rb +61 -0
- data/test/unit/source_readers/inspec_test.rb +38 -0
- data/test/unit/utils/passwd_parser_test.rb +1 -1
- metadata +40 -21
- data/lib/inspec/targets.rb +0 -10
- data/lib/inspec/targets/archive.rb +0 -33
- data/lib/inspec/targets/core.rb +0 -56
- data/lib/inspec/targets/dir.rb +0 -144
- data/lib/inspec/targets/file.rb +0 -33
- data/lib/inspec/targets/folder.rb +0 -38
- data/lib/inspec/targets/tar.rb +0 -61
- data/lib/inspec/targets/url.rb +0 -78
- data/lib/inspec/targets/zip.rb +0 -55
- data/test/unit/targets.rb +0 -132
data/lib/inspec/plugins.rb
CHANGED
@@ -9,6 +9,8 @@ module Inspec
|
|
9
9
|
module Plugins
|
10
10
|
autoload :Resource, 'inspec/plugins/resource'
|
11
11
|
autoload :CLI, 'inspec/plugins/cli'
|
12
|
+
autoload :Fetcher, 'inspec/plugins/fetcher'
|
13
|
+
autoload :SourceReader, 'inspec/plugins/source_reader'
|
12
14
|
end
|
13
15
|
|
14
16
|
# PLEASE NOTE: The Plugin system is an internal mechanism for connecting
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Dominik Richter
|
3
|
+
# author: Christoph Hartmann
|
4
|
+
|
5
|
+
require 'utils/plugin_registry'
|
6
|
+
|
7
|
+
module Inspec
|
8
|
+
module Plugins
|
9
|
+
class Fetcher < PluginRegistry::Plugin
|
10
|
+
def self.plugin_registry
|
11
|
+
Inspec::Fetcher
|
12
|
+
end
|
13
|
+
|
14
|
+
# Provide a list of files that are available to this fetcher.
|
15
|
+
#
|
16
|
+
# @return [Array[String]] A list of filenames
|
17
|
+
def files
|
18
|
+
fail "Fetcher #{self} does not implement `files()`. This is required."
|
19
|
+
end
|
20
|
+
|
21
|
+
# Read a file using this fetcher. The name must correspond to a file
|
22
|
+
# available to this fetcher. Use #files to retrieve the list of
|
23
|
+
# files.
|
24
|
+
#
|
25
|
+
# @param [String] _file The filename you are interested in
|
26
|
+
# @return [String] The file's contents
|
27
|
+
def read(_file)
|
28
|
+
fail "Fetcher #{self} does not implement `read(...)`. This is required."
|
29
|
+
end
|
30
|
+
|
31
|
+
def relative_target
|
32
|
+
RelFetcher.new(self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class RelFetcher < Fetcher
|
37
|
+
attr_reader :files
|
38
|
+
attr_reader :prefix
|
39
|
+
|
40
|
+
def initialize(fetcher)
|
41
|
+
@parent = fetcher
|
42
|
+
@prefix = get_prefix(fetcher.files)
|
43
|
+
@files = fetcher.files.find_all { |x| x.start_with? prefix }
|
44
|
+
.map { |x| x[prefix.length..-1] }
|
45
|
+
end
|
46
|
+
|
47
|
+
def abs_path(file)
|
48
|
+
prefix + file
|
49
|
+
end
|
50
|
+
|
51
|
+
def read(file)
|
52
|
+
@parent.read(abs_path(file))
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def get_prefix(fs)
|
58
|
+
return '' if fs.empty?
|
59
|
+
sorted = fs.sort_by(&:length)
|
60
|
+
get_folder_prefix(sorted)
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_folder_prefix(fs, first_iteration = true)
|
64
|
+
return get_files_prefix(fs) if fs.length == 1
|
65
|
+
pre = fs[0] + File::SEPARATOR
|
66
|
+
rest = fs[1..-1]
|
67
|
+
if rest.all? { |i| i.start_with? pre }
|
68
|
+
return get_folder_prefix(rest, false)
|
69
|
+
end
|
70
|
+
return get_files_prefix(fs) if first_iteration
|
71
|
+
fs
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_files_prefix(fs)
|
75
|
+
return '' if fs.empty?
|
76
|
+
|
77
|
+
file = fs[0]
|
78
|
+
bn = File.basename(file)
|
79
|
+
# no more prefixes
|
80
|
+
return '' if bn == file
|
81
|
+
|
82
|
+
i = file.rindex(bn)
|
83
|
+
pre = file[0..i-1]
|
84
|
+
|
85
|
+
rest = fs.find_all { |f| !f.start_with?(pre) }
|
86
|
+
return pre if rest.empty?
|
87
|
+
|
88
|
+
new_pre = get_prefix(rest)
|
89
|
+
return new_pre if pre.start_with? new_pre
|
90
|
+
# edge case: completely different prefixes; retry prefix detection
|
91
|
+
a = File.dirname(pre + 'a')
|
92
|
+
b = File.dirname(new_pre + 'b')
|
93
|
+
get_prefix([a, b])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Dominik Richter
|
3
|
+
# author: Christoph Hartmann
|
4
|
+
|
5
|
+
require 'utils/plugin_registry'
|
6
|
+
|
7
|
+
module Inspec
|
8
|
+
module Plugins
|
9
|
+
class SourceReader < PluginRegistry::Plugin
|
10
|
+
def self.plugin_registry
|
11
|
+
Inspec::SourceReader
|
12
|
+
end
|
13
|
+
|
14
|
+
# Retrieve this profile's metadata.
|
15
|
+
#
|
16
|
+
# @return [Inspec::Metadata] profile metadata
|
17
|
+
def metadata
|
18
|
+
fail "SourceReader #{self} does not implement `metadata()`. This method is required"
|
19
|
+
end
|
20
|
+
|
21
|
+
# Retrieve this profile's tests
|
22
|
+
#
|
23
|
+
# @return [Hash] Collection with references pointing to test contents
|
24
|
+
def tests
|
25
|
+
fail "SourceReader #{self} does not implement `tests()`. This method is required"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Retrieve this profile's libraries
|
29
|
+
#
|
30
|
+
# @return [Hash] Collection with references pointing to library contents
|
31
|
+
def libraries
|
32
|
+
fail "SourceReader #{self} does not implement `libraries()`. This method is required"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -3,71 +3,53 @@
|
|
3
3
|
# author: Dominik Richter
|
4
4
|
# author: Christoph Hartmann
|
5
5
|
|
6
|
+
require 'forwardable'
|
7
|
+
require 'inspec/fetcher'
|
8
|
+
require 'inspec/source_reader'
|
6
9
|
require 'inspec/metadata'
|
7
|
-
require 'pathname'
|
8
10
|
|
9
11
|
module Inspec
|
10
12
|
class Profile # rubocop:disable Metrics/ClassLength
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
extend Forwardable
|
14
|
+
attr_reader :path
|
15
|
+
|
16
|
+
def self.for_target(target, opts)
|
17
|
+
# Fetchers retrieve file contents
|
18
|
+
opts[:target] = target
|
19
|
+
fetcher = Inspec::Fetcher.resolve(target)
|
20
|
+
return nil if fetcher.nil?
|
21
|
+
# Source readers understand the target's structure and provide
|
22
|
+
# access to tests, libraries, and metadata
|
23
|
+
reader = Inspec::SourceReader.resolve(fetcher.relative_target)
|
24
|
+
return nil if reader.nil?
|
25
|
+
new(reader, opts)
|
16
26
|
end
|
17
27
|
|
18
|
-
attr_reader :
|
19
|
-
|
20
|
-
|
28
|
+
attr_reader :source_reader
|
29
|
+
def_delegator :@source_reader, :tests
|
30
|
+
def_delegator :@source_reader, :libraries
|
31
|
+
def_delegator :@source_reader, :metadata
|
21
32
|
|
22
33
|
# rubocop:disable Metrics/AbcSize
|
23
|
-
def initialize(options = nil)
|
34
|
+
def initialize(source_reader, options = nil)
|
24
35
|
@options = options || {}
|
25
|
-
@
|
26
|
-
@
|
27
|
-
@
|
28
|
-
|
29
|
-
@
|
30
|
-
|
31
|
-
backend: :mock,
|
32
|
-
test_collector: @options.delete(:test_collector),
|
33
|
-
)
|
34
|
-
|
35
|
-
# we're checking a profile, we don't care if it runs on the host machine
|
36
|
-
@options[:ignore_supports] = true
|
37
|
-
tests, libs, metadata = @runner.add_tests([@path], @options)
|
38
|
-
@content = tests + libs + metadata
|
39
|
-
|
40
|
-
# NB if you want to check more than one profile, use one
|
41
|
-
# Inspec::Profile#from_file per profile
|
42
|
-
@metadata_source = metadata.first
|
43
|
-
@metadata = Metadata.from_ref(@metadata_source[:ref], @metadata_source[:content], @profile_id, @logger)
|
44
|
-
@params = @metadata.params
|
45
|
-
@profile_id ||= params[:name]
|
46
|
-
@params[:name] = @profile_id
|
47
|
-
@params[:rules] = rules = {}
|
36
|
+
@target = @options.delete(:target)
|
37
|
+
@logger = @options[:logger] || Logger.new(nil)
|
38
|
+
@source_reader = source_reader
|
39
|
+
@profile_id = @options[:id]
|
40
|
+
Metadata.finalize(@source_reader.metadata, @profile_id)
|
41
|
+
end
|
48
42
|
|
49
|
-
|
50
|
-
|
51
|
-
rules[file] ||= {}
|
52
|
-
rules[file][id] = {
|
53
|
-
title: rule.title,
|
54
|
-
desc: rule.desc,
|
55
|
-
impact: rule.impact,
|
56
|
-
checks: rule.instance_variable_get(:@checks),
|
57
|
-
code: rule.instance_variable_get(:@__code),
|
58
|
-
source_location: rule.instance_variable_get(:@__source_location),
|
59
|
-
group_title: rule.instance_variable_get(:@__group_title),
|
60
|
-
}
|
61
|
-
end
|
43
|
+
def params
|
44
|
+
@params ||= load_params
|
62
45
|
end
|
63
46
|
|
64
47
|
def info
|
65
|
-
res =
|
48
|
+
res = params.dup
|
66
49
|
rules = {}
|
67
50
|
res[:rules].each do |gid, group|
|
68
51
|
next if gid.to_s.empty?
|
69
|
-
|
70
|
-
rules[path] = { title: path, rules: {} }
|
52
|
+
rules[gid] = { title: gid, rules: {} }
|
71
53
|
group.each do |id, rule|
|
72
54
|
next if id.to_s.empty?
|
73
55
|
data = rule.dup
|
@@ -75,10 +57,10 @@ module Inspec
|
|
75
57
|
data[:impact] ||= 0.5
|
76
58
|
data[:impact] = 1.0 if data[:impact] > 1.0
|
77
59
|
data[:impact] = 0.0 if data[:impact] < 0.0
|
78
|
-
rules[
|
60
|
+
rules[gid][:rules][id] = data
|
79
61
|
# TODO: temporarily flatten the group down; replace this with
|
80
62
|
# proper hierarchy later on
|
81
|
-
rules[
|
63
|
+
rules[gid][:title] = data[:group_title]
|
82
64
|
end
|
83
65
|
end
|
84
66
|
res[:rules] = rules
|
@@ -95,7 +77,7 @@ module Inspec
|
|
95
77
|
summary: {
|
96
78
|
valid: false,
|
97
79
|
timestamp: Time.now.iso8601,
|
98
|
-
location: @
|
80
|
+
location: @target,
|
99
81
|
profile: nil,
|
100
82
|
controls: 0,
|
101
83
|
},
|
@@ -123,27 +105,27 @@ module Inspec
|
|
123
105
|
result[:errors].push(entry.call(file, line, column, control, msg))
|
124
106
|
}
|
125
107
|
|
126
|
-
@logger.info "Checking profile in #{@
|
127
|
-
|
128
|
-
if
|
129
|
-
warn.call(
|
108
|
+
@logger.info "Checking profile in #{@target}"
|
109
|
+
meta_path = @source_reader.target.abs_path(@source_reader.metadata.ref)
|
110
|
+
if meta_path =~ /metadata\.rb$/
|
111
|
+
warn.call(@target, 0, 0, nil, 'The use of `metadata.rb` is deprecated. Use `inspec.yml`.')
|
130
112
|
end
|
131
113
|
|
132
114
|
# verify metadata
|
133
|
-
m_errors, m_warnings =
|
134
|
-
m_errors.each { |msg| error.call(
|
135
|
-
m_warnings.each { |msg| warn.call(
|
136
|
-
m_unsupported =
|
137
|
-
m_unsupported.each { |u| warn.call(
|
115
|
+
m_errors, m_warnings = metadata.valid
|
116
|
+
m_errors.each { |msg| error.call(meta_path, 0, 0, nil, msg) }
|
117
|
+
m_warnings.each { |msg| warn.call(meta_path, 0, 0, nil, msg) }
|
118
|
+
m_unsupported = metadata.unsupported
|
119
|
+
m_unsupported.each { |u| warn.call(meta_path, 0, 0, nil, "doesn't support: #{u}") }
|
138
120
|
@logger.info 'Metadata OK.' if m_errors.empty? && m_unsupported.empty?
|
139
121
|
|
140
122
|
# extract profile name
|
141
|
-
result[:summary][:profile] =
|
123
|
+
result[:summary][:profile] = metadata.params[:name]
|
142
124
|
|
143
125
|
# check if the profile is using the old test directory instead of the
|
144
126
|
# new controls directory
|
145
|
-
if @
|
146
|
-
warn.call(
|
127
|
+
if @source_reader.tests.keys.any? { |x| x =~ %r{^test/$} }
|
128
|
+
warn.call(@target, 0, 0, nil, 'Profile uses deprecated `test` directory, rename it to `controls`.')
|
147
129
|
end
|
148
130
|
|
149
131
|
count = rules_count
|
@@ -155,7 +137,7 @@ module Inspec
|
|
155
137
|
end
|
156
138
|
|
157
139
|
# iterate over hash of groups
|
158
|
-
|
140
|
+
params[:rules].each { |group, controls|
|
159
141
|
@logger.info "Verify all controls in #{group}"
|
160
142
|
controls.each { |id, control|
|
161
143
|
sfile, sline = control[:source_location]
|
@@ -177,21 +159,20 @@ module Inspec
|
|
177
159
|
end
|
178
160
|
|
179
161
|
def rules_count
|
180
|
-
|
162
|
+
params[:rules].values.map { |hm| hm.values.length }.inject(:+) || 0
|
181
163
|
end
|
182
164
|
|
183
165
|
# generates a archive of a folder profile
|
184
166
|
# assumes that the profile was checked before
|
185
167
|
def archive(opts) # rubocop:disable Metrics/AbcSize
|
186
|
-
profile_name =
|
187
|
-
|
168
|
+
profile_name = params[:name]
|
188
169
|
ext = opts[:zip] ? 'zip' : 'tar.gz'
|
189
170
|
|
190
171
|
if opts[:archive]
|
191
172
|
archive = Pathname.new(opts[:archive])
|
192
173
|
else
|
193
174
|
slug = profile_name.downcase.strip.tr(' ', '-').gsub(/[^\w-]/, '_')
|
194
|
-
archive = Pathname.new(
|
175
|
+
archive = Pathname.new(Dir.pwd).join("#{slug}.#{ext}")
|
195
176
|
end
|
196
177
|
|
197
178
|
# check if file exists otherwise overwrite the archive
|
@@ -202,38 +183,68 @@ module Inspec
|
|
202
183
|
|
203
184
|
# remove existing archive
|
204
185
|
File.delete(archive) if archive.exist?
|
205
|
-
|
206
186
|
@logger.info "Generate archive #{archive}."
|
207
187
|
|
208
|
-
# find all files
|
209
|
-
files = Dir.glob("#{path}/**/*")
|
210
|
-
|
211
188
|
# filter files that should not be part of the profile
|
212
189
|
# TODO ignore all .files, but add the files to debug output
|
213
190
|
|
214
|
-
# map absolute paths to relative paths
|
215
|
-
files = files.collect { |f| Pathname.new(f).relative_path_from(Pathname.new(path)).to_s }
|
216
|
-
|
217
191
|
# display all files that will be part of the archive
|
218
192
|
@logger.debug 'Add the following files to archive:'
|
219
|
-
|
220
|
-
|
221
|
-
}
|
193
|
+
root_path = @source_reader.target.prefix
|
194
|
+
files = @source_reader.target.files
|
195
|
+
files.each { |f| @logger.debug ' ' + f }
|
222
196
|
|
223
197
|
if opts[:zip]
|
224
198
|
# generate zip archive
|
225
199
|
require 'inspec/archive/zip'
|
226
200
|
zag = Inspec::Archive::ZipArchiveGenerator.new
|
227
|
-
zag.archive(
|
201
|
+
zag.archive(root_path, files, archive)
|
228
202
|
else
|
229
203
|
# generate tar archive
|
230
204
|
require 'inspec/archive/tar'
|
231
205
|
tag = Inspec::Archive::TarArchiveGenerator.new
|
232
|
-
tag.archive(
|
206
|
+
tag.archive(root_path, files, archive)
|
233
207
|
end
|
234
208
|
|
235
209
|
@logger.info 'Finished archive generation.'
|
236
210
|
true
|
237
211
|
end
|
212
|
+
|
213
|
+
private
|
214
|
+
|
215
|
+
def load_params
|
216
|
+
params = @source_reader.metadata.params
|
217
|
+
params[:name] = @profile_id unless @profile_id.nil?
|
218
|
+
params[:rules] = rules = {}
|
219
|
+
prefix = @source_reader.target.prefix || ''
|
220
|
+
|
221
|
+
# we're checking a profile, we don't care if it runs on the host machine
|
222
|
+
opts = @options.dup
|
223
|
+
opts[:ignore_supports] = true
|
224
|
+
runner = Runner.new(
|
225
|
+
id: @profile_id,
|
226
|
+
backend: :mock,
|
227
|
+
test_collector: opts.delete(:test_collector),
|
228
|
+
)
|
229
|
+
runner.add_profile(self, opts)
|
230
|
+
|
231
|
+
runner.rules.each do |id, rule|
|
232
|
+
file = rule.instance_variable_get(:@__file)
|
233
|
+
file = file[prefix.length..-1] if file.start_with?(prefix)
|
234
|
+
rules[file] ||= {}
|
235
|
+
rules[file][id] = {
|
236
|
+
title: rule.title,
|
237
|
+
desc: rule.desc,
|
238
|
+
impact: rule.impact,
|
239
|
+
checks: rule.instance_variable_get(:@checks),
|
240
|
+
code: rule.instance_variable_get(:@__code),
|
241
|
+
source_location: rule.instance_variable_get(:@__source_location),
|
242
|
+
group_title: rule.instance_variable_get(:@__group_title),
|
243
|
+
}
|
244
|
+
end
|
245
|
+
|
246
|
+
@profile_id ||= params[:name]
|
247
|
+
params
|
248
|
+
end
|
238
249
|
end
|
239
250
|
end
|
data/lib/inspec/resource.rb
CHANGED
data/lib/inspec/runner.rb
CHANGED
@@ -8,12 +8,12 @@ require 'forwardable'
|
|
8
8
|
require 'uri'
|
9
9
|
require 'inspec/backend'
|
10
10
|
require 'inspec/profile_context'
|
11
|
-
require 'inspec/
|
11
|
+
require 'inspec/profile'
|
12
12
|
require 'inspec/metadata'
|
13
13
|
# spec requirements
|
14
14
|
|
15
15
|
module Inspec
|
16
|
-
class Runner
|
16
|
+
class Runner
|
17
17
|
extend Forwardable
|
18
18
|
attr_reader :backend, :rules
|
19
19
|
def initialize(conf = {})
|
@@ -46,45 +46,25 @@ module Inspec
|
|
46
46
|
@backend = Inspec::Backend.create(@conf)
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
metas = meta_assets.map do |x|
|
53
|
-
Inspec::Metadata.from_ref(x[:ref], x[:content], @profile_id, @conf[:logger])
|
54
|
-
end
|
55
|
-
metas.each do |meta|
|
56
|
-
return [] unless ignore_supports || meta.supports_transport?(@backend)
|
57
|
-
end
|
58
|
-
assets
|
59
|
-
end
|
49
|
+
def add_profile(profile, options = {})
|
50
|
+
return unless options[:ignore_supports] ||
|
51
|
+
profile.metadata.supports_transport?(@backend)
|
60
52
|
|
61
|
-
|
62
|
-
|
63
|
-
items = tests.map do |test|
|
64
|
-
add_test_profile(test, options[:ignore_supports])
|
65
|
-
end.flatten
|
66
|
-
|
67
|
-
tests = items.find_all { |i| i[:type] == :test }
|
68
|
-
libs = items.find_all { |i| i[:type] == :library }
|
69
|
-
meta = items.find_all { |i| i[:type] == :metadata }
|
70
|
-
|
71
|
-
# Ensure each test directory exists on the $LOAD_PATH. This
|
72
|
-
# will ensure traditional RSpec-isms like `require 'spec_helper'`
|
73
|
-
# continue to work.
|
74
|
-
tests.flatten.each do |test|
|
75
|
-
# do not load path for virtual files, eg. from zip
|
76
|
-
if !test[:ref].nil?
|
77
|
-
test_directory = File.dirname(test[:ref])
|
78
|
-
$LOAD_PATH.unshift test_directory unless $LOAD_PATH.include?(test_directory)
|
79
|
-
end
|
53
|
+
libs = profile.libraries.map do |k, v|
|
54
|
+
{ ref: k, content: v }
|
80
55
|
end
|
81
56
|
|
82
|
-
|
83
|
-
|
57
|
+
profile.tests.each do |ref, content|
|
58
|
+
r = profile.source_reader.target.abs_path(ref)
|
59
|
+
test = { ref: r, content: content }
|
84
60
|
add_content(test, libs)
|
85
61
|
end
|
62
|
+
end
|
86
63
|
|
87
|
-
|
64
|
+
def add_target(target, options = {})
|
65
|
+
profile = Inspec::Profile.for_target(target, options)
|
66
|
+
fail "Could not resolve #{target} to valid input." if profile.nil?
|
67
|
+
add_profile(profile)
|
88
68
|
end
|
89
69
|
|
90
70
|
def create_context
|