abide_dev_utils 0.11.0 → 0.12.1

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +18 -31
  3. data/lib/abide_dev_utils/cem/benchmark.rb +335 -136
  4. data/lib/abide_dev_utils/cem/generate/coverage_report.rb +380 -0
  5. data/lib/abide_dev_utils/cem/generate/reference.rb +238 -35
  6. data/lib/abide_dev_utils/cem/generate.rb +5 -4
  7. data/lib/abide_dev_utils/cem/hiera_data/mapping_data/map_data.rb +110 -0
  8. data/lib/abide_dev_utils/cem/hiera_data/mapping_data/mixins.rb +46 -0
  9. data/lib/abide_dev_utils/cem/hiera_data/mapping_data.rb +146 -0
  10. data/lib/abide_dev_utils/cem/hiera_data/resource_data/control.rb +127 -0
  11. data/lib/abide_dev_utils/cem/hiera_data/resource_data/parameters.rb +90 -0
  12. data/lib/abide_dev_utils/cem/hiera_data/resource_data/resource.rb +102 -0
  13. data/lib/abide_dev_utils/cem/hiera_data/resource_data.rb +310 -0
  14. data/lib/abide_dev_utils/cem/hiera_data.rb +7 -0
  15. data/lib/abide_dev_utils/cem/mapping/mapper.rb +161 -34
  16. data/lib/abide_dev_utils/cem/validate/resource_data.rb +33 -0
  17. data/lib/abide_dev_utils/cem/validate.rb +10 -0
  18. data/lib/abide_dev_utils/cem.rb +0 -1
  19. data/lib/abide_dev_utils/cli/cem.rb +20 -2
  20. data/lib/abide_dev_utils/dot_number_comparable.rb +75 -0
  21. data/lib/abide_dev_utils/errors/cem.rb +10 -0
  22. data/lib/abide_dev_utils/ppt/class_utils.rb +1 -1
  23. data/lib/abide_dev_utils/ppt/code_gen/data_types.rb +64 -0
  24. data/lib/abide_dev_utils/ppt/code_gen/generate.rb +15 -0
  25. data/lib/abide_dev_utils/ppt/code_gen/resource.rb +59 -0
  26. data/lib/abide_dev_utils/ppt/code_gen/resource_types/base.rb +93 -0
  27. data/lib/abide_dev_utils/ppt/code_gen/resource_types/class.rb +17 -0
  28. data/lib/abide_dev_utils/ppt/code_gen/resource_types/manifest.rb +16 -0
  29. data/lib/abide_dev_utils/ppt/code_gen/resource_types/parameter.rb +16 -0
  30. data/lib/abide_dev_utils/ppt/code_gen/resource_types/strings.rb +13 -0
  31. data/lib/abide_dev_utils/ppt/code_gen/resource_types.rb +6 -0
  32. data/lib/abide_dev_utils/ppt/code_gen.rb +15 -0
  33. data/lib/abide_dev_utils/ppt/code_introspection.rb +102 -0
  34. data/lib/abide_dev_utils/ppt/hiera.rb +4 -1
  35. data/lib/abide_dev_utils/ppt/puppet_module.rb +2 -1
  36. data/lib/abide_dev_utils/ppt.rb +3 -0
  37. data/lib/abide_dev_utils/version.rb +1 -1
  38. data/lib/abide_dev_utils/xccdf/parser/helpers.rb +146 -0
  39. data/lib/abide_dev_utils/xccdf/parser/objects.rb +87 -144
  40. data/lib/abide_dev_utils/xccdf/parser.rb +5 -0
  41. data/lib/abide_dev_utils/xccdf/utils.rb +89 -0
  42. data/lib/abide_dev_utils/xccdf.rb +193 -63
  43. metadata +27 -3
  44. data/lib/abide_dev_utils/cem/coverage_report.rb +0 -348
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbideDevUtils
4
+ # Module provides comparison methods for "dot numbers", numbers that
5
+ # take the form of "1.1.1" as found in CIS benchmarks. Classes that
6
+ # include this module must implement a method "number" that returns
7
+ # their dot number representation.
8
+ module DotNumberComparable
9
+ include ::Comparable
10
+
11
+ def <=>(other)
12
+ return 0 if number_eq(number, other.number)
13
+ return 1 if number_gt(number, other.number)
14
+ return -1 if number_lt(number, other.number)
15
+ end
16
+
17
+ def number_eq(this_num, other_num)
18
+ this_num == other_num
19
+ end
20
+
21
+ def number_parent_of?(this_num, other_num)
22
+ return false if number_eq(this_num, other_num)
23
+
24
+ # We split the numbers into parts and compare the resulting arrays
25
+ num1_parts = this_num.to_s.split('.')
26
+ num2_parts = other_num.to_s.split('.')
27
+ # For this_num to be a parent of other_num, the number of parts in
28
+ # this_num must be less than the number of parts in other_num.
29
+ # Additionally, each part of this_num must be equal to the parts of
30
+ # other_num at the same index.
31
+ # Example: this_num = '1.2.3' and other_num = '1.2.3.4'
32
+ # In this case, num1_parts = ['1', '2', '3'] and num2_parts = ['1', '2', '3', '4']
33
+ # So, this_num is a parent of other_num because at indexes 0, 1, and 2
34
+ # of num1_parts and num2_parts, the parts are equal.
35
+ num1_parts.length < num2_parts.length &&
36
+ num2_parts[0..(num1_parts.length - 1)] == num1_parts
37
+ end
38
+
39
+ def number_child_of?(this_num, other_num)
40
+ number_parent_of?(other_num, this_num)
41
+ end
42
+
43
+ def number_gt(this_num, other_num)
44
+ return false if number_eq(this_num, other_num)
45
+ return true if number_parent_of?(this_num, other_num)
46
+
47
+ num1_parts = this_num.to_s.split('.')
48
+ num2_parts = other_num.to_s.split('.')
49
+ num1_parts.zip(num2_parts).each do |num1_part, num2_part|
50
+ next if num1_part == num2_part # we skip past equal parts
51
+
52
+ # If num1_part is nil that means that we've had equal numbers so far.
53
+ # Therfore, this_num is greater than other num because of the
54
+ # hierarchical nature of the numbers.
55
+ # Example: this_num = '1.2' and other_num = '1.2.3'
56
+ # In this case, num1_part is nil and num2_part is '3'
57
+ # So, this_num is greater than other_num
58
+ return true if num1_part.nil?
59
+ # If num2_part is nil that means that we've had equal numbers so far.
60
+ # Therfore, this_num is less than other num because of the
61
+ # hierarchical nature of the numbers.
62
+ # Example: this_num = '1.2.3' and other_num = '1.2'
63
+ # In this case, num1_part is '3' and num2_part is nil
64
+ # So, this_num is less than other_num
65
+ return false if num2_part.nil?
66
+
67
+ return num1_part.to_i > num2_part.to_i
68
+ end
69
+ end
70
+
71
+ def number_lt(this_num, other_num)
72
+ number_gt(other_num, this_num)
73
+ end
74
+ end
75
+ end
@@ -18,5 +18,15 @@ module AbideDevUtils
18
18
  class ResourceDataNotFoundError < GenericError
