abide_dev_utils 0.9.7 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -1
- data/Gemfile.lock +82 -64
- data/Rakefile +28 -0
- data/abide_dev_utils.gemspec +3 -1
- data/lib/abide_dev_utils/cem/benchmark.rb +291 -0
- data/lib/abide_dev_utils/cem/coverage_report.rb +348 -0
- data/lib/abide_dev_utils/cem/generate/reference.rb +116 -0
- data/lib/abide_dev_utils/cem/generate.rb +10 -0
- data/lib/abide_dev_utils/cem/mapping/mapper.rb +155 -0
- data/lib/abide_dev_utils/cem.rb +74 -0
- data/lib/abide_dev_utils/cli/cem.rb +153 -0
- data/lib/abide_dev_utils/cli/jira.rb +1 -1
- data/lib/abide_dev_utils/cli/xccdf.rb +15 -1
- data/lib/abide_dev_utils/cli.rb +2 -0
- data/lib/abide_dev_utils/errors/cem.rb +22 -0
- data/lib/abide_dev_utils/errors/general.rb +8 -2
- data/lib/abide_dev_utils/errors/ppt.rb +4 -0
- data/lib/abide_dev_utils/errors.rb +6 -0
- data/lib/abide_dev_utils/files.rb +34 -0
- data/lib/abide_dev_utils/markdown.rb +104 -0
- data/lib/abide_dev_utils/ppt/facter_utils.rb +140 -0
- data/lib/abide_dev_utils/ppt/hiera.rb +297 -0
- data/lib/abide_dev_utils/ppt/puppet_module.rb +74 -0
- data/lib/abide_dev_utils/ppt.rb +3 -5
- data/lib/abide_dev_utils/validate.rb +14 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf/diff/benchmark/number_title.rb +270 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/profile.rb +104 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/property.rb +127 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/property_existence.rb +47 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark.rb +267 -0
- data/lib/abide_dev_utils/xccdf/diff/utils.rb +30 -0
- data/lib/abide_dev_utils/xccdf/diff.rb +233 -0
- data/lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb +118 -0
- data/lib/abide_dev_utils/xccdf/parser/objects/numbered_object.rb +104 -0
- data/lib/abide_dev_utils/xccdf/parser/objects.rb +741 -0
- data/lib/abide_dev_utils/xccdf/parser.rb +52 -0
- data/lib/abide_dev_utils/xccdf.rb +14 -124
- data/new_diff.rb +48 -0
- metadata +60 -9
- data/lib/abide_dev_utils/ppt/coverage.rb +0 -86
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'abide_dev_utils/files'
|
4
|
+
require 'abide_dev_utils/xccdf/parser/objects'
|
5
|
+
|
6
|
+
module AbideDevUtils
|
7
|
+
module XCCDF
|
8
|
+
# Contains methods and classes for parsing XCCDF files,
|
9
|
+
module Parser
|
10
|
+
def self.parse(file_path)
|
11
|
+
doc = AbideDevUtils::Files::Reader.read(file_path)
|
12
|
+
benchmark = AbideDevUtils::XCCDF::Parser::Objects::Benchmark.new(doc)
|
13
|
+
Linker.resolve_links(benchmark)
|
14
|
+
benchmark
|
15
|
+
end
|
16
|
+
|
17
|
+
# Links XCCDF objects by reference.
|
18
|
+
# Each link is resolved and then a bidirectional link is established
|
19
|
+
# between the two objects.
|
20
|
+
module Linker
|
21
|
+
def self.resolve_links(benchmark)
|
22
|
+
link_profile_rules(benchmark)
|
23
|
+
link_rule_values(benchmark)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.link_profile_rules(benchmark)
|
27
|
+
rules = benchmark.find_children_by_class(AbideDevUtils::XCCDF::Parser::Objects::Rule, recurse: true)
|
28
|
+
benchmark.profile.each do |profile|
|
29
|
+
profile.xccdf_select.each do |sel|
|
30
|
+
rules.select { |rule| rule.id == sel.idref }.each do |rule|
|
31
|
+
rule.add_link(profile)
|
32
|
+
profile.add_link(rule)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.link_rule_values(benchmark)
|
39
|
+
rules = benchmark.find_children_by_class(AbideDevUtils::XCCDF::Parser::Objects::Rule, recurse: true)
|
40
|
+
benchmark.value.each do |value|
|
41
|
+
rules.each do |rule|
|
42
|
+
unless rule.find_children_by_attribute_value('value-id', value.id, recurse: true).empty?
|
43
|
+
rule.add_link(value)
|
44
|
+
value.add_link(rule)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -34,21 +34,17 @@ module AbideDevUtils
|
|
34
34
|
|
35
35
|
# Diffs two xccdf files
|
36
36
|
def self.diff(file1, file2, opts)
|
37
|
+
require 'abide_dev_utils/xccdf/diff'
|
37
38
|
bm1 = Benchmark.new(file1)
|
38
39
|
bm2 = Benchmark.new(file2)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
profile_key = profile.nil? ? 'all_profiles' : profile
|
48
|
-
{
|
49
|
-
'benchmark' => bm1.diff_title_version(bm2),
|
50
|
-
profile_key => profile_diff
|
51
|
-
}
|
40
|
+
AbideDevUtils::XCCDF::Diff.diff_benchmarks(bm1, bm2, opts)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Use new-style diff
|
44
|
+
def self.new_style_diff(file1, file2, opts)
|
45
|
+
require 'abide_dev_utils/xccdf/diff/benchmark'
|
46
|
+
bm_diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(file1, file2, opts)
|
47
|
+
bm_diff.diff
|
52
48
|
end
|
53
49
|
|
54
50
|
# Common constants and methods included by nearly everything else
|
@@ -164,25 +160,6 @@ module AbideDevUtils
|
|
164
160
|
diff_properties.map { |x| send(x) } == other.diff_properties.map { |x| other.send(x) }
|
165
161
|
end
|
166
162
|
|
167
|
-
def default_diff_opts
|
168
|
-
{
|
169
|
-
similarity: 1,
|
170
|
-
strict: true,
|
171
|
-
strip: true,
|
172
|
-
array_path: true,
|
173
|
-
delimiter: '//',
|
174
|
-
use_lcs: false
|
175
|
-
}
|
176
|
-
end
|
177
|
-
|
178
|
-
def diff(other, **opts)
|
179
|
-
Hashdiff.diff(
|
180
|
-
to_h,
|
181
|
-
other.to_h,
|
182
|
-
default_diff_opts.merge(opts)
|
183
|
-
)
|
184
|
-
end
|
185
|
-
|
186
163
|
def abide_object?
|
187
164
|
true
|
188
165
|
end
|
@@ -231,9 +208,12 @@ module AbideDevUtils
|
|
231
208
|
profiles.select { |x| x.title == profile_title }.controls
|
232
209
|
end
|
233
210
|
|
234
|
-
def gen_map(dir: nil, type: '
|
211
|
+
def gen_map(dir: nil, type: 'cis', parent_key_prefix: '', version_output_dir: false, **_)
|
235
212
|
os, ver = facter_platform
|
236
|
-
|
213
|
+
output_path = [type, os, ver]
|
214
|
+
output_path.unshift(File.expand_path(dir)) if dir
|
215
|
+
output_path << version if version_output_dir
|
216
|
+
mapping_dir = File.expand_path(File.join(output_path))
|
237
217
|
parent_key_prefix = '' if parent_key_prefix.nil?
|
238
218
|
MAP_INDICES.each_with_object({}) do |idx, h|
|
239
219
|
map_file_path = "#{mapping_dir}/#{idx}.yaml"
|
@@ -257,33 +237,6 @@ module AbideDevUtils
|
|
257
237
|
}
|
258
238
|
end
|
259
239
|
|
260
|
-
def diff_title_version(other)
|
261
|
-
Hashdiff.diff(
|
262
|
-
to_h.reject { |k, _| k.to_s == 'profiles' },
|
263
|
-
other.to_h.reject { |k, _| k.to_s == 'profiles' },
|
264
|
-
default_diff_opts
|
265
|
-
)
|
266
|
-
end
|
267
|
-
|
268
|
-
def diff_profiles(other)
|
269
|
-
this_diff = {}
|
270
|
-
other_hash = other.to_h[:profiles]
|
271
|
-
to_h[:profiles].each do |name, data|
|
272
|
-
diff_h = Hashdiff.diff(data, other_hash[name], default_diff_opts).each_with_object({}) do |x, a|
|
273
|
-
val_to = x.length == 4 ? x[3] : nil
|
274
|
-
a_key = x[2].is_a?(Hash) ? x[2][:title] : x[2]
|
275
|
-
a[a_key] = [] unless a.key?(a_key)
|
276
|
-
a[a_key] << ChangeSet.new(change: x[0], key: x[1], value: x[2], value_to: val_to)
|
277
|
-
end
|
278
|
-
this_diff[name] = diff_h
|
279
|
-
end
|
280
|
-
this_diff
|
281
|
-
end
|
282
|
-
|
283
|
-
def diff_controls(other)
|
284
|
-
controls.diff(other.controls)
|
285
|
-
end
|
286
|
-
|
287
240
|
def map_indexed(index: 'title', framework: 'cis', key_prefix: '')
|
288
241
|
c_map = profiles.each_with_object({}) do |profile, obj|
|
289
242
|
obj[profile.level.downcase] = {} unless obj[profile.level.downcase].is_a?(Hash)
|
@@ -396,69 +349,6 @@ module AbideDevUtils
|
|
396
349
|
end
|
397
350
|
end
|
398
351
|
|
399
|
-
class ChangeSet
|
400
|
-
attr_reader :change, :key, :value, :value_to
|
401
|
-
|
402
|
-
def initialize(change:, key:, value:, value_to: nil)
|
403
|
-
validate_change(change)
|
404
|
-
@change = change
|
405
|
-
@key = key
|
406
|
-
@value = value
|
407
|
-
@value_to = value_to
|
408
|
-
end
|
409
|
-
|
410
|
-
def to_s
|
411
|
-
val_to_str = value_to.nil? ? ' ' : " to #{value_to} "
|
412
|
-
"#{change_string} value #{value}#{val_to_str}at #{key}"
|
413
|
-
end
|
414
|
-
|
415
|
-
def can_merge?(other)
|
416
|
-
return false unless (change == '-' && other.change == '+') || (change == '+' && other.change == '-')
|
417
|
-
return false unless key == other.key || value_hash_equality(other)
|
418
|
-
|
419
|
-
true
|
420
|
-
end
|
421
|
-
|
422
|
-
def merge(other)
|
423
|
-
unless can_merge?(other)
|
424
|
-
raise ArgumentError, 'Cannot merge. Possible causes: change is identical; key or value do not match'
|
425
|
-
end
|
426
|
-
|
427
|
-
new_to_value = value == other.value ? nil : other.value
|
428
|
-
ChangeSet.new(
|
429
|
-
change: '~',
|
430
|
-
key: key,
|
431
|
-
value: value,
|
432
|
-
value_to: new_to_value
|
433
|
-
)
|
434
|
-
end
|
435
|
-
|
436
|
-
private
|
437
|
-
|
438
|
-
def value_hash_equality(other)
|
439
|
-
equality = false
|
440
|
-
value.each do |k, v|
|
441
|
-
equality = true if v == other.value[k]
|
442
|
-
end
|
443
|
-
equality
|
444
|
-
end
|
445
|
-
|
446
|
-
def validate_change(change)
|
447
|
-
raise ArgumentError, "Change type #{change} in invalid" unless ['+', '-', '~'].include?(change)
|
448
|
-
end
|
449
|
-
|
450
|
-
def change_string
|
451
|
-
case change
|
452
|
-
when '-'
|
453
|
-
'remove'
|
454
|
-
when '+'
|
455
|
-
'add'
|
456
|
-
else
|
457
|
-
'change'
|
458
|
-
end
|
459
|
-
end
|
460
|
-
end
|
461
|
-
|
462
352
|
class ObjectContainer
|
463
353
|
include AbideDevUtils::XCCDF::Common
|
464
354
|
|
data/new_diff.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'pry'
|
6
|
+
require 'abide_dev_utils/xccdf/diff/benchmark'
|
7
|
+
|
8
|
+
xml_file1 = File.expand_path(ARGV[0])
|
9
|
+
xml_file2 = File.expand_path(ARGV[1])
|
10
|
+
legacy_config = ARGV.length > 2 ? YAML.load_file(File.expand_path(ARGV[2])) : nil
|
11
|
+
|
12
|
+
def convert_legacy_config(config, num_title_diff, key_format: :hiera_num)
|
13
|
+
nt_diff = num_title_diff.diff(key: :number)
|
14
|
+
updated_config = config['config']['control_configs'].each_with_object({}) do |(key, value), h|
|
15
|
+
next if value.nil?
|
16
|
+
|
17
|
+
diff_key = key.to_s.gsub(/^c/, '').tr('_', '.') if key_format == :hiera_num
|
18
|
+
if nt_diff.key?(diff_key)
|
19
|
+
if nt_diff[diff_key][0][:diff] == :number
|
20
|
+
new_key = "c#{nt_diff[diff_key][0][:other_number].to_s.tr('.', '_')}"
|
21
|
+
h[new_key] = value
|
22
|
+
puts "Converted #{key} to #{new_key}"
|
23
|
+
elsif nt_diff[diff_key][0][:diff] == :title
|
24
|
+
|
25
|
+
h[key] = value
|
26
|
+
end
|
27
|
+
else
|
28
|
+
h[key] = value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
{ 'config' => { 'control_configs' => updated_config } }.to_yaml
|
32
|
+
end
|
33
|
+
|
34
|
+
start_time = Time.now
|
35
|
+
|
36
|
+
bm_diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(xml_file1, xml_file2)
|
37
|
+
self_nc_count, other_nc_count = bm_diff.numbered_children_counts
|
38
|
+
puts "Benchmark numbered children count: #{self_nc_count}"
|
39
|
+
puts "Other benchmark numbered children count: #{other_nc_count}"
|
40
|
+
puts "Rule count difference: #{bm_diff.numbered_children_count_diff}"
|
41
|
+
num_diff = bm_diff.number_title_diff
|
42
|
+
binding.pry if legacy_config.nil?
|
43
|
+
File.open('/tmp/legacy_converted.yaml', 'w') do |f|
|
44
|
+
converted = convert_legacy_config(legacy_config, num_diff)
|
45
|
+
f.write(converted)
|
46
|
+
end
|
47
|
+
|
48
|
+
puts "Computation time: #{Time.now - start_time}"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abide_dev_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- abide-team
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.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: '1.
|
26
|
+
version: '1.13'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: cmdparse
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +122,34 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '1.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: amatch
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.4'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.4'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: facterdb
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.18'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.18'
|
125
153
|
- !ruby/object:Gem::Dependency
|
126
154
|
name: bundler
|
127
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -330,8 +358,15 @@ files:
|
|
330
358
|
- bin/setup
|
331
359
|
- exe/abide
|
332
360
|
- lib/abide_dev_utils.rb
|
361
|
+
- lib/abide_dev_utils/cem.rb
|
362
|
+
- lib/abide_dev_utils/cem/benchmark.rb
|
363
|
+
- lib/abide_dev_utils/cem/coverage_report.rb
|
364
|
+
- lib/abide_dev_utils/cem/generate.rb
|
365
|
+
- lib/abide_dev_utils/cem/generate/reference.rb
|
366
|
+
- lib/abide_dev_utils/cem/mapping/mapper.rb
|
333
367
|
- lib/abide_dev_utils/cli.rb
|
334
368
|
- lib/abide_dev_utils/cli/abstract.rb
|
369
|
+
- lib/abide_dev_utils/cli/cem.rb
|
335
370
|
- lib/abide_dev_utils/cli/comply.rb
|
336
371
|
- lib/abide_dev_utils/cli/jira.rb
|
337
372
|
- lib/abide_dev_utils/cli/puppet.rb
|
@@ -342,6 +377,7 @@ files:
|
|
342
377
|
- lib/abide_dev_utils/constants.rb
|
343
378
|
- lib/abide_dev_utils/errors.rb
|
344
379
|
- lib/abide_dev_utils/errors/base.rb
|
380
|
+
- lib/abide_dev_utils/errors/cem.rb
|
345
381
|
- lib/abide_dev_utils/errors/comply.rb
|
346
382
|
- lib/abide_dev_utils/errors/gcloud.rb
|
347
383
|
- lib/abide_dev_utils/errors/general.rb
|
@@ -351,19 +387,34 @@ files:
|
|
351
387
|
- lib/abide_dev_utils/files.rb
|
352
388
|
- lib/abide_dev_utils/gcloud.rb
|
353
389
|
- lib/abide_dev_utils/jira.rb
|
390
|
+
- lib/abide_dev_utils/markdown.rb
|
354
391
|
- lib/abide_dev_utils/mixins.rb
|
355
392
|
- lib/abide_dev_utils/output.rb
|
356
393
|
- lib/abide_dev_utils/ppt.rb
|
357
394
|
- lib/abide_dev_utils/ppt/api.rb
|
358
395
|
- lib/abide_dev_utils/ppt/class_utils.rb
|
359
|
-
- lib/abide_dev_utils/ppt/
|
396
|
+
- lib/abide_dev_utils/ppt/facter_utils.rb
|
397
|
+
- lib/abide_dev_utils/ppt/hiera.rb
|
360
398
|
- lib/abide_dev_utils/ppt/new_obj.rb
|
399
|
+
- lib/abide_dev_utils/ppt/puppet_module.rb
|
361
400
|
- lib/abide_dev_utils/ppt/score_module.rb
|
362
401
|
- lib/abide_dev_utils/prompt.rb
|
363
402
|
- lib/abide_dev_utils/resources/generic_spec.erb
|
364
403
|
- lib/abide_dev_utils/validate.rb
|
365
404
|
- lib/abide_dev_utils/version.rb
|
366
405
|
- lib/abide_dev_utils/xccdf.rb
|
406
|
+
- lib/abide_dev_utils/xccdf/diff.rb
|
407
|
+
- lib/abide_dev_utils/xccdf/diff/benchmark.rb
|
408
|
+
- lib/abide_dev_utils/xccdf/diff/benchmark/number_title.rb
|
409
|
+
- lib/abide_dev_utils/xccdf/diff/benchmark/profile.rb
|
410
|
+
- lib/abide_dev_utils/xccdf/diff/benchmark/property.rb
|
411
|
+
- lib/abide_dev_utils/xccdf/diff/benchmark/property_existence.rb
|
412
|
+
- lib/abide_dev_utils/xccdf/diff/utils.rb
|
413
|
+
- lib/abide_dev_utils/xccdf/parser.rb
|
414
|
+
- lib/abide_dev_utils/xccdf/parser/objects.rb
|
415
|
+
- lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb
|
416
|
+
- lib/abide_dev_utils/xccdf/parser/objects/numbered_object.rb
|
417
|
+
- new_diff.rb
|
367
418
|
homepage: https://github.com/puppetlabs/abide_dev_utils
|
368
419
|
licenses:
|
369
420
|
- MIT
|
@@ -371,7 +422,7 @@ metadata:
|
|
371
422
|
homepage_uri: https://github.com/puppetlabs/abide_dev_utils
|
372
423
|
source_code_uri: https://github.com/puppetlabs/abide_dev_utils
|
373
424
|
changelog_uri: https://github.com/puppetlabs/abide_dev_utils
|
374
|
-
post_install_message:
|
425
|
+
post_install_message:
|
375
426
|
rdoc_options: []
|
376
427
|
require_paths:
|
377
428
|
- lib
|
@@ -386,8 +437,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
386
437
|
- !ruby/object:Gem::Version
|
387
438
|
version: '0'
|
388
439
|
requirements: []
|
389
|
-
rubygems_version: 3.1.
|
390
|
-
signing_key:
|
440
|
+
rubygems_version: 3.1.4
|
441
|
+
signing_key:
|
391
442
|
specification_version: 4
|
392
443
|
summary: Helper utilities for developing compliance Puppet code
|
393
444
|
test_files: []
|
@@ -1,86 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
require 'pathname'
|
5
|
-
require 'yaml'
|
6
|
-
require 'puppet_pal'
|
7
|
-
require 'abide_dev_utils/ppt/class_utils'
|
8
|
-
|
9
|
-
module AbideDevUtils
|
10
|
-
module Ppt
|
11
|
-
class CoverageReport
|
12
|
-
def self.generate(puppet_class_dir, hiera_path, profile = nil)
|
13
|
-
coverage = {}
|
14
|
-
coverage['classes'] = {}
|
15
|
-
all_cap = ClassUtils.find_all_classes_and_paths(puppet_class_dir)
|
16
|
-
invalid_classes = find_invalid_classes(all_cap)
|
17
|
-
valid_classes = find_valid_classes(all_cap, invalid_classes)
|
18
|
-
coverage['classes']['invalid'] = invalid_classes
|
19
|
-
coverage['classes']['valid'] = valid_classes
|
20
|
-
hiera = YAML.safe_load(File.open(hiera_path))
|
21
|
-
profile&.gsub!(/^profile_/, '') unless profile.nil?
|
22
|
-
|
23
|
-
matcher = profile.nil? ? /^profile_/ : /^profile_#{profile}/
|
24
|
-
hiera.each do |k, v|
|
25
|
-
key_base = k.split('::')[-1]
|
26
|
-
coverage['benchmark'] = v if key_base == 'title'
|
27
|
-
next unless key_base.match?(matcher)
|
28
|
-
|
29
|
-
coverage[key_base] = generate_uncovered_data(v, valid_classes)
|
30
|
-
end
|
31
|
-
coverage
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.generate_uncovered_data(ctrl_list, valid_classes)
|
35
|
-
out_hash = {}
|
36
|
-
out_hash[:num_total] = ctrl_list.length
|
37
|
-
out_hash[:uncovered] = []
|
38
|
-
out_hash[:covered] = []
|
39
|
-
ctrl_list.each do |c|
|
40
|
-
if valid_classes.include?(c)
|
41
|
-
out_hash[:covered] << c
|
42
|
-
else
|
43
|
-
out_hash[:uncovered] << c
|
44
|
-
end
|
45
|
-
end
|
46
|
-
out_hash[:num_covered] = out_hash[:covered].length
|
47
|
-
out_hash[:num_uncovered] = out_hash[:uncovered].length
|
48
|
-
out_hash[:coverage] = Float(
|
49
|
-
(Float(out_hash[:num_covered]) / Float(out_hash[:num_total])) * 100.0
|
50
|
-
).floor(3)
|
51
|
-
out_hash
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.find_valid_classes(all_cap, invalid_classes)
|
55
|
-
all_classes = all_cap.dup.transpose[0]
|
56
|
-
return [] if all_classes.nil?
|
57
|
-
|
58
|
-
return all_classes - invalid_classes unless invalid_classes.nil?
|
59
|
-
|
60
|
-
all_classes
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.find_invalid_classes(all_cap)
|
64
|
-
invalid_classes = []
|
65
|
-
all_cap.each do |cap|
|
66
|
-
invalid_classes << cap[0] unless class_valid?(cap[1])
|
67
|
-
end
|
68
|
-
invalid_classes
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.class_valid?(manifest_path)
|
72
|
-
compiler = Puppet::Pal::Compiler.new(nil)
|
73
|
-
ast = compiler.parse_file(manifest_path)
|
74
|
-
ast.body.body.statements.each do |s|
|
75
|
-
next unless s.respond_to?(:arguments)
|
76
|
-
next unless s.arguments.respond_to?(:each)
|
77
|
-
|
78
|
-
s.arguments.each do |i|
|
79
|
-
return false if i.value == 'Not implemented'
|
80
|
-
end
|
81
|
-
end
|
82
|
-
true
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|