inspec 0.25.0 → 0.26.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 +25 -2
- data/inspec.gemspec +1 -1
- data/lib/inspec/cli.rb +2 -1
- data/lib/inspec/rspec_json_formatter.rb +249 -10
- data/lib/inspec/runner.rb +1 -0
- data/lib/inspec/runner_mock.rb +1 -0
- data/lib/inspec/runner_rspec.rb +14 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +1 -1
- data/lib/utils/base_cli.rb +1 -1
- data/test/functional/inspec_exec_jsonmin_test.rb +59 -0
- data/test/functional/inspec_exec_test.rb +54 -48
- data/test/integration/default/compare_matcher_spec.rb +5 -0
- data/test/unit/mock/profiles/spec_only/specfile.rb +11 -0
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24a4519c426bef0955b532d458a7436c172ee78e
|
4
|
+
data.tar.gz: 94fa93e202174527e9d40cbf1f174cc37a879492
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afa1eeb884e110fd29387f621aa29ff8a90f428257a96f657fba4001520bb893e23af8f94d583cb73579c9eb6a4f95986a4df842f81aea5513fd7eb7c450a944
|
7
|
+
data.tar.gz: 7cb77d205bdf7ebadae0b376aefb35d03ee1ab444b8d95a30f8042eb5ab139bc2f6112d2557ded9bdbfbff07cb68998bf86b7d8884d4b15554b64f6dd827a925
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,30 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.
|
4
|
-
[Full Changelog](https://github.com/chef/inspec/compare/v0.
|
3
|
+
## [0.26.0](https://github.com/chef/inspec/tree/0.26.0) (2016-06-16)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.25.0...0.26.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- use train instead of r-train [\#795](https://github.com/chef/inspec/pull/795) ([chris-rock](https://github.com/chris-rock))
|
9
|
+
|
10
|
+
**Fixed bugs:**
|
11
|
+
|
12
|
+
- Transport error while trying to ssh to mac osx [\#788](https://github.com/chef/inspec/issues/788)
|
13
|
+
|
14
|
+
**Closed issues:**
|
15
|
+
|
16
|
+
- Can't upload inherited profile [\#789](https://github.com/chef/inspec/issues/789)
|
17
|
+
|
18
|
+
**Merged pull requests:**
|
19
|
+
|
20
|
+
- provide target info in cli output [\#796](https://github.com/chef/inspec/pull/796) ([arlimus](https://github.com/arlimus))
|
21
|
+
- multi-profile reporting in cli formatter [\#794](https://github.com/chef/inspec/pull/794) ([arlimus](https://github.com/arlimus))
|
22
|
+
- use utf-8 characters for default cli formatter [\#792](https://github.com/chef/inspec/pull/792) ([arlimus](https://github.com/arlimus))
|
23
|
+
- integer?\("0300"\) should not be true [\#791](https://github.com/chef/inspec/pull/791) ([srenatus](https://github.com/srenatus))
|
24
|
+
- introduce cli report formatter [\#790](https://github.com/chef/inspec/pull/790) ([arlimus](https://github.com/arlimus))
|
25
|
+
|
26
|
+
## [v0.25.0](https://github.com/chef/inspec/tree/v0.25.0) (2016-06-14)
|
27
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.24.0...v0.25.0)
|
5
28
|
|
6
29
|
**Closed issues:**
|
7
30
|
|
data/inspec.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
25
25
|
spec.require_paths = ['lib']
|
26
26
|
|
27
|
-
spec.add_dependency '
|
27
|
+
spec.add_dependency 'train', '~> 0.13'
|
28
28
|
spec.add_dependency 'thor', '~> 0.19'
|
29
29
|
spec.add_dependency 'json', '~> 1.8'
|
30
30
|
spec.add_dependency 'rainbow', '~> 2'
|
data/lib/inspec/cli.rb
CHANGED
@@ -9,6 +9,7 @@ require 'json'
|
|
9
9
|
require 'pp'
|
10
10
|
require 'utils/base_cli'
|
11
11
|
require 'utils/json_log'
|
12
|
+
require 'inspec/runner_mock'
|
12
13
|
|
13
14
|
class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
14
15
|
class_option :diagnose, type: :boolean,
|
@@ -160,7 +161,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
160
161
|
private
|
161
162
|
|
162
163
|
def run_command(opts)
|
163
|
-
opts[:test_collector] =
|
164
|
+
opts[:test_collector] = Inspec::RunnerMock.new
|
164
165
|
runner = Inspec::Runner.new(opts)
|
165
166
|
runner.create_context.load(opts[:command])
|
166
167
|
end
|
@@ -73,19 +73,19 @@ end
|
|
73
73
|
|
74
74
|
class InspecRspecJson < InspecRspecMiniJson
|
75
75
|
RSpec::Core::Formatters.register self, :message, :dump_summary, :dump_profile, :stop, :close
|
76
|
+
attr_writer :backend
|
77
|
+
|
78
|
+
def initialize(*args)
|
79
|
+
super(*args)
|
80
|
+
@profiles = []
|
81
|
+
@backend = nil
|
82
|
+
end
|
76
83
|
|
77
84
|
def add_profile(profile)
|
78
|
-
@profiles ||= []
|
79
85
|
@profiles.push(profile)
|
80
86
|
end
|
81
87
|
|
82
|
-
def dump_one_example(example,
|
83
|
-
profile = profiles[example[:profile_id]]
|
84
|
-
return missing.push(example) if profile.nil? || profile[:controls].nil?
|
85
|
-
|
86
|
-
control = profile[:controls][example[:id]]
|
87
|
-
return missing.push(example) if control.nil?
|
88
|
-
|
88
|
+
def dump_one_example(example, control)
|
89
89
|
control[:results] ||= []
|
90
90
|
example.delete(:id)
|
91
91
|
example.delete(:profile_id)
|
@@ -99,13 +99,14 @@ class InspecRspecJson < InspecRspecMiniJson
|
|
99
99
|
|
100
100
|
def dump_summary(summary)
|
101
101
|
super(summary)
|
102
|
-
@profiles ||= []
|
103
102
|
examples = @output_hash.delete(:controls)
|
104
103
|
profiles = Hash[@profiles.map { |x| profile_info(x) }]
|
105
104
|
missing = []
|
106
105
|
|
107
106
|
examples.each do |example|
|
108
|
-
|
107
|
+
control = example2control(example, profiles)
|
108
|
+
next missing.push(example) if control.nil?
|
109
|
+
dump_one_example(example, control)
|
109
110
|
end
|
110
111
|
|
111
112
|
@output_hash[:profiles] = profiles
|
@@ -114,6 +115,12 @@ class InspecRspecJson < InspecRspecMiniJson
|
|
114
115
|
|
115
116
|
private
|
116
117
|
|
118
|
+
def example2control(example, profiles)
|
119
|
+
profile = profiles[example[:profile_id]]
|
120
|
+
return nil if profile.nil? || profile[:controls].nil?
|
121
|
+
profile[:controls][example[:id]]
|
122
|
+
end
|
123
|
+
|
117
124
|
def format_example(example)
|
118
125
|
super(example).tap do |res|
|
119
126
|
res[:run_time] = example.execution_result.run_time
|
@@ -121,3 +128,235 @@ class InspecRspecJson < InspecRspecMiniJson
|
|
121
128
|
end
|
122
129
|
end
|
123
130
|
end
|
131
|
+
|
132
|
+
class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
133
|
+
RSpec::Core::Formatters.register self, :message, :dump_summary, :dump_profile, :stop, :close
|
134
|
+
|
135
|
+
STATUS_TYPES = {
|
136
|
+
'unknown' => -3,
|
137
|
+
'passed' => -2,
|
138
|
+
'skipped' => -1,
|
139
|
+
'minor' => 1,
|
140
|
+
'major' => 2,
|
141
|
+
'failed' => 2.5,
|
142
|
+
'critical' => 3,
|
143
|
+
}.freeze
|
144
|
+
|
145
|
+
COLORS = {
|
146
|
+
'critical' => "\033[31;1m",
|
147
|
+
'major' => "\033[31m",
|
148
|
+
'minor' => "\033[33m",
|
149
|
+
'failed' => "\033[31m",
|
150
|
+
'passed' => "\033[32m",
|
151
|
+
'skipped' => "\033[37m",
|
152
|
+
'reset' => "\033[0m",
|
153
|
+
}.freeze
|
154
|
+
|
155
|
+
INDICATORS = {
|
156
|
+
'critical' => ' ✖ ',
|
157
|
+
'major' => ' ✖ ',
|
158
|
+
'minor' => ' ✖ ',
|
159
|
+
'failed' => ' ✖ ',
|
160
|
+
'skipped' => ' ○ ',
|
161
|
+
'passed' => ' ✔ ',
|
162
|
+
'unknown' => ' ? ',
|
163
|
+
'empty' => ' ',
|
164
|
+
}.freeze
|
165
|
+
|
166
|
+
TEST_INDICATORS = {
|
167
|
+
'failed' => ' fail: ',
|
168
|
+
'skipped' => ' skip: ',
|
169
|
+
'empty' => ' ',
|
170
|
+
}.freeze
|
171
|
+
|
172
|
+
def initialize(*args)
|
173
|
+
@colors = COLORS
|
174
|
+
@indicators = INDICATORS
|
175
|
+
@test_indicators = TEST_INDICATORS
|
176
|
+
|
177
|
+
@format = '%color%indicator%id%summary'
|
178
|
+
@current_control = nil
|
179
|
+
@current_profile = nil
|
180
|
+
@missing_controls = []
|
181
|
+
super(*args)
|
182
|
+
end
|
183
|
+
|
184
|
+
def start(_notification)
|
185
|
+
@profiles_info ||= Hash[@profiles.map { |x| profile_info(x) }]
|
186
|
+
end
|
187
|
+
|
188
|
+
def close(_notification)
|
189
|
+
flush_current_control
|
190
|
+
output.puts('') unless @current_control.nil?
|
191
|
+
|
192
|
+
@profiles_info.each do |_id, profile|
|
193
|
+
next if profile[:already_printed]
|
194
|
+
@current_profile = profile
|
195
|
+
next unless print_current_profile
|
196
|
+
print_line(
|
197
|
+
color: '', indicator: @indicators['empty'], id: '', profile: '',
|
198
|
+
summary: 'No tests executed.'
|
199
|
+
)
|
200
|
+
output.puts('')
|
201
|
+
end
|
202
|
+
|
203
|
+
res = @output_hash[:summary]
|
204
|
+
passed = res[:example_count] - res[:failure_count] - res[:skip_count]
|
205
|
+
s = format('Summary: %3d successful %3d failures %3d skipped',
|
206
|
+
passed, res[:failure_count], res[:skip_count])
|
207
|
+
output.puts(s)
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
|
212
|
+
def status_type(data, control)
|
213
|
+
status = data[:status]
|
214
|
+
return status if status != 'failed' || control[:impact].nil?
|
215
|
+
if control[:impact] > 0.7
|
216
|
+
'critical'
|
217
|
+
elsif control[:impact] > 0.4
|
218
|
+
'major'
|
219
|
+
elsif control[:impact] > 0.0
|
220
|
+
'minor'
|
221
|
+
else
|
222
|
+
'failed'
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def current_control_infos
|
227
|
+
summary_status = STATUS_TYPES['unknown']
|
228
|
+
skips = []
|
229
|
+
fails = []
|
230
|
+
@current_control[:results].each do |r|
|
231
|
+
i = STATUS_TYPES[r[:status_type]]
|
232
|
+
summary_status = i if i > summary_status
|
233
|
+
fails.push(r) if i > 0
|
234
|
+
skips.push(r) if i == STATUS_TYPES['skipped']
|
235
|
+
end
|
236
|
+
[fails, skips, STATUS_TYPES.key(summary_status)]
|
237
|
+
end
|
238
|
+
|
239
|
+
def current_control_summary(fails, skips)
|
240
|
+
sum_info = [
|
241
|
+
(fails.length > 0) ? "#{fails.length} failed" : nil,
|
242
|
+
(skips.length > 0) ? "#{skips.length} skipped" : nil,
|
243
|
+
].compact
|
244
|
+
|
245
|
+
summary = @current_control[:title]
|
246
|
+
unless summary.nil?
|
247
|
+
return summary + ' (' + sum_info.join(' ') + ')' unless sum_info.empty?
|
248
|
+
return summary
|
249
|
+
end
|
250
|
+
|
251
|
+
return sum_info.join(' ') if @current_control[:results].length != 1
|
252
|
+
|
253
|
+
fails.clear
|
254
|
+
skips.clear
|
255
|
+
c = @current_control[:results][0]
|
256
|
+
c[:code_desc].to_s + c[:message].to_s
|
257
|
+
end
|
258
|
+
|
259
|
+
def format_line(fields)
|
260
|
+
@format.gsub(/%\w+/) do |x|
|
261
|
+
term = x[1..-1]
|
262
|
+
fields.key?(term.to_sym) ? fields[term.to_sym].to_s : x
|
263
|
+
end + @colors['reset']
|
264
|
+
end
|
265
|
+
|
266
|
+
def print_line(fields)
|
267
|
+
output.puts(format_line(fields))
|
268
|
+
end
|
269
|
+
|
270
|
+
def format_lines(lines, indentation)
|
271
|
+
lines.gsub(/\n/, "\n" + indentation)
|
272
|
+
end
|
273
|
+
|
274
|
+
def print_fails_and_skips(all, color)
|
275
|
+
all.each do |x|
|
276
|
+
indicator = @test_indicators[x[:status]]
|
277
|
+
indicator = @test_indicators['empty'] if all.length == 1 || indicator.nil?
|
278
|
+
msg = x[:message] || x[:skip_message] || x[:code_desc]
|
279
|
+
print_line(
|
280
|
+
color: color,
|
281
|
+
indicator: indicator,
|
282
|
+
summary: format_lines(msg, @test_indicators['empty']),
|
283
|
+
id: nil, profile: nil
|
284
|
+
)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def flush_current_control
|
289
|
+
return if @current_control.nil?
|
290
|
+
|
291
|
+
prev_profile = @current_profile
|
292
|
+
@current_profile = @profiles_info[@current_control[:profile_id]]
|
293
|
+
print_current_profile if prev_profile != @current_profile
|
294
|
+
|
295
|
+
fails, skips, summary_indicator = current_control_infos
|
296
|
+
summary = current_control_summary(fails, skips)
|
297
|
+
|
298
|
+
control_id = @current_control[:id].to_s
|
299
|
+
control_id += ': '
|
300
|
+
control_id = '' if control_id.start_with? '(generated from '
|
301
|
+
|
302
|
+
print_line(
|
303
|
+
color: @colors[summary_indicator] || '',
|
304
|
+
indicator: @indicators[summary_indicator] || @indicators['unknown'],
|
305
|
+
summary: format_lines(summary, @indicators['empty']),
|
306
|
+
id: control_id,
|
307
|
+
profile: @current_control[:profile_id],
|
308
|
+
)
|
309
|
+
|
310
|
+
print_fails_and_skips(fails + skips, @colors[summary_indicator] || '')
|
311
|
+
end
|
312
|
+
|
313
|
+
def print_target(before, after)
|
314
|
+
return if @backend.nil?
|
315
|
+
connection = @backend.backend
|
316
|
+
return unless connection.respond_to?(:uri)
|
317
|
+
output.puts(before + connection.uri + after)
|
318
|
+
end
|
319
|
+
|
320
|
+
def print_current_profile
|
321
|
+
profile = @current_profile
|
322
|
+
return false if profile.nil?
|
323
|
+
|
324
|
+
output.puts ''
|
325
|
+
profile[:already_printed] = true
|
326
|
+
if profile[:name].nil?
|
327
|
+
print_target('Target: ', "\n\n")
|
328
|
+
return true
|
329
|
+
end
|
330
|
+
|
331
|
+
if profile[:title].nil?
|
332
|
+
output.puts "Profile: #{profile[:name] || 'unknown'}"
|
333
|
+
else
|
334
|
+
output.puts "Profile: #{profile[:title]} (#{profile[:name] || 'unknown'})"
|
335
|
+
end
|
336
|
+
|
337
|
+
output.puts 'Version: ' + (profile[:version] || 'unknown')
|
338
|
+
print_target('Target: ', "\n")
|
339
|
+
output.puts
|
340
|
+
true
|
341
|
+
end
|
342
|
+
|
343
|
+
def format_example(example)
|
344
|
+
data = super(example)
|
345
|
+
control = example2control(data, @profiles_info) || {}
|
346
|
+
control[:id] = data[:id]
|
347
|
+
control[:profile_id] = data[:profile_id]
|
348
|
+
|
349
|
+
data[:status_type] = status_type(data, control)
|
350
|
+
dump_one_example(data, control)
|
351
|
+
|
352
|
+
@current_control ||= control
|
353
|
+
if control[:id].nil?
|
354
|
+
@missing_controls.push(data)
|
355
|
+
elsif @current_control[:id] != control[:id]
|
356
|
+
flush_current_control
|
357
|
+
@current_control = control
|
358
|
+
end
|
359
|
+
|
360
|
+
data
|
361
|
+
end
|
362
|
+
end
|
data/lib/inspec/runner.rb
CHANGED
data/lib/inspec/runner_mock.rb
CHANGED
data/lib/inspec/runner_rspec.rb
CHANGED
@@ -40,6 +40,18 @@ module Inspec
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
# Configure the backend of the runner.
|
44
|
+
#
|
45
|
+
# @param [Inspec::Backend] backend
|
46
|
+
# @return [nil]
|
47
|
+
def backend=(backend)
|
48
|
+
RSpec.configuration.formatters
|
49
|
+
.find_all { |c| c.is_a? InspecRspecJson }
|
50
|
+
.each do |fmt|
|
51
|
+
fmt.backend = backend
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
43
55
|
# Add an example group to the list of registered tests.
|
44
56
|
#
|
45
57
|
# @param [RSpecExampleGroup] example test
|
@@ -90,6 +102,7 @@ module Inspec
|
|
90
102
|
'json-min' => 'InspecRspecMiniJson',
|
91
103
|
'json' => 'InspecRspecJson',
|
92
104
|
'json-rspec' => 'InspecRspecVanilla',
|
105
|
+
'cli' => 'InspecRspecCli',
|
93
106
|
}.freeze
|
94
107
|
|
95
108
|
# Configure the output formatter and stream to be used with RSpec.
|
@@ -102,7 +115,7 @@ module Inspec
|
|
102
115
|
RSpec.configuration.output_stream = @conf['output']
|
103
116
|
end
|
104
117
|
|
105
|
-
format = FORMATTERS[@conf['format']] || @conf['format'] || '
|
118
|
+
format = FORMATTERS[@conf['format']] || @conf['format'] || FORMATTERS['cli']
|
106
119
|
@formatter = RSpec.configuration.add_formatter(format)
|
107
120
|
RSpec.configuration.color = @conf['color']
|
108
121
|
|
data/lib/inspec/version.rb
CHANGED
data/lib/matchers/matchers.rb
CHANGED
data/lib/utils/base_cli.rb
CHANGED
@@ -52,7 +52,7 @@ module Inspec
|
|
52
52
|
option :controls, type: :array,
|
53
53
|
desc: 'A list of controls to run. Ignore all other tests.'
|
54
54
|
option :format, type: :string,
|
55
|
-
desc: 'Which formatter to use: progress, documentation, json'
|
55
|
+
desc: 'Which formatter to use: cli, progress, documentation, json, json-min'
|
56
56
|
option :color, type: :boolean, default: true,
|
57
57
|
desc: 'Use colors in output.'
|
58
58
|
option :attrs, type: :array,
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Dominik Richter
|
3
|
+
# author: Christoph Hartmann
|
4
|
+
|
5
|
+
require 'functional/helper'
|
6
|
+
|
7
|
+
describe 'inspec exec' do
|
8
|
+
include FunctionalHelper
|
9
|
+
|
10
|
+
it 'can execute the profile with the mini json formatter' do
|
11
|
+
out = inspec('exec ' + example_profile + ' --format json-min')
|
12
|
+
out.stderr.must_equal ''
|
13
|
+
out.exit_status.must_equal 0
|
14
|
+
JSON.load(out.stdout).must_be_kind_of Hash
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can execute a simple file with the mini json formatter' do
|
18
|
+
out = inspec('exec ' + example_control + ' --format json-min')
|
19
|
+
out.stderr.must_equal ''
|
20
|
+
out.exit_status.must_equal 0
|
21
|
+
JSON.load(out.stdout).must_be_kind_of Hash
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'execute a profile with mini json formatting' do
|
25
|
+
let(:json) { JSON.load(inspec('exec ' + example_profile + ' --format json-min').stdout) }
|
26
|
+
let(:controls) { json['controls'] }
|
27
|
+
let(:ex1) { controls.find{|x| x['id'] == 'tmp-1.0'} }
|
28
|
+
let(:ex2) { controls.find{|x| x['id'] =~ /generated/} }
|
29
|
+
let(:ex3) { controls.find{|x| x['id'] == 'gordon-1.0'} }
|
30
|
+
|
31
|
+
it 'must have 5 examples' do
|
32
|
+
json['controls'].length.must_equal 5
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'has an id' do
|
36
|
+
controls.find { |ex| !ex.key? 'id' }.must_be :nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'has a profile_id' do
|
40
|
+
controls.find { |ex| !ex.key? 'profile_id' }.must_be :nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'has a code_desc' do
|
44
|
+
ex1['code_desc'].must_equal 'File /tmp should be directory'
|
45
|
+
controls.find { |ex| !ex.key? 'code_desc' }.must_be :nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'has a status' do
|
49
|
+
ex1['status'].must_equal 'passed'
|
50
|
+
ex3['status'].must_equal 'skipped'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'has a skip_message' do
|
54
|
+
ex1['skip_message'].must_be :nil?
|
55
|
+
ex3['skip_message'].must_equal "Can't find file \"/tmp/gordon/config.yaml\""
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -11,71 +11,77 @@ describe 'inspec exec' do
|
|
11
11
|
out = inspec('exec ' + example_profile)
|
12
12
|
out.stderr.must_equal ''
|
13
13
|
out.exit_status.must_equal 0
|
14
|
-
out.stdout.
|
15
|
-
|
14
|
+
stdout = out.stdout.force_encoding(Encoding::UTF_8)
|
15
|
+
stdout.must_include "\n\e[32m ✔ ssh-1: Allow only SSH Protocol 2\e[0m\n"
|
16
|
+
stdout.must_include "\n\e[32m ✔ tmp-1.0: Create /tmp directory\e[0m\n"
|
17
|
+
stdout.must_include "
|
18
|
+
\e[37m ○ gordon-1.0: Verify the version number of Gordon (1 skipped)\e[0m
|
19
|
+
\e[37m Can't find file \"/tmp/gordon/config.yaml\"\e[0m
|
20
|
+
"
|
21
|
+
stdout.must_include "\nSummary: 4 successful 0 failures 1 skipped\n"
|
16
22
|
end
|
17
23
|
|
18
|
-
it 'executes only
|
19
|
-
out = inspec('exec ' +
|
24
|
+
it 'executes a minimum metadata-only profile' do
|
25
|
+
out = inspec('exec ' + File.join(profile_path, 'simple-metadata'))
|
20
26
|
out.stderr.must_equal ''
|
21
27
|
out.exit_status.must_equal 0
|
22
|
-
out.stdout.
|
28
|
+
out.stdout.must_equal "
|
29
|
+
Profile: yumyum profile
|
30
|
+
Version: unknown
|
31
|
+
Target: local://
|
32
|
+
|
33
|
+
No tests executed.\e[0m
|
34
|
+
|
35
|
+
Summary: 0 successful 0 failures 0 skipped
|
36
|
+
"
|
23
37
|
end
|
24
38
|
|
25
|
-
it '
|
26
|
-
out = inspec('exec ' +
|
39
|
+
it 'executes a metadata-only profile' do
|
40
|
+
out = inspec('exec ' + File.join(profile_path, 'complete-metadata'))
|
27
41
|
out.stderr.must_equal ''
|
28
42
|
out.exit_status.must_equal 0
|
29
|
-
|
43
|
+
out.stdout.must_equal "
|
44
|
+
Profile: title (name)
|
45
|
+
Version: 1.2.3
|
46
|
+
Target: local://
|
47
|
+
|
48
|
+
No tests executed.\e[0m
|
49
|
+
|
50
|
+
Summary: 0 successful 0 failures 0 skipped
|
51
|
+
"
|
30
52
|
end
|
31
53
|
|
32
|
-
it '
|
33
|
-
out = inspec('exec ' +
|
54
|
+
it 'executes a specs-only profile' do
|
55
|
+
out = inspec('exec ' + File.join(profile_path, 'spec_only'))
|
34
56
|
out.stderr.must_equal ''
|
35
|
-
out.exit_status.must_equal
|
36
|
-
out.stdout.
|
57
|
+
out.exit_status.must_equal 1
|
58
|
+
out.stdout.force_encoding(Encoding::UTF_8).must_equal "
|
59
|
+
Target: local://
|
60
|
+
|
61
|
+
\e[32m ✔ working should eq \"working\"\e[0m
|
62
|
+
\e[37m ○ skippy This will be skipped intentionally.\e[0m
|
63
|
+
\e[31m ✖ failing should eq \"as intended\"
|
64
|
+
expected: \"as intended\"
|
65
|
+
got: \"failing\"
|
66
|
+
\n (compared using ==)
|
67
|
+
\e[0m
|
68
|
+
|
69
|
+
Summary: 1 successful 1 failures 1 skipped
|
70
|
+
"
|
37
71
|
end
|
38
72
|
|
39
|
-
it '
|
40
|
-
out = inspec('exec ' +
|
73
|
+
it 'executes only specified controls' do
|
74
|
+
out = inspec('exec ' + example_profile + ' --controls tmp-1.0')
|
41
75
|
out.stderr.must_equal ''
|
42
76
|
out.exit_status.must_equal 0
|
43
|
-
|
77
|
+
out.stdout.must_include "\nSummary: 1 successful 0 failures 0 skipped\n"
|
44
78
|
end
|
45
79
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
let(:ex3) { controls.find{|x| x['id'] == 'gordon-1.0'} }
|
52
|
-
|
53
|
-
it 'must have 5 examples' do
|
54
|
-
json['controls'].length.must_equal 5
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'has an id' do
|
58
|
-
controls.find { |ex| !ex.key? 'id' }.must_be :nil?
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'has a profile_id' do
|
62
|
-
controls.find { |ex| !ex.key? 'profile_id' }.must_be :nil?
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'has a code_desc' do
|
66
|
-
ex1['code_desc'].must_equal 'File /tmp should be directory'
|
67
|
-
controls.find { |ex| !ex.key? 'code_desc' }.must_be :nil?
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'has a status' do
|
71
|
-
ex1['status'].must_equal 'passed'
|
72
|
-
ex3['status'].must_equal 'skipped'
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'has a skip_message' do
|
76
|
-
ex1['skip_message'].must_be :nil?
|
77
|
-
ex3['skip_message'].must_equal "Can't find file \"/tmp/gordon/config.yaml\""
|
78
|
-
end
|
80
|
+
it 'can execute a simple file with the default formatter' do
|
81
|
+
out = inspec('exec ' + example_control)
|
82
|
+
out.stderr.must_equal ''
|
83
|
+
out.exit_status.must_equal 0
|
84
|
+
out.stdout.must_include 'Summary: 2 successful 0 failures 0 skipped'
|
79
85
|
end
|
80
86
|
|
81
87
|
describe 'with a profile that is not supported on this OS/platform' do
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.26.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: train
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.13'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.13'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thor
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -404,6 +404,7 @@ files:
|
|
404
404
|
- test/functional/inspec_archive_test.rb
|
405
405
|
- test/functional/inspec_compliance_test.rb
|
406
406
|
- test/functional/inspec_exec_json_test.rb
|
407
|
+
- test/functional/inspec_exec_jsonmin_test.rb
|
407
408
|
- test/functional/inspec_exec_test.rb
|
408
409
|
- test/functional/inspec_json_profile_test.rb
|
409
410
|
- test/functional/inspec_test.rb
|
@@ -567,6 +568,7 @@ files:
|
|
567
568
|
- test/unit/mock/profiles/simple-metadata/inspec.yml
|
568
569
|
- test/unit/mock/profiles/skippy-profile-os/controls/one.rb
|
569
570
|
- test/unit/mock/profiles/skippy-profile-os/inspec.yml
|
571
|
+
- test/unit/mock/profiles/spec_only/specfile.rb
|
570
572
|
- test/unit/mock/profiles/supported_inspec/inspec.yml
|
571
573
|
- test/unit/mock/profiles/unsupported_inspec/inspec.yml
|
572
574
|
- test/unit/objects_test.rb
|
@@ -686,6 +688,7 @@ test_files:
|
|
686
688
|
- test/functional/inspec_archive_test.rb
|
687
689
|
- test/functional/inspec_compliance_test.rb
|
688
690
|
- test/functional/inspec_exec_json_test.rb
|
691
|
+
- test/functional/inspec_exec_jsonmin_test.rb
|
689
692
|
- test/functional/inspec_exec_test.rb
|
690
693
|
- test/functional/inspec_json_profile_test.rb
|
691
694
|
- test/functional/inspec_test.rb
|
@@ -849,6 +852,7 @@ test_files:
|
|
849
852
|
- test/unit/mock/profiles/simple-metadata/inspec.yml
|
850
853
|
- test/unit/mock/profiles/skippy-profile-os/controls/one.rb
|
851
854
|
- test/unit/mock/profiles/skippy-profile-os/inspec.yml
|
855
|
+
- test/unit/mock/profiles/spec_only/specfile.rb
|
852
856
|
- test/unit/mock/profiles/supported_inspec/inspec.yml
|
853
857
|
- test/unit/mock/profiles/unsupported_inspec/inspec.yml
|
854
858
|
- test/unit/objects_test.rb
|