19
19
  @default = 'Resource data not found using facts:'
20
20
  end
21
+
22
+ # Raised by Control when it can't find mapping data for itself
23
+ class NoMappingDataForControlError < GenericError
24
+ @default = 'No mapping data found for control:'
25
+ end
26
+
27
+ # Raised by a control when it's given ID and framework are incompatible
28
+ class ControlIdFrameworkMismatchError < GenericError
29
+ @default = 'Control ID is invalid with the given framework:'
30
+ end
21
31
  end
22
32
  end
@@ -27,7 +27,7 @@ module AbideDevUtils
27
27
  def self.path_from_class_name(class_name)
28
28
  parts = class_name.split('::')
29
29
  parts[-1] = "#{parts[-1]}.pp"
30
- File.expand_path(File.join('manifests', parts[1..-1]))
30
+ File.expand_path(File.join('manifests', parts[1..]))
31
31
  end
32
32
 
33
33
  # Returns the namespaced class name from a file path
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puppet'
4
+
5
+ module AbideDevUtils
6
+ module Ppt
7
+ module CodeGen
8
+ module DataTypes
9
+ def infer_data_type(data)
10
+ Puppet::Pops::Types::TypeCalculator.infer(data).to_s
11
+ end
12
+
13
+ # Displays a Puppet type value as a string
14
+ def display_value(val)
15
+ if val.is_a?(Puppet::Pops::Model::LiteralUndef)
16
+ 'undef'
17
+ elsif val.respond_to?(:value)
18
+ display_value(val.value)
19
+ elsif val.respond_to?(:cased_value)
20
+ display_value(val.cased_value)
21
+ else
22
+ val
23
+ end
24
+ end
25
+
26
+ # Displays a Puppet type expression (type signature) as a string
27
+ # @param param [Puppet::Pops::Model::Parameter] AST Parameter node of a parsed Puppet manifest
28
+ def display_type_expr(param)
29
+ te = param.respond_to?(:type_expr) ? param.type_expr : param
30
+ if te.respond_to? :left_expr
31
+ display_type_expr_with_left_expr(te)
32
+ elsif te.respond_to? :entries
33
+ display_type_expr_with_entries(te)
34
+ elsif te.respond_to? :cased_value
35
+ te.cased_value
36
+ elsif te.respond_to? :value
37
+ te.value
38
+ end
39
+ end
40
+
41
+ # Used by #display_type_expr
42
+ def display_type_expr_with_left_expr(te)
43
+ cased = nil
44
+ keys = nil
45
+ cased = te.left_expr.cased_value if te.left_expr.respond_to? :cased_value
46
+ keys = te.keys.map { |x| display_type_expr(x) }.to_s if te.respond_to? :keys
47
+ keys.tr!('"', '') unless cased == 'Enum'
48
+ "#{cased}#{keys}"
49
+ end
50
+
51
+ # Used by #display_type_expr
52
+ def display_type_expr_with_entries(te)
53
+ te.entries.each_with_object({}) do |x, hsh|
54
+ key = nil
55
+ val = nil
56
+ key = display_value(x.key) if x.respond_to? :key
57
+ val = display_type_expr(x.value) if x.respond_to? :value
58
+ hsh[key] = val if key
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/ppt/code_gen/resource_types'
4
+
5
+ module AbideDevUtils
6
+ module Ppt
7
+ module CodeGen
8
+ module Generate
9
+ def self.a_manifest
10
+ AbideDevUtils::Ppt::CodeGen::Manifest.new
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbideDevUtils
4
+ module Ppt
5
+ module CodeGen
6
+ class Resource
7
+ attr_reader :type, :title
8
+
9
+ def initialize(type, title, **attributes)
10
+ validate_type_and_title(type, title)
11
+ @type = type
12
+ @title = title
13
+ @attributes = attributes
14
+ end
15
+
16
+ def reference
17
+ "#{title.split('::').map(&:capitalize).join('::')}['#{title}']"
18
+ end
19
+
20
+ def to_s
21
+ return "#{type} { '#{title}': }" if @attributes.empty?
22
+
23
+ str_array = ["#{type} { '#{title}':"]
24
+ @attributes.each do |key, val|
25
+ str_array << " #{pad_attribute(key)} => #{val},"
26
+ end
27
+ str_array << '}'
28
+ str_array.join("\n")
29
+ end
30
+
31
+ private
32
+
33
+ def validate_type_and_title(type, title)
34
+ raise 'Type / title must be String' unless type.is_a?(String) && title.is_a?(String)
35
+ raise 'Type / title must not be empty' if type.empty? || title.empty?
36
+ end
37
+
38
+ def longest_attribute_length
39
+ return @longest_attribute_length if defined?(@longest_attribute_length)
40
+
41
+ longest = ''
42
+ @attributes.each_key do |k|
43
+ longest = k if k.length > longest.length
44
+ end
45
+ @longest_attribute_length = longest.length
46
+ @longest_attribute_length
47
+ end
48
+
49
+ def pad_attribute(attribute)
50
+ return attribute if attribute.length == longest_attribute_length
51
+
52
+ attr_array = [attribute]
53
+ (longest_attribute_length - attribute.length).times { attr_array << ' ' }
54
+ attr_array.join
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module AbideDevUtils
6
+ module Ppt
7
+ module CodeGen
8
+ # Base class for all code gen objects
9
+ class Base
10
+ attr_accessor :title, :id
11
+
12
+ def initialize
13
+ @id = SecureRandom.hex(10)
14
+ @supports_value = false
15
+ @supports_children = false
16
+ end
17
+
18
+ def to_s
19
+ "#{type} : value: #{@value}; children: #{@children}"
20
+ end
21
+
22
+ def reference
23
+ raise NotImplementedError, "#{type} does not support having a reference"
24
+ end
25
+
26
+ def type
27
+ self.class.to_s
28
+ end
29
+
30
+ def value
31
+ raise NotImplementedError, "#{type} does not support having a value" unless @supports_value
32
+
33
+ @value
34
+ end
35
+
36
+ def get_my(t, named: nil)
37
+ if named.nil?
38
+ children.each_with_object([]) do |(k, v), arr|
39
+ arr << v if k.start_with?("#{t.to_s.capitalize}_")
40
+ end
41
+ else
42
+ children["#{t.to_s.capitalize}_#{named}"]
43
+ end
44
+ end
45
+
46
+ # Creates a new object of the given type and adds it to the current objects children
47
+ # if the current object supports children.
48
+ # Returns `self`. If a block is given, the new
49
+ # object will be yielded before adding to children.
50
+ def with_a(t, named: nil)
51
+ obj = Object.const_get("AbideDevUtils::Ppt::CodeGen::#{t.to_s.capitalize}").new
52
+ obj.title = named unless named.nil? || named.empty?
53
+
54
+ yield obj if block_given?
55
+
56
+ children["#{t.to_s.capitalize}_#{obj.id}"] = obj
57
+ self
58
+ end
59
+ alias and_a with_a
60
+
61
+ def has_a(t, named: nil)
62
+ obj = Object.const_get("AbideDevUtils::Ppt::CodeGen::#{t.to_s.capitalize}").new
63
+ obj.title = named unless named.nil? || named.empty?
64
+ children["#{t.to_s.capitalize}_#{obj.id}"] = obj
65
+ obj
66
+ end
67
+ alias and_has_a has_a
68
+ alias that_has_a has_a
69
+
70
+ # Sets the explicit value of the current object if the current object has an explicit value.
71
+ def that_equals(val)
72
+ self.value = val
73
+ self
74
+ end
75
+ alias and_assign_a_value_of that_equals
76
+ alias has_a_value_of that_equals
77
+ alias that_has_a_value_of that_equals
78
+
79
+ private
80
+
81
+ def children
82
+ raise NotImplementedError, "#{type} does not support children" unless @supports_children
83
+
84
+ @children ||= {}
85
+ end
86
+
87
+ def value=(val)
88
+ @value = val if @supports_value
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/ppt/code_gen/resource_types/base'
4
+
5
+ module AbideDevUtils
6
+ module Ppt
7
+ module CodeGen
8
+ class Class < Base
9
+ def initialize
10
+ super
11
+ @supports_children = true
12
+ @supports_value = true
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/ppt/code_gen/resource_types/base'
4
+
5
+ module AbideDevUtils
6
+ module Ppt
7
+ module CodeGen
8
+ class Manifest < Base
9
+ def initialize
10
+ super
11
+ @supports_children = true
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/ppt/code_gen/resource_types/base'
4
+
5
+ module AbideDevUtils
6
+ module Ppt
7
+ module CodeGen
8
+ class Parameter < Base
9
+ def initialize
10
+ @supports_children = true
11
+ @supports_value = true
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/ppt/code_gen/resource_types/base'
4
+
5
+ module AbideDevUtils
6
+ module Ppt
7
+ module CodeGen
8
+ class Strings < Base
9
+ VALID_CHILDREN = %w[See Summary Param Example].freeze
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/ppt/code_gen/resource_types/class'
4
+ require 'abide_dev_utils/ppt/code_gen/resource_types/manifest'
5
+ require 'abide_dev_utils/ppt/code_gen/resource_types/parameter'
6
+ require 'abide_dev_utils/ppt/code_gen/resource_types/strings'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/ppt/code_gen/data_types'
4
+ require 'abide_dev_utils/ppt/code_gen/resource'
5
+ require 'abide_dev_utils/ppt/code_gen/resource_types'
6
+
7
+ module AbideDevUtils
8
+ module Ppt
9
+ module CodeGen
10
+ def self.generate_a_manifest
11
+ Manifest.new
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puppet_pal'
4
+ require_relative 'code_gen/data_types'
5
+
6
+ module AbideDevUtils
7
+ module Ppt
8
+ module CodeIntrospection
9
+ class Manifest
10
+ attr_reader :manifest_file
11
+
12
+ def initialize(manifest_file)
13
+ @manifest_file = File.expand_path(manifest_file)
14
+ raise ArgumentError, "File #{@manifest_file} is not a file" unless File.file?(@manifest_file)
15
+ end
16
+
17
+ def ast
18
+ @ast ||= Puppet::Pal::Compiler.new(nil).parse_file(manifest_file)
19
+ end
20
+
21
+ def declaration
22
+ @declaration ||= Declaration.new(ast)
23
+ end
24
+ end
25
+
26
+ class Declaration
27
+ include AbideDevUtils::Ppt::CodeGen::DataTypes
28
+ attr_reader :ast
29
+
30
+ def initialize(ast)
31
+ @ast = ast.definitions.first
32
+ end
33
+
34
+ def parameters?
35
+ ast.respond_to? :parameters
36
+ end
37
+
38
+ def parameters
39
+ return unless parameters?
40
+
41
+ @parameters ||= ast.parameters.map { |p| Parameter.new(p) }
42
+ end
43
+ end
44
+
45
+ class Parameter
46
+ include AbideDevUtils::Ppt::CodeGen::DataTypes
47
+ attr_reader :ast
48
+
49
+ def initialize(param_ast)
50
+ @ast = param_ast
51
+ end
52
+
53
+ def to_a(raw: false)
54
+ [type_expr(raw: raw), name(raw: raw), value(raw: raw)]
55
+ end
56
+
57
+ def to_h(raw: false)
58
+ {
59
+ type_expr: type_expr(raw: raw),
60
+ name: name(raw: raw),
61
+ value: value(raw: raw),
62
+ }
63
+ end
64
+
65
+ def to_s(raw: false)
66
+ stra = [type_expr(raw: raw), name(raw: raw)]
67
+ stra << '=' if value? && !raw
68
+ stra << value(raw: raw)
69
+ stra.compact.join(' ')
70
+ end
71
+
72
+ def name(raw: false)
73
+ return ast.name if raw
74
+
75
+ "$#{ast.name}"
76
+ end
77
+
78
+ def value?
79
+ ast.respond_to? :value
80
+ end
81
+
82
+ def value(raw: false)
83
+ return unless value?
84
+ return ast.value if raw
85
+
86
+ display_value(ast)
87
+ end
88
+
89
+ def type_expr?
90
+ ast.respond_to? :type_expr
91
+ end
92
+
93
+ def type_expr(raw: false)
94
+ return unless type_expr?
95
+ return ast.type_expr if raw
96
+
97
+ display_type_expr(ast)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -38,10 +38,13 @@ module AbideDevUtils
38
38
  @path = File.expand_path(path)
