abide_dev_utils 0.2.1 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9e993f8a435b4be58831bc98cf1658533c8c1084f14c96c1a12ecd73ff89da6
4
- data.tar.gz: 1120b6cc91eac28ff8168e808f13c16cf6c6d844b5928f04f4f4bb6d7cda0bcb
3
+ metadata.gz: ecd985f39afeac37bf8f2305dc65c782f34722f95a655249d7219b975952012f
4
+ data.tar.gz: 9123b33054f39149ba2deb34464b56bcac404438ac161f64a02e93fc1d33b340
5
5
  SHA512:
6
- metadata.gz: bcf0b6aa95f003e5402be98cc797202949368ceff62e6cdb778f4002e452716ef5ef833bc0bcd34bb797f628997e1c807d88f191048a5afec767bd8bcb7dc7a3
7
- data.tar.gz: 2ca0b4fb33d0329f13e3ce04d317427b4ba67c9937b4df739d991a1692871d19c17d1eeb24d5035573a676560795ae466e6df65148693258718aeda115c9e1d8
6
+ metadata.gz: 595556633f91088d8b34ac1d17d5f012c9d84ca7c03d45ef31bd59ccc45278b008f967b5e096909fa625c8eac7911163584ac7d0d4cc46caa1bd062b14eb1f7c
7
+ data.tar.gz: 0dc612075817afeae37820a7c2d097a29af5ed3ee491b7ab2c61743e209b0345e5fd5fff6f5aab53b3d85b9f0e5b9c07cf16cefff5092ec981c679523fd141e2
data/.dockerignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Dockerfile ADDED
@@ -0,0 +1,23 @@
1
+ FROM ruby:2.7.3-alpine
2
+
3
+ ARG version
4
+
5
+ RUN mkdir /extvol && \
6
+ apk update && \
7
+ apk add git build-base
8
+
9
+ VOLUME /extvol
10
+
11
+ WORKDIR /usr/src/app
12
+
13
+ RUN mkdir -p ./lib/abide_dev_utils/
14
+ COPY Gemfile abide_dev_utils.gemspec ./
15
+ COPY lib/abide_dev_utils/version.rb lib/abide_dev_utils
16
+ RUN bundle install
17
+
18
+ COPY . .
19
+
20
+ RUN bundle exec rake build && \
21
+ gem install pkg/abide_dev_utils-${version}.gem
22
+
23
+ ENTRYPOINT [ "abide" ]
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Helper library and CLI app for Abide development.
4
4
 
5
+ Issues and pull requests are welcome!
6
+
5
7
  ## Features
6
8
 
7
9
  ### CLI
@@ -125,7 +127,9 @@ Install the gem:
125
127
  * `--root-dir`, `-r` - Path to the root directory of your module. Defaults to the current working directory
126
128
  * `--absolute-template-dir`, `-A` - Allows you to specify an absolute path with `--template-dir`. This is useful if your template directory is not relative to your module's root directory
127
129
  * `--template-name`, `-n` - Allows you to specify a template name if it is different than the `TYPE` parameter
128
- * `--vars`, `-v` - Comma-separated key=value pairs to pass in to the template renderer. This allows you to pass arbitrary values that can be used in your templates.
130
+ * `--vars`, `-V` - Comma-separated key=value pairs to pass in to the template renderer. This allows you to pass arbitrary values that can be used in your templates.
131
+ * `--spec-template`, `-S` - Path to an ERB template to use for rspec test generation instead of the default
132
+ * `--force`, `-f` - Skips any prompts and executes the command
129
133
 
130
134
  `abide puppet new` exposes a few variables for you to use in your templates by default:
131
135
 
@@ -177,8 +181,10 @@ $ ls manifests
177
181
  init.pp
178
182
  $ abide puppet new control_class 'test_module::controls::test_new_control'
179
183
  Created file /Users/the.dude/test_module/manifests/controls/test_new_control.pp
184
+ Created file /Users/the.dude/test_module/spec/classes/controls/test_new_control_spec.rb
180
185
  $ abide puppet new util_class 'test_module::utils::test_new_util' -v 'testvar1=dude,testvar2=sweet'
181
186
  Created file /Users/the.dude/test_module/manifests/utils/test_new_util.pp
187
+ Created file /Users/the.dude/test_module/spec/classes/utils/test_new_util_spec.rb
182
188
  $ cat manifests/controls/test_new_control.pp
