abide_dev_utils 0.4.1 → 0.6.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.
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'tempfile'
5
+ require 'abide_dev_utils/errors/ppt'
6
+
7
+ module AbideDevUtils
8
+ module Ppt
9
+ module ClassUtils
10
+ include AbideDevUtils::Errors::Ppt
11
+
12
+ CLASS_NAME_PATTERN = /\A([a-z][a-z0-9_]*)?(::[a-z][a-z0-9_]*)*\Z/.freeze
13
+ CLASS_NAME_CAPTURE_PATTERN = /\A^class (?<class_name>([a-z][a-z0-9_]*)?(::[a-z][a-z0-9_]*)*).*\Z/.freeze
14
+
15
+ # Validates a Puppet class name
16
+ # @param name [String] Puppet class name
17
+ # @return [Boolean] Is the name a valid Puppet class name
18
+ def self.valid_class_name?(name)
19
+ name.match?(CLASS_NAME_PATTERN)
20
+ end
21
+
22
+ # Takes a full Puppet class name and returns the path
23
+ # of the class file. This command must be run from the
24
+ # root module directory if validate_path is true.
25
+ # @param class_name [String] full Puppet class name
26
+ # @return [String] path to class file
27
+ def self.path_from_class_name(class_name)
28
+ parts = class_name.split('::')
29
+ parts[-1] = "#{parts[-1]}.pp"
30
+ File.expand_path(File.join('manifests', parts[1..-1]))
31
+ end
32
+
33
+ # Returns the namespaced class name from a file path
34
+ # @param class_path [String] the path to the Puppet class
35
+ # @return [String] the namespaced class name
36
+ def self.class_name_from_path(class_path)
37
+ parts = class_path.split(File::SEPARATOR).map { |x| x == '' ? File::SEPARATOR : x }
38
+ module_root_idx = parts.find_index('manifests') - 1
39
+ module_root = parts[module_root_idx].split('-')[-1]
40
+ namespaces = parts[(module_root_idx + 2)..-2].join('::') # add 2 to module root idx to skip manifests dir
41
+ class_name = parts[-1].delete_suffix('.pp')
42
+ [module_root, namespaces, class_name].join('::')
43
+ end
44
+
45
+ # Takes a path to a Puppet file and extracts the class name from the class declaration in the file.
46
+ # This differs from class_name_from_path because we actually read the class file and search
47
+ # the code for a class declaration to get the class name instead of just using the path
48
+ # to construct a valid Puppet class name.
49
+ # @param path [String] the path to a Puppet file
50
+ # @return [String] the Puppet class name
51
+ # @raise [ClassDeclarationNotFoundError] if there is not class declaration in the file
52
+ def self.class_name_from_declaration(path)
53
+ File.readlines(path).each do |line|
54
+ next unless line.match?(/^class /)
55
+
56
+ return CLASS_NAME_CAPTURE_PATTERN.match(line)['class_name']
57
+ end
58
+ raise ClassDeclarationNotFoundError, "Path:#{path}"
59
+ end
60
+
61
+ # Renames a file by file move. Ensures destination path exists before moving.
62
+ # @param from_path [String] path of the original file
63
+ # @param to_path [String] path of the new file
64
+ # @param verbose [Boolean] Sets verbose mode on file operations
65
+ # @param force [Boolean] If true, file move file overwrite existing files
66
+ def self.rename_class_file(from_path, to_path, **kwargs)
67
+ verbose = kwargs.fetch(:verbose, false)
68
+ force = kwargs.fetch(:force, false)
69
+ FileUtils.mkdir_p(File.dirname(to_path), verbose: verbose)
70
+ FileUtils.mv(from_path, to_path, verbose: verbose, force: force)
71
+ end
72
+
73
+ # Renames a Puppet class in the class declaration of the given file
74
+ # @param from [String] the original class name
75
+ # @param to [String] the new class name
76
+ # @param file_path [String] the path to the class file
77
+ # @param verbose [Boolean] Sets verbose mode on file operations
78
+ # @param force [Boolean] If true, file move file overwrite existing files
79
+ # @raise [ClassDeclarationNotFoundError] if the class file does not contain the from class declaration
80
+ def self.rename_puppet_class_declaration(from, to, file_path, **kwargs)
81
+ verbose = kwargs.fetch(:verbose, false)
82
+ force = kwargs.fetch(:force, false)
83
+ temp_file = Tempfile.new
84
+ renamed = false
85
+ begin
86
+ File.readlines(file_path).each do |line|
87
+ if line.match?(/^class #{from}.*/)
88
+ line.gsub!(/^class #{from}/, "class #{to}")
89
+ renamed = true
90
+ end
91
+ temp_file.puts line
92
+ end
93
+ raise ClassDeclarationNotFoundError, "File:#{file_path},Declaration:class #{from}" unless renamed
94
+
95
+ temp_file.close
96
+ FileUtils.mv(temp_file.path, file_path, verbose: verbose, force: force)
97
+ ensure
98
+ temp_file.close
99
+ temp_file.unlink
100
+ end
101
+ end
102
+
103
+ # Determines if a Puppet class name is mismatched by constructing a class name from
104
+ # a path to a Puppet file and extracting the class name from the class declaration
105
+ # inside the file. This is useful to determine if a Puppet class file breaks the
106
+ # autoload path pattern.
107
+ # @param path [String] path to a Puppet class file
108
+ # @return [Boolean] if the actual class name and path-constructed class name match
109
+ def self.mismatched_class_declaration?(path)
110
+ class_name_from_path(path) != class_name_from_declaration(path)
111
+ end
112
+
113
+ # Finds all Puppet classes in the given directory that have class declarations
114
+ # that do not adhere to the autoload path pattern.
115
+ # @param class_dir [String] path to a directory containing Puppet class files
116
+ # @return [Array] paths to all Puppet class files with mismatched class names
117
+ def self.find_all_mismatched_class_declarations(class_dir)
118
+ mismatched = []
119
+ Dir[File.join(File.expand_path(class_dir), '*.pp')].each do |class_file|
120
+ mismatched << class_file if mismatched_class_declaration?(class_file)
121
+ end
122
+ mismatched.sort
123
+ end
124
+
125
+ # Given a directory holding Puppet manifests, returns
126
+ # the full namespace for all classes in that directory.
127
+ # @param puppet_class_dir [String] path to a dir containing Puppet manifests
128
+ # @return [String] The namespace for all classes in manifests in the dir
129
+ def self.find_class_namespace(puppet_class_dir)
130
+ path = Pathname.new(puppet_class_dir)
131
+ mod_root = nil
132
+ ns_parts = []
133
+ found_manifests = false
134
+ path.ascend do |p|
135
+ if found_manifests
136
+ mod_root = find_mod_root(p)
137
+ break
138
+ end
139
+ if File.basename(p) == 'manifests'
140
+ found_manifests = true
141
+ next
142
+ else
143
+ ns_parts << File.basename(p)
144
+ end
145
+ end
146
+ "#{mod_root}::#{ns_parts.reverse.join('::')}::"
147
+ end
148
+
149
+ # Given a Pathname object of the 'manifests' directory in a Puppet module,
150
+ # determines the module namespace root. Does this by consulting
151
+ # metadata.json, if it exists, or by using the parent directory name.
152
+ # @param pathname [Pathname] A Pathname object of the module's manifests dir
153
+ # @return [String] The module's namespace root
154
+ def self.find_mod_root(pathname)
155
+ metadata_file = nil
156
+ pathname.entries.each do |e|
157
+ metadata_file = "#{pathname}/metadata.json" if File.basename(e) == 'metadata.json'
158
+ end
159
+ if metadata_file.nil?
160
+ File.basename(p)
161
+ else
162
+ File.open(metadata_file) do |f|
163
+ file = JSON.parse(f.read)
164
+ File.basename(p) unless file.key?('name')
165
+ file['name'].split('-')[-1]
166
+ end
167
+ end
168
+ end
169
+
170
+ # @return [Array] An array of frozen arrays where each sub-array's
171
+ # index 0 is class_name and index 1 is the full path to the file.
172
+ def self.find_all_classes_and_paths(puppet_class_dir)
173
+ all_cap = []
174
+ Dir.each_child(puppet_class_dir) do |c|
175
+ path = "#{puppet_class_dir}/#{c}"
176
+ next if File.directory?(path) || File.extname(path) != '.pp'
177
+
178
+ all_cap << [File.basename(path, '.pp'), path].freeze
179
+ end
180
+ all_cap
181
+ end
182
+ end
183
+ end
184
+ end
@@ -4,16 +4,15 @@ require 'json'
4
4
  require 'pathname'
5
5
  require 'yaml'
6
6
  require 'puppet_pal'
7
- require 'abide_dev_utils/ppt'
7
+ require 'abide_dev_utils/ppt/class_utils'
8
8
 
9
9
  module AbideDevUtils
10
10
  module Ppt
11
11
  class CoverageReport
12
- include AbideDevUtils::Ppt
13
12
  def self.generate(puppet_class_dir, hiera_path, profile = nil)
14
13
  coverage = {}
15
14
  coverage['classes'] = {}
16
- all_cap = AbideDevUtils::Ppt.find_all_classes_and_paths(puppet_class_dir)
15
+ all_cap = ClassUtils.find_all_classes_and_paths(puppet_class_dir)
17
16
  invalid_classes = find_invalid_classes(all_cap)
18
17
  valid_classes = find_valid_classes(all_cap, invalid_classes)
19
18
  coverage['classes']['invalid'] = invalid_classes
@@ -1,66 +1,152 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'abide_dev_utils/ppt/coverage'
4
- require 'abide_dev_utils/ppt/new_obj'
3
+ require 'abide_dev_utils/output'
4
+ require 'abide_dev_utils/validate'
5
+ require 'abide_dev_utils/errors'
6
+ require 'abide_dev_utils/ppt/class_utils'
5
7
 
6
8
  module AbideDevUtils
7
9
  module Ppt
8
- # Given a directory holding Puppet manifests, returns
9
- # the full namespace for all classes in that directory.
10
- # @param puppet_class_dir [String] path to a dir containing Puppet manifests
11
- # @return [String] The namespace for all classes in manifests in the dir
12
- def self.find_class_namespace(puppet_class_dir)
13
- path = Pathname.new(puppet_class_dir)
14
- mod_root = nil
15
- ns_parts = []
16
- found_manifests = false
17
- path.ascend do |p|
18
- if found_manifests
19
- mod_root = find_mod_root(p)
20
- break
21
- end
22
- if File.basename(p) == 'manifests'
23
- found_manifests = true
24
- next
25
- else
26
- ns_parts << File.basename(p)
27
- end
10
+ # Renames a Puppet class by renaming the class declaration and class file
11
+ # @param from [String] fully-namespaced existing Puppet class name
12
+ # @param to [String] fully-namespaced new Puppet class name
13
+ def self.rename_puppet_class(from, to, **kwargs)
14
+ from_path = ClassUtils.path_from_class_name(from)
15
+ to_path = ClassUtils.path_from_class_name(to)
16
+ file_path = kwargs.fetch(:declaration_in_to_file, false) ? to_path : from_path
17
+ raise ClassFileNotFoundError, "Path:#{file_path}" if !File.file?(file_path) && kwargs.fetch(:validate_path, true)
18
+
19
+ rename_puppet_class_declaration(from, to, file_path, **kwargs)
20
+ AbideDevUtils::Output.simple("Renamed #{from} to #{to} at #{file_path}.")
21
+ return unless kwargs.fetch(:declaration_only, false)
22
+
23
+ rename_class_file(from_path, to_path, **kwargs)
24
+ AbideDevUtils::Output.simple("Renamed file #{from_path} to #{to_path}.")
25
+ end
26
+
27
+ def self.audit_class_names(dir, **kwargs)
28
+ mismatched = ClassUtils.find_all_mismatched_class_declarations(dir)
29
+ outfile = kwargs.key?(:file) ? File.open(kwargs[:file], 'a') : nil
30
+ quiet = kwargs.fetch(:quiet, false)
31
+ mismatched.each do |class_file|
32
+ AbideDevUtils::Output.simple("Mismatched class name in file #{class_file}") unless quiet
33
+ outfile << "MISMATCHED_CLASS_NAME: #{class_file}\n" unless outfile.nil?
28
34
  end
29
- "#{mod_root}::#{ns_parts.reverse.join('::')}::"
35
+ outfile&.close
36
+ AbideDevUtils::Output.simple("Found #{mismatched.length} mismatched classes in #{dir}.") unless quiet
37
+ ensure
38
+ outfile&.close
30
39
  end
31
40
 
32
- # Given a Pathname object of the 'manifests' directory in a Puppet module,
33
- # determines the module namespace root. Does this by consulting
34
- # metadata.json, if it exists, or by using the parent directory name.
35
- # @param pathname [Pathname] A Pathname object of the module's manifests dir
36
- # @return [String] The module's namespace root
37
- def self.find_mod_root(pathname)
38
- metadata_file = nil
39
- pathname.entries.each do |e|
40
- metadata_file = "#{pathname}/metadata.json" if File.basename(e) == 'metadata.json'
41
+ def self.fix_class_names_file_rename(dir, **kwargs)
42
+ mismatched = ClassUtils.find_all_mismatched_class_declarations(dir)
43
+ progress = AbideDevUtils::Output.progress(title: 'Renaming files', total: mismatched.length)
44
+ mismatched.each do |class_path|
45
+ should = ClassUtils.path_from_class_name(class_name_from_declaration(class_path))
46
+ ClassUtils.rename_class_file(class_path, should, **kwargs)
47
+ progress.increment
48
+ AbideDevUtils::Output.simple("Renamed file #{class_path} to #{should}...") if kwargs.fetch(:verbose, false)
41
49
  end
42
- if metadata_file.nil?
43
- File.basename(p)
44
- else
45
- File.open(metadata_file) do |f|
46
- file = JSON.parse(f.read)
47
- File.basename(p) unless file.key?('name')
48
- file['name'].split('-')[-1]
49
- end
50
+ AbideDevUtils::Output.simple('Successfully fixed all classes.')
51
+ end
52
+
53
+ def self.fix_class_names_class_rename(dir, **kwargs)
54
+ mismatched = ClassUtils.find_all_mismatched_class_declarations(dir)
55
+ progress = AbideDevUtils::Output.progress(title: 'Renaming classes', total: mismatched.length)
56
+ mismatched.each do |class_path|
57
+ current = ClassUtils.class_name_from_declaration(class_path)
58
+ should = ClassUtils.class_name_from_path(class_path)
59
+ ClassUtils.rename_puppet_class_declaration(current, should, class_path, **kwargs)
60
+ progress.increment
61
+ AbideDevUtils::Output.simple("Renamed #{from} to #{to} at #{file_path}...") if kwargs.fetch(:verbose, false)
62
+ end
63
+ AbideDevUtils::Output.simple('Successfully fixed all classes.')
64
+ end
65
+
66
+ def self.generate_coverage_report(puppet_class_dir, hiera_path, profile = nil)
67
+ require 'abide_dev_utils/ppt/coverage'
68
+ CoverageReport.generate(puppet_class_dir, hiera_path, profile)
69
+ end
70
+
71
+ def self.build_new_object(type, name, opts)
72
+ require 'abide_dev_utils/ppt/new_obj'
73
+ AbideDevUtils::Ppt::NewObjectBuilder.new(
74
+ type,
75
+ name,
76
+ opts: opts,
77
+ vars: opts.fetch(:vars, '').split(',').map { |i| i.split('=') }.to_h # makes the str a hash
78
+ ).build
79
+ end
80
+
81
+ def self.add_cis_comment(path, xccdf, number_format: false)
82
+ require 'abide_dev_utils/xccdf'
83
+ utils = AbideDevUtils::XCCDF::UtilsObject
84
+ parsed_xccdf = utils.parse(xccdf)
85
+ return add_cis_comment_to_all(path, parsed_xccdf, utils, number_format: number_format) if File.directory?(path)
86
+ return add_cis_comment_to_single(path, parsed_xccdf, utils, number_format: number_format) if File.file?(path)
87
+
88
+ raise AbideDevUtils::Errors::FileNotFoundError, path
89
+ end
90
+
91
+ def self.add_cis_comment_to_single(path, xccdf, utils, number_format: false)
92
+ write_cis_comment_to_file(
93
+ path,
94
+ cis_recommendation_comment(
95
+ path,
96
+ utils.all_cis_recommendations(xccdf),
97
+ number_format,
98
+ utils
99
+ )
100
+ )
101
+ end
102
+
103
+ def self.add_cis_comment_to_all(path, xccdf, utils, number_format: false)
104
+ comments = {}
105
+ recommendations = utils.all_cis_recommendations(xccdf)
106
+ Dir[File.join(path, '*.pp')].each do |puppet_file|
107
+ comment = cis_recommendation_comment(puppet_file, recommendations, number_format, utils)
108
+ comments[puppet_file] = comment unless comment.nil?
109
+ end
110
+ comments.each do |key, value|
111
+ write_cis_comment_to_file(key, value)
50
112
  end
113
+ AbideDevUtils::Output.simple('Successfully added comments.')
51
114
  end
52
115
 
53
- # @return [Array] An array of frozen arrays where each sub-array's
54
- # index 0 is class_name and index 1 is the full path to the file.
55
- def self.find_all_classes_and_paths(puppet_class_dir)
56
- all_cap = []
57
- Dir.each_child(puppet_class_dir) do |c|
58
- path = "#{puppet_class_dir}/#{c}"
59
- next if File.directory?(path) || File.extname(path) != '.pp'
116
+ def self.write_cis_comment_to_file(path, comment)
117
+ require 'tempfile'
118
+ tempfile = Tempfile.new
119
+ begin
120
+ File.open(tempfile, 'w') do |nf|
121
+ nf.write("#{comment}\n")
122
+ File.foreach(path) do |line|
123
+ next if line.match?(/#{comment}/)
124
+
125
+ nf << line
126
+ end
127
+ end
128
+ File.rename(path, "#{path}.old")
129
+ tempfile.close
130
+ File.rename(tempfile.path, path)
131
+ File.delete("#{path}.old")
132
+ AbideDevUtils::Output.simple("Added CIS recomendation comment to #{path}...")
133
+ ensure
134
+ tempfile.close
135
+ tempfile.unlink
136
+ end
137
+ end
60
138
 
61
- all_cap << [File.basename(path, '.pp'), path].freeze
139
+ def self.cis_recommendation_comment(puppet_file, recommendations, number_format, utils)
140
+ reco_text = utils.find_cis_recommendation(
141
+ File.basename(puppet_file, '.pp'),
142
+ recommendations,
143
+ number_format: number_format
144
+ )
145
+ if reco_text.nil?
146
+ AbideDevUtils::Output.simple("Could not find recommendation text for #{puppet_file}...")
147
+ return nil
62
148
  end
63
- all_cap
149
+ "# #{reco_text}"
64
150
  end
65
151
  end
66
152
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbideDevUtils
4
- VERSION = "0.4.1"
4
+ VERSION = "0.6.0"
5
5
  end
@@ -3,6 +3,7 @@
3
3
  require 'yaml'
4
4
  require 'nokogiri'
5
5
  require 'abide_dev_utils/errors'
6
+ require 'abide_dev_utils/xccdf/utils'
6
7
 
7
8
  module AbideDevUtils
8
9
  module XCCDF
@@ -12,21 +13,23 @@ module AbideDevUtils
12
13
  # @!attribute [r] version
13
14
  # @!attribute [r] yaml_title
14
15
  class Hiera
15
- CONTROL_PREFIX = /^[\d.]+_/.freeze
16
- UNDERSCORED = /(\s|\(|\)|-|\.)/.freeze
17
- XPATHS = {
18
- benchmark: {
19
- all: 'xccdf:Benchmark',
20
- title: 'xccdf:Benchmark/xccdf:title',
21
- version: 'xccdf:Benchmark/xccdf:version'
22
- },
23
- profiles: {
24
- all: 'xccdf:Benchmark/xccdf:Profile',
25
- relative_title: './xccdf:title',
26
- relative_select: './xccdf:select'
27
- }
28
- }.freeze
29
- NEXT_GEN_WINDOWS = /(next_generation_windows_security)/.freeze
16
+ include AbideDevUtils::XCCDF::Utils
17
+
18
+ # CONTROL_PREFIX = /^[\d.]+_/.freeze
19
+ # UNDERSCORED = /(\s|\(|\)|-|\.)/.freeze
20
+ # XPATHS = {
21
+ # benchmark: {
22
+ # all: 'xccdf:Benchmark',
23
+ # title: 'xccdf:Benchmark/xccdf:title',
24
+ # version: 'xccdf:Benchmark/xccdf:version'
25
+ # },
26
+ # profiles: {
27
+ # all: 'xccdf:Benchmark/xccdf:Profile',
28
+ # relative_title: './xccdf:title',
29
+ # relative_select: './xccdf:select'
30
+ # }
31
+ # }.freeze
32
+ # NEXT_GEN_WINDOWS = /(next_generation_windows_security)/.freeze
30
33
 
31
34
  attr_reader :title, :version
32
35
 
@@ -37,15 +40,15 @@ module AbideDevUtils
37
40
  # the top-level key.
38
41
  def initialize(xccdf_file, parent_key_prefix: nil, num: false)
39
42
  @doc = parse(xccdf_file)
40
- @title = xpath(XPATHS[:benchmark][:title]).children.to_s
41
- @version = xpath(XPATHS[:benchmark][:version]).children.to_s
42
- @profiles = xpath(XPATHS[:profiles][:all])
43
+ @title = xpath(CIS_XPATHS[:benchmark][:title]).children.to_s
44
+ @version = xpath(CIS_XPATHS[:benchmark][:version]).children.to_s
45
+ @profiles = xpath(CIS_XPATHS[:profiles][:all])
43
46
  @parent_key = make_parent_key(@doc, parent_key_prefix)
44
- @hash = make_hash(@doc, @parent_key, num)
47
+ @hash = make_hash(@doc, number_format: num)
45
48
  end
46
49
 
47
50
  def yaml_title
48
- normalize_str(@title)
51
+ normalize_string(@title)
49
52
  end
50
53
 
51
54
  # Convert the Hiera object to a hash
@@ -63,8 +66,8 @@ module AbideDevUtils
63
66
  # Convert the Hiera object to YAML string
64
67
  # @return [String] YAML-formatted string
65
68
  def to_yaml
66
- yh = @hash[@parent_key.to_sym].transform_keys do |k|
67
- "#{@parent_key}::#{k}"
69
+ yh = @hash.transform_keys do |k|
70
+ [@parent_key, k].join('::').strip
68
71
  end
69
72
  yh.to_yaml
70
73
  end
@@ -92,64 +95,66 @@ module AbideDevUtils
92
95
 
93
96
  attr_accessor :doc, :hash, :parent_key, :profiles
94
97
 
95
- # Accepts a path to an xccdf xml file and returns a parsed Nokogiri object of the file
96
- # @param xccdf_file [String] path to an xccdf xml file
97
- # @return [Nokogiri::Node] A Nokogiri node object of the XML document
98
- def parse(xccdf_file)
99
- raise AbideDevUtils::Errors::FileNotFoundError, xccdf_file unless File.file?(xccdf_file)
98
+ # # Accepts a path to an xccdf xml file and returns a parsed Nokogiri object of the file
99
+ # # @param xccdf_file [String] path to an xccdf xml file
100
+ # # @return [Nokogiri::Node] A Nokogiri node object of the XML document
101
+ # def parse(xccdf_file)
102
+ # raise AbideDevUtils::Errors::FileNotFoundError, xccdf_file unless File.file?(xccdf_file)
100
103
 
101
- Nokogiri.XML(File.open(xccdf_file))
102
- end
104
+ # Nokogiri.XML(File.open(xccdf_file))
105
+ # end
103
106
 
104
- def make_hash(doc, parent_key, num)
105
- hash = { parent_key.to_sym => { title: @title, version: @version } }
107
+ def make_hash(doc, number_format: false)
108
+ hash = { 'title' => @title, 'version' => @version }
106
109
  profiles = doc.xpath('xccdf:Benchmark/xccdf:Profile')
107
110
  profiles.each do |p|
108
111
  title = normalize_profile_name(p.xpath('./xccdf:title').children.to_s)
109
- hash[parent_key.to_sym][title.to_sym] = []
112
+ hash[title.to_s] = []
110
113
  selects = p.xpath('./xccdf:select')
111
114
  selects.each do |s|
112
- hash[parent_key.to_sym][title.to_sym] << normalize_ctrl_name(s['idref'].to_s, num)
115
+ hash[title.to_s] << normalize_control_name(s['idref'].to_s, number_format: number_format)
113
116
  end
114
117
  end
115
118
  hash
116
119
  end
117
120
 
118
- def normalize_str(str)
119
- nstr = str.downcase
120
- nstr.gsub!(/[^a-z0-9]$/, '')
121
- nstr.gsub!(/^[^a-z]/, '')
122
- nstr.gsub!(/^(l1_|l2_|ng_)/, '')
123
- nstr.delete!('(/|\\)')
124
- nstr.gsub!(UNDERSCORED, '_')
125
- nstr
126
- end
127
-
128
- def normalize_profile_name(prof)
129
- prof_name = normalize_str("profile_#{prof}")
130
- prof_name.gsub!(NEXT_GEN_WINDOWS, 'ngws')
131
- prof_name
132
- end
133
-
134
- def normalize_ctrl_name(ctrl, num)
135
- return num_normalize_ctrl(ctrl) if num
136
-
137
- name_normalize_ctrl(ctrl)
138
- end
139
-
140
- def name_normalize_ctrl(ctrl)
141
- new_ctrl = ctrl.split('benchmarks_rule_')[-1].gsub(CONTROL_PREFIX, '')
142
- normalize_str(new_ctrl)
143
- end
144
-
145
- def num_normalize_ctrl(ctrl)
146
- part = ctrl.split('benchmarks_rule_')[-1]
147
- numpart = CONTROL_PREFIX.match(part).to_s.chop.gsub(UNDERSCORED, '_')
148
- "c#{numpart}"
149
- end
121
+ # def normalize_str(str)
122
+ # nstr = str.downcase
123
+ # nstr.gsub!(/[^a-z0-9]$/, '')
124
+ # nstr.gsub!(/^[^a-z]/, '')
125
+ # nstr.gsub!(/^(l1_|l2_|ng_)/, '')
126
+ # nstr.delete!('(/|\\|\+)')
127
+ # nstr.gsub!(UNDERSCORED, '_')
128
+ # nstr.strip!
129
+ # nstr
130
+ # end
131
+
132
+ # def normalize_profile_name(prof)
133
+ # prof_name = normalize_str("profile_#{prof}")
134
+ # prof_name.gsub!(NEXT_GEN_WINDOWS, 'ngws')
135
+ # prof_name.strip!
136
+ # prof_name
137
+ # end
138
+
139
+ # def normalize_ctrl_name(ctrl, num)
140
+ # return num_normalize_ctrl(ctrl) if num
141
+
142
+ # name_normalize_ctrl(ctrl)
143
+ # end
144
+
145
+ # def name_normalize_ctrl(ctrl)
146
+ # new_ctrl = ctrl.split('benchmarks_rule_')[-1].gsub(CONTROL_PREFIX, '')
147
+ # normalize_str(new_ctrl)
148
+ # end
149
+
150
+ # def num_normalize_ctrl(ctrl)
151
+ # part = ctrl.split('benchmarks_rule_')[-1]
152
+ # numpart = CONTROL_PREFIX.match(part).to_s.chop.gsub(UNDERSCORED, '_')
153
+ # "c#{numpart}"
154
+ # end
150
155
 
151
156
  def make_parent_key(doc, prefix)
152
- doc_title = normalize_str(doc.xpath(XPATHS[:benchmark][:title]).children.to_s)
157
+ doc_title = normalize_string(doc.xpath(CIS_XPATHS[:benchmark][:title]).children.to_s)
153
158
  return doc_title if prefix.nil?
154
159
 
155
160
  sepped_prefix = prefix.end_with?('::') ? prefix : "#{prefix}::"