39
39
  raise "Hiera config file at path #{@path} not found!" unless File.file?(@path)
40
40
 
41
+ @root_dir = File.dirname(@path)
41
42
  @conf = YAML.load_file(File.expand_path(path))
42
43
  @by_name_path_store = {}
43
- AbideDevUtils::Ppt::Hiera.default_datadir = @conf['defaults']['datadir'] if @conf['defaults'].key?('datadir')
44
44
  AbideDevUtils::Ppt::Hiera.facter_version = facter_version
45
+ if @conf['defaults'].key?('datadir')
46
+ AbideDevUtils::Ppt::Hiera.default_datadir = File.join(@root_dir, @conf['defaults']['datadir'])
47
+ end
45
48
  end
46
49
 
47
50
  def hierarchy
@@ -14,6 +14,7 @@ module AbideDevUtils
14
14
  readme: 'README.md',
15
15
  reference: 'REFERENCE.md',
16
16
  changelog: 'CHANGELOG.md',
17
+ hiera_config: 'hiera.yaml',
17
18
  fixtures: '.fixtures.yml',
18
19
  rubocop: '.rubocop.yml',
19
20
  sync: '.sync.yml',
@@ -42,7 +43,7 @@ module AbideDevUtils
42
43
  end
43
44
 
44
45
  def hiera_conf
45
- @hiera_conf ||= AbideDevUtils::Ppt::Hiera::Config.new
46
+ @hiera_conf ||= AbideDevUtils::Ppt::Hiera::Config.new(special_files[:hiera_config])
46
47
  end
47
48
 
48
49
  private
@@ -3,6 +3,9 @@
3
3
  require 'abide_dev_utils/output'
4
4
  require 'abide_dev_utils/validate'
5
5
  require 'abide_dev_utils/errors'
6
+ require 'abide_dev_utils/ppt/api'
7
+ require 'abide_dev_utils/ppt/code_gen'
8
+ require 'abide_dev_utils/ppt/code_introspection'
6
9
  require 'abide_dev_utils/ppt/class_utils'
7
10
  require 'abide_dev_utils/ppt/facter_utils'
8
11
  require 'abide_dev_utils/ppt/hiera'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbideDevUtils
4
- VERSION = "0.11.0"
4
+ VERSION = "0.12.1"
5
5
  end