183
189
  # @api private
184
190
  class test_module::controls::test_new_control (
@@ -202,10 +208,22 @@ class test_module::utils::test_new_util (
202
208
 
203
209
  ```
204
210
 
211
+ **NOTE**: You can use two special prefixes on your template files to denote where the rspec test should be generated for that object.
212
+ If the prefix `c-` is used, the test will be generated in the `spec/classes` directory. If the prefix `d-` is used, the test will be generated in the `spec/defines` directory. For example, to create a template for a defined type, name the template something like this: `d-my_defined_type.pp.erb`.
213
+
205
214
  ### XCCDF Command Reference
206
215
 
207
216
  #### to_hiera
208
217
 
218
+ NOTE: When converting XCCDF files to Hiera, control names are sanitized. This means that some characters will be changed to ensure the resulting control names in the Hiera file are valid for both YAML and Puppet class names. Here's what gets changed:
219
+
220
+ * All letters are coverted to lower case
221
+ * The first and last characters of the control name is dropped if they are not letters (a-z)
222
+ * If a control name has a prefix of `l1_`, `l2_`, or `ng_`, that prefix is dropped
223
+ * Differentiation between profile level occurs outside of control names
224
+ * The characters `/` and `\` are deleted. This means that paths are smashed together
225
+ * Whitespace and the characters `(`, `)`, `.`, and `-` are substituted with underscores (`_`)
226
+
209
227
  * Required positional parameters:
210
228
  * `XCCDF_FILE` - Path to an XCCDF XML file
211
229
  * Options:
@@ -213,6 +231,15 @@ class test_module::utils::test_new_util (
213
231
  * `--out-file`, `-o` - A path to a file where you would like to save the generated Hiera
214
232
  * `--parent-key-prefix`, `-p` - Allows you to append a prefix to all top-level Hiera keys
215
233
 
234
+ ## Docker
235
+
236
+ A Dockerfile has been provided in this repo for convenience since Ruby environments can be painful to deal with. To abide_dev_utils with Docker:
237
+
238
+ * Build the Dockerfile: `docker build . -t abide_dev_utils --build-arg version=<semver>`
239
+ * Run the commands using the container: `docker run -it abide_dev_utils --help`
240
+ * The container declares a volume for external resources such as files. To use the volume, add the following flag to your `docker run` commands: `-v /path/to/my/files:/extvol`
241
+ * When using the volume, all paths should be absolute based on the root directory `/extvol`
242
+
216
243
  ## Development
217
244
 
218
245
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -41,6 +41,7 @@ Gem::Specification.new do |spec|
41
41
  # Dev dependencies
42
42
  spec.add_development_dependency 'bundler'
43
43
  spec.add_development_dependency 'rake'
44
+ spec.add_development_dependency 'console'
44
45
  spec.add_development_dependency 'github_changelog_generator'
45
46
  spec.add_development_dependency 'gem-release'
46
47
  spec.add_development_dependency 'rspec', '~> 3.10'
@@ -20,6 +20,7 @@ module Abide
20
20
  parser.main_options.version = AbideDevUtils::VERSION
21
21
  parser.main_options.banner = ROOT_CMD_BANNER
22
22
  parser.add_command(CmdParse::HelpCommand.new, default: true)
23
+ parser.add_command(CmdParse::VersionCommand.new(add_switches: true))
23
24
  parser.add_command(PuppetCommand.new)
24
25
  parser.add_command(XccdfCommand.new)
25
26
  parser.add_command(TestCommand.new)
@@ -87,6 +87,16 @@ module Abide
87
87
  '--vars [VARNAME=VALUE]',
88
88
  'Allows you to specify comma-separated variable names and values that will be converted into a hash that is available for you to use in your templates'
89
89
  ) { |v| @data[:vars] = v }
90
+ options.on(
91
+ '-S [PATH]',
92
+ '--spec-template [PATH]',
93
+ 'Path to an ERB template to use for rspec test generation instead of the default'
94
+ )
95
+ options.on(
96
+ '-f',
97
+ '--force',
98
+ 'Skips any prompts and executes the command'
99
+ ) { |_| @data[:force] = true }
90
100
  end
91
101
 
92
102
  def execute(type, name)
@@ -97,8 +107,7 @@ module Abide
97
107
  opts: @data,
98
108
  vars: @data.fetch(:vars, '').split(',').map { |i| i.split('=') }.to_h # makes the str a hash
99
109
  )
100
- result = builder.build
101
- Abide::CLI::OUTPUT.simple(result)
110
+ builder.build
102
111
  end
103
112
  end
104
113
  end
@@ -35,10 +35,10 @@ module Abide
35
35
  @litmus_im = [CMD_LIT_BASE, "'litmus:install_module'"]
36
36
  @litmus_ap = [CMD_LIT_BASE, "'litmus:acceptance:parallel'"]
37
37
  @litmus_td = [CMD_LIT_BASE, "'litmus:tear_down'"]
38
- validate_env_and_opts
39
38
  end
40
39
 
41
40
  def execute(suite)
41
+ validate_env_and_opts
42
42
  case suite.downcase
43
43
  when /^a[A-Za-z]*/
44
44
  run_command(@validate)
@@ -27,7 +27,12 @@ module Abide
27
27
  long_desc(CMD_LONG)
28
28
  options.on('-b [TYPE]', '--benchmark-type [TYPE]', 'XCCDF Benchmark type') { |b| @data[:type] = b }
29
29
  options.on('-o [FILE]', '--out-file [FILE]', 'Path to save file') { |f| @data[:file] = f }
30
- options.on('-p [PREFIX]', '--parent-key-prefix [PREFIX]', 'A prefix to append to the parent key') { |p| @data[:parent_key_prefix] = p }
30
+ options.on('-p [PREFIX]', '--parent-key-prefix [PREFIX]', 'A prefix to append to the parent key') do |p|
31
+ @data[:parent_key_prefix] = p
32
+ end
33
+ options.on('-N', '--number-fmt', 'Format Hiera control names based off of control number instead of name.') do
34
+ @data[:num] = true
35
+ end
31
36
  end
32
37
 
33
38
  def execute(xccdf_file)
@@ -40,8 +45,7 @@ module Abide
40
45
 
41
46
  def to_hiera(xccdf_file)
42
47
  xfile = AbideDevUtils::XCCDF.to_hiera(xccdf_file, @data)
43
- console = @data[:file].nil? ? true : false
44
- Abide::CLI::OUTPUT.yaml(xfile, console: console, file: @data[:file])
48
+ Abide::CLI::OUTPUT.yaml(xfile, console: @data[:file].nil?, file: @data[:file])
45
49
  end
46
50
  end
47
51
  end
@@ -8,5 +8,9 @@ module AbideDevUtils
8
8
  class XPathSearchError < GenericError
9
9
  @default = 'XPath seach failed to find anything at:'
10
10
  end
11
+
12
+ class StrategyInvalidError < GenericError
13
+ @default = 'Invalid strategy selected. Should be either \'name\' or \'num\''
14
+ end
11
15
  end
12
16
  end
@@ -9,7 +9,7 @@ module AbideDevUtils
9
9
  # the full namespace for all classes in that directory.
10
10
  # @param puppet_class_dir [String] path to a dir containing Puppet manifests
11
11
  # @return [String] The namespace for all classes in manifests in the dir
12
- def find_class_namespace(puppet_class_dir)
12
+ def self.find_class_namespace(puppet_class_dir)
13
13
  path = Pathname.new(puppet_class_dir)
14
14
  mod_root = nil
15
15
  ns_parts = []
@@ -34,7 +34,7 @@ module AbideDevUtils
34
34
  # metadata.json, if it exists, or by using the parent directory name.
35
35
  # @param pathname [Pathname] A Pathname object of the module's manifests dir
36
36
  # @return [String] The module's namespace root
37
- def find_mod_root(pathname)
37
+ def self.find_mod_root(pathname)
38
38
  metadata_file = nil
39
39
  pathname.entries.each do |e|
40
40
  metadata_file = "#{pathname}/metadata.json" if File.basename(e) == 'metadata.json'
@@ -52,7 +52,7 @@ module AbideDevUtils
52
52
 
53
53
  # @return [Array] An array of frozen arrays where each sub-array's
54
54
  # index 0 is class_name and index 1 is the full path to the file.
55
- def find_all_classes_and_paths(puppet_class_dir)
55
+ def self.find_all_classes_and_paths(puppet_class_dir)
56
56
  all_cap = []
57
57
  Dir.each_child(puppet_class_dir) do |c|
58
58
  path = "#{puppet_class_dir}/#{c}"
@@ -13,12 +13,14 @@ module AbideDevUtils
13
13
  def self.generate(puppet_class_dir, hiera_path, profile = nil)
14
14
  coverage = {}
15
15
  coverage['classes'] = {}
16
- all_cap = find_all_classes_and_paths(puppet_class_dir)
16
+ all_cap = AbideDevUtils::Ppt.find_all_classes_and_paths(puppet_class_dir)
17
17
  invalid_classes = find_invalid_classes(all_cap)
18
- valid_classes = all_cap.dup.transpose[0] - invalid_classes
18
+ valid_classes = find_valid_classes(all_cap, invalid_classes)
19
19
  coverage['classes']['invalid'] = invalid_classes
20
20
  coverage['classes']['valid'] = valid_classes
21
21
  hiera = YAML.safe_load(File.open(hiera_path))
22
+ profile&.gsub!(/^profile_/, '') unless profile.nil?
23
+
22
24
  matcher = profile.nil? ? /^profile_/ : /^profile_#{profile}/
23
25
  hiera.each do |k, v|
24
26
  key_base = k.split('::')[-1]
@@ -50,9 +52,13 @@ module AbideDevUtils
50
52
  out_hash
51
53
  end
52
54
 
53
- def self.find_valid_classes(all_cap)
55
+ def self.find_valid_classes(all_cap, invalid_classes)
54
56
  all_classes = all_cap.dup.transpose[0]
55
- all_classes - find_invalid_classes(all_cap)
57
+ return [] if all_classes.nil?
58
+
59
+ return all_classes - invalid_classes unless invalid_classes.nil?
60
+
61
+ all_classes
56
62
  end
57
63
 
58
64
  def self.find_invalid_classes(all_cap)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'erb'
4
4
  require 'pathname'
5
+ require 'abide_dev_utils/output'
5
6
  require 'abide_dev_utils/prompt'
6
7
  require 'abide_dev_utils/errors/ppt'
7
8
 
@@ -9,6 +10,10 @@ module AbideDevUtils
9
10
  module Ppt
10
11
  class NewObjectBuilder
11
12
  DEFAULT_EXT = '.pp'
13
+ VALID_EXT = /(\.pp|\.rb)\.erb$/.freeze
14
+ TMPL_PATTERN = /^[a-zA-Z][^\s]*\.erb$/.freeze
15
+ OBJ_PREFIX = /^(c-|d-)/.freeze
16
+ PREFIX_TEST_PATH = { 'c-' => 'classes', 'd-' => 'defines' }.freeze
12
17
 
13
18
  def initialize(obj_type, obj_name, opts: {}, vars: {})
14
19
  @obj_type = obj_type
@@ -17,25 +22,17 @@ module AbideDevUtils
17
22
  @vars = vars
18
23
  class_vars
19
24
  validate_class_vars
25
+ @tmpl_data = template_data(@opts.fetch(:tmpl_name, @obj_type))
20
26
  end
21
27
 
22
- attr_reader :obj_type, :obj_name, :tmpl_name, :root_dir, :tmpl_dir, :tmpl_path, :type_path_map, :obj_path, :vars
23
-
24
- def render
25
- ERB.new(File.read(@tmpl_path.to_s), 0, '<>-').result(binding)
26
- end
28
+ attr_reader :obj_type, :obj_name, :root_dir, :tmpl_dir, :obj_path, :vars, :tmpl_data
27
29
 
28
30
  def build
29
- continue = File.exist?(obj_path) ? AbideDevUtils::Prompt.yes_no('File exists, would you like to overwrite?') : true
30
- return "Not overwriting file #{obj_path}" unless continue
31
-
32
- dir, = Pathname.new(obj_path).split
33
- Pathname.new(dir).mkpath unless Dir.exist?(dir)
34
- content = render
35
- File.open(obj_path, 'w') { |f| f.write(render) } unless content.empty?
36
- raise AbideDevUtils::Errors::Ppt::FailedToCreateFileError, obj_path unless File.file?(obj_path)
37
-
38
- "Created file #{obj_path}"
31
+ force = @opts.fetch(:force, false)
32
+ obj_cont = force ? true : continue?(obj_path)
33
+ spec_cont = force ? true : continue?(@tmpl_data[:spec_path])
34
+ write_file(obj_path, @tmpl_data[:path]) if obj_cont
35
+ write_file(@tmpl_data[:spec_path], @spec_tmpl) if spec_cont
39
36
  end
40
37
 
41
38
  # If a method gets called on the Hiera object which is not defined,
@@ -59,42 +56,98 @@ module AbideDevUtils
59
56
 
60
57
  private
61
58
 
59
+ def continue?(path)
60
+ continue = if File.exist?(path)
61
+ AbideDevUtils::Prompt.yes_no('File exists, would you like to overwrite?')
62
+ else
63
+ true
64
+ end
65
+ AbideDevUtils::Output.simple("Not overwriting file #{path}") unless continue
66
+
67
+ continue
68
+ end
69
+
70
+ def write_file(path, tmpl_path)
71
+ dir, = Pathname.new(path).split
72
+ Pathname.new(dir).mkpath unless Dir.exist?(dir)
73
+ content = render(tmpl_path)
74
+ File.open(path, 'w') { |f| f.write(content) } unless content.empty?
75
+ raise AbideDevUtils::Errors::Ppt::FailedToCreateFileError, path unless File.file?(path)
76
+
77
+ AbideDevUtils::Output.simple("Created file #{path}")
78
+ end
79
+
80
+ def build_obj; end
81
+
62
82
  def class_vars
63
- @tmpl_name = @opts.fetch(:tmpl_name, "#{@obj_type}.erb")
64
83
  @root_dir = Pathname.new(@opts.fetch(:root_dir, Dir.pwd))
65
84
  @tmpl_dir = if @opts.fetch(:absolute_template_dir, false)
66
85
  @opts.fetch(:tmpl_dir)
67
86
  else
68
- "#{@opts.fetch(:root_dir, Dir.pwd)}/#{@opts.fetch(:tmpl_dir, 'object_templates')}"
87
+ "#{@root_dir}/#{@opts.fetch(:tmpl_dir, 'object_templates')}"
69
88
  end
70
- @tmpl_path = Pathname.new("#{@tmpl_dir}/#{@opts.fetch(:tmpl_name, "#{@obj_type}.erb")}")
71
- @type_path_map = @opts.fetch(:type_path_map, {})
72
89
  @obj_path = new_obj_path
90
+ @spec_tmpl = @opts.fetch(:spec_template, File.expand_path(File.join(__dir__, '../resources/generic_spec.erb')))
73
91
  end
74
92
 
75
93
  def validate_class_vars
76
94
  raise AbideDevUtils::Errors::PathNotDirectoryError, @root_dir unless Dir.exist? @root_dir
77
95
  raise AbideDevUtils::Errors::PathNotDirectoryError, @tmpl_dir unless Dir.exist? @tmpl_dir
78
- raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_path.to_s unless @tmpl_path.file?
79
96
  end
80
97
 
81
98
  def basename(obj_name)
82
99
  obj_name.split('::')[-1]
83
100
  end
84
101
 
85
- def new_obj_path
86
- if obj_type == 'class'
87
- obj_path_from_name
88
- else
89
- custom_obj_path
102
+ def prefix
103
+ pfx = basename.match(OBJ_PREFIX)
104
+ return pfx[1] unless pfx.empty?
105
+ end
106
+
107
+ def templates
108
+ return [] if Dir.entries(tmpl_dir).empty?
109
+
110
+ file_names = Dir.entries(tmpl_dir).select { |f| f.match?(TMPL_PATTERN) }
111
+ file_names.map { |i| File.join(tmpl_dir, i) }
112
+ end
113
+
114
+ def template_data(query)
115
+ raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_dir if Dir.entries(@tmpl_dir).empty?
116
+
117
+ data = {}
118
+ pattern = /#{Regexp.quote(query)}/
119
+ templates.each do |i|
120
+ pn = Pathname.new(i)
121
+ next unless pn.basename.to_s.match?(pattern)
122
+
123
+ data[:path] = pn.to_s
124
+ data[:fname] = pn.basename.to_s
90
125
  end
126
+ raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_dir unless data.key?(:fname)
127
+
128
+ data[:ext] = data[:fname].match?(VALID_EXT) ? data[:fname].match(VALID_EXT)[1] : '.pp'
129
+ data[:pfx] = data[:fname].match?(OBJ_PREFIX) ? data[:fname].match(OBJ_PREFIX)[1] : 'c-'
130
+ data[:spec_base] = PREFIX_TEST_PATH[data[:pfx]]
131
+ data[:obj_name] = normalize_obj_name(data.dup)
132
+ data[:spec_name] = "#{@obj_name.split('::')[-1]}_spec.rb"
133
+ data[:spec_path] = spec_path(data[:spec_base], data[:spec_name])
134
+ data
135
+ end
136
+
137
+ def normalize_obj_name(data)
138
+ new_name = data[:fname].slice(/^(?:#{Regexp.quote(data[:pfx])})?(?<name>[^\s.]+)(?:#{Regexp.quote(data[:ext])})?\.erb$/, 'name')
139
+ "#{new_name}#{data[:ext]}"
140
+ end
141
+
142
+ def render(path)
143
+ ERB.new(File.read(path), 0, '<>-').result(binding)
91
144
  end
92
145
 
93
146
  def namespace_format(name)
94
147
  name.split(':').reject(&:empty?).join('::')
95
148
  end
96
149
 
97
- def obj_path_from_name
150
+ def new_obj_path
98
151
  parts = @obj_name.split('::')[1..-2]
99
152
  parts.insert(0, 'manifests')
100
153
  parts.insert(-1, "#{basename(@obj_name)}#{DEFAULT_EXT}")
@@ -102,27 +155,13 @@ module AbideDevUtils
102
155
  path.to_s
103
156
  end
104
157
 
105
- def custom_obj_path
106
- map_val = type_path_map.fetch(@obj_type.to_sym, nil)
107
- return obj_path_from_name if map_val.nil?
108
-
109
- if map_val.respond_to?(:key?)
110
- custom_obj_path_from_hash(map_val, @obj_name)
111
- else
112
- abs_path = Pathname.new(map_val).absolute? ? map_val : "#{Dir.pwd}/#{map_val}"
113
- "#{abs_path}/#{basename(@obj_name)}#{DEFAULT_EXT}"
114
- end
115
- end
116
-
117
- def custom_obj_path_from_hash(map_val, obj_name)
118
- raise AbideDevUtils::Errors::Ppt::CustomObjPathKeyError, map_val unless map_val.key?(:path)
119
-
120
- abs_path = Pathname.new(map_val[:path]).absolute? ? map_val[:path] : "#{Dir.pwd}/#{map_val[:path]}"
121
- if map_val.key?(:extension)
122
- "#{abs_path}/#{basename(obj_name)}#{map_val[:extension]}"
123
- else
124
- "#{abs_path}/#{basename(obj_name)}#{DEFAULT_EXT}"
125
- end
158
+ def spec_path(base_dir, spec_name)
159
+ parts = @obj_name.split('::')[1..-2]
160
+ parts.insert(0, 'spec')
161
+ parts.insert(1, base_dir)
162
+ parts.insert(-1, spec_name)
163
+ path = @root_dir + Pathname.new(parts.join('/'))
164
+ path.to_s
126
165
  end
127
166
  end
128
167
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe '<%= @obj_name %>' do
6
+ on_supported_os.each do |os, os_facts|
7
+ context "on #{os}" do
8
+ let(:facts) { os_facts }
9
+
10
+ it { is_expected.to compile }
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbideDevUtils
4
- VERSION = "0.2.1"
4
+ VERSION = "0.4.1"
5
5
  end
@@ -15,7 +15,7 @@ module AbideDevUtils
15
15
  type = opts.fetch(:type, 'cis')
16
16
  case type.downcase
17
17
  when 'cis'
18
- AbideDevUtils::XCCDF::CIS::Hiera.new(xccdf_file, parent_key_prefix: opts[:parent_key_prefix])
18
+ AbideDevUtils::XCCDF::CIS::Hiera.new(xccdf_file, parent_key_prefix: opts[:parent_key_prefix], num: opts[:num])
19
19
  else
20
20
  AbideDevUtils::Output.simple("XCCDF type #{type} is unsupported!")
21
21
  end
@@ -13,6 +13,7 @@ module AbideDevUtils
13
13
  # @!attribute [r] yaml_title
14
14
  class Hiera
15
15
  CONTROL_PREFIX = /^[\d.]+_/.freeze
16
+ UNDERSCORED = /(\s|\(|\)|-|\.)/.freeze
16
17
  XPATHS = {
17
18
  benchmark: {
18
19
  all: 'xccdf:Benchmark',
@@ -34,13 +35,13 @@ module AbideDevUtils
34
35
  # @param parent_key_prefix [String] a string to be prepended to the
35
36
  # top-level key in the Hiera structure. Useful for namespacing
36
37
  # the top-level key.
37
- def initialize(xccdf_file, parent_key_prefix: nil)
38
+ def initialize(xccdf_file, parent_key_prefix: nil, num: false)
38
39
  @doc = parse(xccdf_file)
39
40
  @title = xpath(XPATHS[:benchmark][:title]).children.to_s
40
41
  @version = xpath(XPATHS[:benchmark][:version]).children.to_s
41
42
  @profiles = xpath(XPATHS[:profiles][:all])
42
43
  @parent_key = make_parent_key(@doc, parent_key_prefix)
43
- @hash = make_hash(@doc, @parent_key)
44
+ @hash = make_hash(@doc, @parent_key, num)
44
45
  end
45
46
 
46
47
  def yaml_title
@@ -89,15 +90,18 @@ module AbideDevUtils
89
90
 
90
91
  private
91
92
 
92
- attr_accessor :doc, :parent_key, :hash, :profiles
93
+ attr_accessor :doc, :hash, :parent_key, :profiles
93
94
 
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
94
98
  def parse(xccdf_file)
95
99
  raise AbideDevUtils::Errors::FileNotFoundError, xccdf_file unless File.file?(xccdf_file)
96
100
 
97
101
  Nokogiri.XML(File.open(xccdf_file))
98
102
  end
99
103
 
100
- def make_hash(doc, parent_key)
104
+ def make_hash(doc, parent_key, num)
101
105
  hash = { parent_key.to_sym => { title: @title, version: @version } }
102
106
  profiles = doc.xpath('xccdf:Benchmark/xccdf:Profile')
103
107
  profiles.each do |p|
@@ -105,7 +109,7 @@ module AbideDevUtils
105
109
  hash[parent_key.to_sym][title.to_sym] = []
106
110
  selects = p.xpath('./xccdf:select')
107
111
  selects.each do |s|
108
- hash[parent_key.to_sym][title.to_sym] << normalize_ctrl_name(s['idref'].to_s)
112
+ hash[parent_key.to_sym][title.to_sym] << normalize_ctrl_name(s['idref'].to_s, num)
109
113
  end
110
114
  end
111
115
  hash
@@ -113,11 +117,11 @@ module AbideDevUtils
113
117
 
114
118
  def normalize_str(str)
115
119
  nstr = str.downcase
116
- nstr.gsub!(/[^a-z]$/, '')
120
+ nstr.gsub!(/[^a-z0-9]$/, '')
117
121
  nstr.gsub!(/^[^a-z]/, '')
118
122
  nstr.gsub!(/^(l1_|l2_|ng_)/, '')
119
- nstr.delete!('-')
120
- nstr.gsub!(/(\s|\(|\))/, '_')
123
+ nstr.delete!('(/|\\)')
124
+ nstr.gsub!(UNDERSCORED, '_')
121
125
  nstr
122
126
  end
123
127
 
@@ -127,9 +131,21 @@ module AbideDevUtils
127
131
  prof_name
128
132
  end
129
133
 
130
- def normalize_ctrl_name(ctrl)
131
- new_ctrl = ctrl.split('_rule_')[-1].gsub(CONTROL_PREFIX, '')
132
- normalize_str(new_ctrl.gsub(/\./, '_'))
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}"
133
149
  end
134
150
 
135
151
  def make_parent_key(doc, prefix)
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.2.1
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heston Snodgrass
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-23 00:00:00.000000000 Z
11
+ date: 2021-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: console
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: github_changelog_generator
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -242,11 +256,13 @@ executables:
242
256
  extensions: []
243
257
  extra_rdoc_files: []
244
258
  files:
259
+ - ".dockerignore"
245
260
  - ".gitignore"
246
261
  - ".rspec"
247
262
  - ".rubocop.yml"
248
263
  - ".rubocop_todo.yml"
249
264
  - CHANGELOG.md
265
+ - Dockerfile
250
266
  - Gemfile
251
267
  - LICENSE.txt
252
268
  - README.md
@@ -278,6 +294,7 @@ files:
278
294
  - lib/abide_dev_utils/ppt/coverage.rb
279
295
  - lib/abide_dev_utils/ppt/new_obj.rb
280
296
  - lib/abide_dev_utils/prompt.rb
297
+ - lib/abide_dev_utils/resources/generic_spec.erb
281
298
  - lib/abide_dev_utils/utils/general.rb
282
299
  - lib/abide_dev_utils/validate.rb
283
300
  - lib/abide_dev_utils/version.rb