abide-data-processor 0.2.1 → 1.1.0

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: 6ac1b297c18c221a7ed68588b5f19e9cd5dc5b62b97a745d6041acabbb3867ff
4
- data.tar.gz: 340fc29d78ef0014e94ccdf1a32b7edadc8b2e9653aa1b69a313d785444236cd
3
+ metadata.gz: 0fb3fd8f80e90db869d7f0230ecead72fe3fa500c0c6046aad010b6fea953cbd
4
+ data.tar.gz: d44ec5bc9e68724c0f0cae4a2acfb4d8fd39fd59118774bceb3ac47f8e36b625
5
5
  SHA512:
6
- metadata.gz: 718c8e4a751a56e17fd1f170ab41da6e677aa91b5c6cec1e0745ec415bcb25b5d55215b5175107d0503ea819758a23e73b34afbd31a01a96417fe114a44a178b
7
- data.tar.gz: cd9898b06b1e4296e4e7b4ec4405852639dac5aa2365ec0ecb2fb0d28559078dc7f3ca1365af11af42c7424913ccc70faf6d7b0953d7530fc06e3282152787df
6
+ metadata.gz: c7ef4cbcc7e1862f2a6ecf3e9fb33df5b972de5b2fcbe1ee3f2297478510fdaa7666995a3065d139bbb087c3beb167a26ffb92e8d0db9572341eb10753c391ce
7
+ data.tar.gz: 411bc8d6084ebac6345cc4625160d689e3d277d3ff6c892b048bf787c264f2665c53e8b8b8761b739b9cfde8e2eb2c06ed11d5fdfc34869e295d96dfe83e85d7
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- abide-data-processor (0.2.1)
5
- puppet (>= 6.23)
4
+ abide-data-processor (1.1.0)
5
+ deep_merge (~> 1.2)
6
+ rgl (~> 0.5)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
@@ -39,11 +40,8 @@ GEM
39
40
  concurrent-ruby (1.1.9)
40
41
  console (1.13.1)
41
42
  fiber-local
42
- deep_merge (1.2.1)
43
+ deep_merge (1.2.2)
43
44
  diff-lcs (1.4.4)
44
- facter (4.2.5)
45
- hocon (~> 1.3)
46
- thor (>= 1.0.1, < 2.0)
47
45
  faraday (1.8.0)
48
46
  faraday-em_http (~> 1.0)
49
47
  faraday-em_synchrony (~> 1.0)
@@ -68,6 +66,7 @@ GEM
68
66
  fast_gettext (1.8.0)
69
67
  fiber-local (1.0.0)
70
68
  gem-release (2.2.2)
69
+ generator (0.0.1)
71
70
  github_changelog_generator (1.16.4)
72
71
  activesupport
73
72
  async (>= 1.25.0)
@@ -77,11 +76,9 @@ GEM
77
76
  octokit (~> 4.6)
78
77
  rainbow (>= 2.2.1)
79
78
  rake (>= 10.0)
80
- hiera (3.7.0)
81
- hocon (1.3.1)
82
79
  i18n (1.8.10)
83
80
  concurrent-ruby (~> 1.0)
84
- locale (2.1.3)
81
+ lazy_priority_queue (0.1.1)
85
82
  method_source (1.0.0)
86
83
  minitest (5.14.4)
87
84
  multi_json (1.15.0)
@@ -107,23 +104,13 @@ GEM
107
104
  byebug (~> 11.0)
108
105
  pry (~> 0.10)
109
106
  public_suffix (4.0.6)
110
- puppet (7.12.1)
111
- concurrent-ruby (~> 1.0)
112
- deep_merge (~> 1.0)
113
- facter (> 2.0.1, < 5)
114
- fast_gettext (~> 1.1)
115
- hiera (>= 3.2.1, < 4)
116
- locale (~> 2.1)
117
- multi_json (~> 1.10)
118
- puppet-resource_api (~> 1.5)
119
- scanf (~> 1.0)
120
- semantic_puppet (~> 1.0)
121
- puppet-resource_api (1.8.14)
122
- hocon (>= 1.0)
123
107
  rainbow (3.0.0)
124
108
  rake (12.3.3)
125
109
  regexp_parser (2.1.1)
126
110
  rexml (3.2.5)
111
+ rgl (0.5.7)
112
+ lazy_priority_queue (~> 0.1.0)
113
+ stream (~> 0.5.3)
127
114
  rspec (3.10.0)
128
115
  rspec-core (~> 3.10.0)
129
116
  rspec-expectations (~> 3.10.0)
@@ -160,9 +147,8 @@ GEM
160
147
  sawyer (0.8.2)
161
148
  addressable (>= 2.3.5)
162
149
  faraday (> 0.8, < 2.0)
163
- scanf (1.0.0)
164
- semantic_puppet (1.0.4)
165
- thor (1.1.0)
150
+ stream (0.5.3)
151
+ generator
166
152
  timers (4.3.3)
167
153
  tzinfo (2.0.4)
168
154
  concurrent-ruby (~> 1.0)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'lib/abide-data-processor/version'
2
4
 
3
5
  Gem::Specification.new do |spec|
@@ -28,8 +30,8 @@ Gem::Specification.new do |spec|
28
30
  spec.require_paths = ["lib"]
29
31
 
30
32
  # Prod dependencies
31
- # I'm not too sure about this version
32
- spec.add_dependency 'puppet', '>= 6.23'
33
+ spec.add_dependency 'deep_merge', '~> 1.2'
34
+ spec.add_dependency 'rgl', '~> 0.5'
33
35
 
34
36
  # Dev dependencies
35
37
  spec.add_development_dependency 'bundler'
@@ -0,0 +1,733 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'deep_merge'
4
+ require 'rgl/adjacency'
5
+ require 'rgl/topsort'
6
+ require 'rgl/traversal'
7
+ require 'set'
8
+
9
+ module AbideDataProcessor
10
+ # This module contains the logic for creating resource data from Hiera data.
11
+ module Parser
12
+ MAP_TYPES = %w[hiera_title hiera_title_num number title].freeze
13
+ METAPARAMS = %w[dependent before require subscribe notify].freeze
14
+
15
+ # Parse Hiera data into a resource data Hash
16
+ # @param hiera_data [Hash] Hiera data to parse
17
+ # @param control_maps [Array] Control maps to use
18
+ # @return [Hash] Parsed resource data
19
+ def self.parse(hiera_data, control_maps, control_configs: {}, ignore: [], only: [])
20
+ ResourceDataParser.new(
21
+ hiera_data,
22
+ control_maps,
23
+ control_configs: control_configs,
24
+ ignore: ignore,
25
+ only: only
26
+ ).parse
27
+ end
28
+
29
+ # This module handles data validation for the CIS data parser
30
+ module Validation
31
+ # Validates the hiera_data parameter and either raises an ArgumentError or returns the hiera_data parameter.
32
+ # @param hiera_data [Hash] The Hiera data to be parsed.
33
+ # @return [Hash] The Hiera data to be parsed.
34
+ # @raise [ArgumentError] If the hiera_data parameter is not a non-empty Hash.
35
+ def validate_hiera_data(hiera_data)
36
+ return hiera_data if hiera_data == :no_params
37
+
38
+ unless not_nil_or_empty?(hiera_data) && hiera_data.is_a?(Hash)
39
+ raise ArgumentError, 'hiera_data must be a non-nil, non-empty Hash'
40
+ end
41
+
42
+ hiera_data
43
+ end
44
+
45
+ # Validates the control_maps parameter and either raises an ArgumentError or returns the control_maps parameter.
46
+ # @param control_maps [Array] The control maps to be parsed.
47
+ # @return [Array] The control maps to be parsed.
48
+ # @raise [ArgumentError] If the control_maps parameter is not a non-empty Array of Hashes.
49
+ def validate_control_maps(control_maps)
50
+ unless not_nil_or_empty?(control_maps) && array_of_hashes?(control_maps)
51
+ raise ArgumentError, 'control_maps must be a non-nil, non-empty Array of Hashes'
52
+ end
53
+
54
+ control_maps
55
+ end
56
+
57
+ # Checks if the value is not nil or empty.
58
+ # @param value [Any] The value to be checked.
59
+ # @return [Boolean] True if the value is not nil or empty, false otherwise.
60
+ def not_nil_or_empty?(value)
61
+ !value.nil? && !value.empty?
62
+ end
63
+
64
+ # Checks if the value is an Array of Hashes.
65
+ # @param value [Any] The value to be checked.
66
+ # @return [Boolean] True if the value is an Array of Hashes, false otherwise.
67
+ def array_of_hashes?(value)
68
+ value.is_a?(Array) && value.all? { |h| h.is_a?(Hash) }
69
+ end
70
+ end
71
+
72
+ # Parser class for resource Hiera data.
73
+ # rubocop:disable Metrics/ClassLength
74
+ class ResourceDataParser
75
+ include Validation
76
+ attr_reader :hiera_data, :control_maps, :resources
77
+
78
+ def initialize(hiera_data, control_maps, control_configs: {}, ignore: [], only: [])
79
+ @hiera_data = validate_hiera_data(hiera_data)
80
+ @control_maps = validate_control_maps(control_maps)
81
+ @control_configs = control_configs
82
+ @ignore = ignore
83
+ @only = only
84
+ @resources = RGL::DirectedAdjacencyGraph.new
85
+ @controls = Set.new
86
+ @filtered = Set.new
87
+ @dependent = {}
88
+ end
89
+
90
+ # Parse the Hiera data into a Hash used by Puppet to create the resources.
91
+ # The way this works is by first creating a DAG and adding all resources to the graph
92
+ # as vertices, with an edge for each resource pointing from a dummy node, :root, to the
93
+ # resource. We then add edges to the graph based on the `before_me` and `after_me` lists
94
+ # of each resource and remove the :root-connected edges for each resource that has a
95
+ # `before_me` list, and remove the :root-connected edges for each resource in a `after_me`
96
+ # list. Finally, we sort the graph into an Array populated with a single Hash of ordered
97
+ # resources and return that Hash.
98
+ # @return [Array] A sorted array of resource hashes.
99
+ # rubocop:disable Metrics/MethodLength
100
+ def parse
101
+ @hiera_data.each do |name, data|
102
+ resource = AbideDataProcessor::Parser.new_resource(name, data, @control_maps)
103
+ add_control_names(resource)
104
+ add_dependent_mapping(resource) # Map any controls this resource depends on
105
+ @resources.add_vertex(resource) # Add all the resources to the graph
106
+ @resources.add_edge(:root, resource) # Establish the root -> resource edges
107
+ add_edge_ordering(resource) # Add resource ordering edges
108
+ end
109
+ # If the resource should be filtered (i.e. only or ignore), remove it from the graph.
110
+ filter_resources!
111
+ # Verify that all dependent resources are in the graph, remove them if not.
112
+ remove_unsatisfied_dependents!
113
+ # Sort the graph and return the array of ordered resource hashes
114
+ sort_resources.map do |r|
115
+ r.add_control_configs(@control_configs)
116
+ resource_data(r)
117
+ end
118
+ end
119
+ # rubocop:enable Metrics/MethodLength
120
+
121
+ private
122
+
123
+ # Adds control neames for the given resource to the @controls set.
124
+ # @param resource [Resource] The resource to add control names for.
125
+ def add_control_names(resource)
126
+ return unless resource.controls
127
+
128
+ @controls.merge(resource.control_names).flatten!
129
+ @controls.merge(resource.mapped_control_names).flatten!
130
+ end
131
+
132
+ # Calls the given Resource's `resource_data` method, filters out any resource references
133
+ # in metaparameters that references filtered resources, and returns the result.
134
+ # @param resource [Resource] The resource to be filtered.
135
+ # @return [Hash] The filtered resource data.
136
+ # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
137
+ def resource_data(resource)
138
+ data = resource.resource_data.dup
139
+ data.each do |_, res_data|
140
+ res_data.each do |_, params|
141
+ METAPARAMS.each do |param|
142
+ next unless params.key?(param)
143
+
144
+ params[param].reject! { |r| @filtered.to_a.map(&:resource_reference).include?(r) }
145
+ params.delete(param) if params[param].empty?
146
+ end
147
+ end
148
+ end
149
+ data
150
+ end
151
+ # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
152
+
153
+ # Removes Resources from the graph if they should be filtered.
154
+ def filter_resources!
155
+ @resources.depth_first_search do |resource|
156
+ next if resource == :root
157
+
158
+ if filter_resource?(resource)
159
+ @resources.remove_vertex(resource) # Remove resource's graph vertex
160
+ @filtered.add(resource) # Add resource to filtered set
161
+ end
162
+ end
163
+ end
164
+
165
+ # Checks whether the resource should be filtered out based on the ignore and only lists.
166
+ # @param resource [Resource] The resource to check.
167
+ # @return [Boolean] True if the resource should be filtered out, false otherwise.
168
+ def filter_resource?(resource)
169
+ return true if control_in?(resource, @ignore)
170
+ return true unless @only.empty? || control_in?(resource, @only)
171
+
172
+ false
173
+ end
174
+
175
+ # Adds a mapping for a dependent control and the resources that depend on it.
176
+ # @param resource [Resource] The resource to add the mapping for.
177
+ def add_dependent_mapping(resource)
178
+ return unless resource.dependent
179
+
180
+ resource.dependent.each do |control_name|
181
+ @dependent[control_name] = [] unless @dependent.key?(control_name)
182
+ @dependent[control_name] << resource
183
+ end
184
+ end
185
+
186
+ # Checks the dependent controls against all controls after filtered resource controls are removed
187
+ # and removes any dependent resources that are not satisfied.
188
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
189
+ def remove_unsatisfied_dependents!
190
+ dependent_set = Set.new(@dependent.keys)
191
+ filtered_set = Set.new(@filtered.to_a.map(&:control_names)).flatten
192
+ filtered_mapped = Set.new(@filtered.to_a.map(&:mapped_control_names)).flatten
193
+
194
+ all_controls = @controls.subtract(filtered_set + filtered_mapped)
195
+ return if dependent_set.proper_subset?(all_controls) # All dependent controls exist in the graph
196
+
197
+ (dependent_set - all_controls).each do |control_name|
198
+ @dependent[control_name].each do |resource|
199
+ @resources.remove_vertex(resource)
200
+ @filtered.add(resource)
201
+ end
202
+ end
203
+ end
204
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
205
+
206
+ # Gets all verticies in the graph that have the associated control
207
+ # @param control_name [String] The name of the control to check.
208
+ # @return [Array] The verticies that have the associated control.
209
+ def collect_verticies_by_control(control_name)
210
+ @resources.vertices.select { |r| r.control?(control_name) }
211
+ end
212
+
213
+ # Checks if the given Resource has a control in the given list.
214
+ # @param resource [Resource] The resource to check.
215
+ # @param control_list [Array] The list of controls to check against.
216
+ # @return [Boolean] True if the resource is in the control list, false otherwise.
217
+ def control_in?(resource, control_list)
218
+ return false if control_list.empty?
219
+
220
+ control_list.each do |ignored_control|
221
+ return true if resource.control?(ignored_control)
222
+ end
223
+ false
224
+ end
225
+
226
+ # Adds edges to the graph based on the given Resource's `before_me` and `after_me` lists.
227
+ # @param resource [Resource] The Resource to add edges for.
228
+ def add_edge_ordering(resource)
229
+ add_before_me_edge(resource)
230
+ add_after_me_edge(resource)
231
+ end
232
+
233
+ # Adds edges to the graph based on the given Resource's `before_me` list.
234
+ # @param resource [Resource] The Resource to add edges for.
235
+ def add_before_me_edge(resource)
236
+ resource.before_me.flatten.each do |before|
237
+ next unless before # Skip if this `before` is nil, empty, or falsy (e.g. false, 0, etc.)
238
+ next if before.equal?(resource) # Skip if this `before` is the same as the current resource
239
+
240
+ # We remove the edge from root to this resource if it exists because this resource is no longer
241
+ # attached to the root of the graph as it has other resources before it.
242
+ @resources.remove_edge(:root, resource) if @resources.has_edge?(:root, resource)
243
+ # Add the edge from the before resource to this resource
244
+ @resources.add_edge(before, resource) unless @resources.has_edge?(before, resource)
245
+ end
246
+ end
247
+
248
+ # Adds edges to the graph based on the given Resource's `after_me` list.
249
+ # @param resource [Resource] The Resource to add edges for.
250
+ def add_after_me_edge(resource)
251
+ resource.after_me.flatten.each do |after|
252
+ next unless after # Skip if this `after` is nil, empty, or falsy (e.g. false, 0, etc.)
253
+ next if after.equal?(resource) # Skip if this `after` is the same as the current resource
254
+
255
+ # We remove the edge from root to the `after` resource if it exists because the `after` resource
256
+ # is no longer attached to the root of the graph as this resources comes before it.
257
+ @resources.remove_edge(:root, after) if @resources.has_edge?(:root, after)
258
+ # Add the edge from this resource to the after resource
259
+ @resources.add_edge(resource, after) unless @resources.has_edge?(resource, after)
260
+ end
261
+ end
262
+
263
+ # This method validates that the resources graph has no cycles and then returns a topological sort of the graph
264
+ # as an Array of Resource objects.
265
+ # @return [Array] The sorted Resources.
266
+ # @raise [ArgumentError] If the resources graph has any cycles.
267
+ def sort_resources
268
+ raise "Resource cyclic ordering detected: #{@resources.cycles}" unless @resources.acyclic?
269
+
270
+ # We call topsort on the graph to get the sorted list of resources, convert it to an array, and
271
+ # remove the root node.
272
+ @resources.topsort_iterator.to_a.flatten.uniq.reject { |r| r == :root }
273
+ end
274
+ end
275
+ # rubocop:enable Metrics/ClassLength
276
+
277
+ # This class holds all base attributes and methods for every syntax object.
278
+ # rubocop:disable Metrics/ClassLength
279
+ class ProcessorObject
280
+ include Validation
281
+ attr_reader :name, *METAPARAMS.map(&:to_sym)
282
+
283
+ def initialize(name, data, control_maps)
284
+ @name = name
285
+ @data = validate_hiera_data(data)
286
+ @control_maps = validate_control_maps(control_maps)
287
+ @dependent = Set.new
288
+ initialize_metaparams(@data, @control_maps)
289
+ end
290
+
291
+ # Determines if the name supplied is equal to the name of the object.
292
+ # This is overridden by subclasses to implement name mapped matches.
293
+ # @param name [String] The name to be compared to the object's name.
294
+ # @return [Boolean] True if the name is equal to the object's name, false otherwise.
295
+ def name?(_name)
296
+ raise NotImplementedError, 'This method must be implemented by a subclass'
297
+ end
298
+
299
+ # Abstract method to be implemented by subclasses.
300
+ # Returns a representation of this object as a Hash usable by Puppet's
301
+ # create_resources function.
302
+ def resource_data
303
+ raise NotImplementedError, 'This method must be implemented by a subclass'
304
+ end
305
+
306
+ # Returns any Resource objects that must be ordered before this object.
307
+ # @return [Array] The Resources that must be ordered before this object.
308
+ def before_me
309
+ defined?(@before_me) ? @before_me : initialize_before_me
310
+ end
311
+
312
+ # Returns any Resource objects that must be ordered after this object.
313
+ # @return [Array] The Resources that must be ordered after this object.
314
+ def after_me
315
+ defined?(@after_me) ? @after_me : initialize_after_me
316
+ end
317
+
318
+ # Converts this object to a String.
319
+ # @return [String] The class and name of this object.
320
+ def to_s
321
+ "#{self.class.name}('#{@name}')"
322
+ end
323
+
324
+ # Gives a more detailed String representation of this object.
325
+ # @return [String] The class, object id, and name of this object.
326
+ def inspect
327
+ "#<#{self.class.name}:#{object_id} '#{@name}'>"
328
+ end
329
+
330
+ private
331
+
332
+ # This method normalizes an array of Resources, or anything really, by
333
+ # flattening it, removing any nil values, removing any duplicates, and
334
+ # rejecting any empty objects if they respond to `empty?`. It then
335
+ # returns the new array.
336
+ # @param resources [Array] The array of Resources to be normalized.
337
+ # @return [Array] The normalized array of Resources.
338
+ def normalize_resource_array(array)
339
+ array.flatten.compact.uniq.reject { |r| r.empty? if r.respond_to?(:empty?) }
340
+ end
341
+
342
+ # This method normalizes an array of Resources, or anything really, by
343
+ # flattening it, removing any nil values, removing any duplicates, and
344
+ # rejecting any empty objects if they respond to `empty?`. It does this
345
+ # in place, directly modifying the input array.
346
+ # @param resources [Array] The array of Resources to be normalized.
347
+ def normalize_resource_array!(array)
348
+ array.flatten!
349
+ array.compact!
350
+ array.uniq!
351
+ array.reject! { |r| r.empty? if r.respond_to?(:empty?) }
352
+ end
353
+
354
+ # Initializes any relevant metaparameters based on the data supplied.
355
+ # @param data [Hash] The resource data to be parsed.
356
+ # @param control_maps [Array] The control maps to be used.
357
+ def initialize_metaparams(data, control_maps)
358
+ METAPARAMS.each do |param|
359
+ metaparam_data = data == :no_params ? {} : data[param]
360
+ raw_mdata = data == :no_params ? {} : data
361
+ value, bool_value = parse_metaparam(metaparam_data, control_maps)
362
+ raw_value, raw_bool_value = parse_raw_metaparam(raw_mdata, param)
363
+ set_metaparam_instance_vars(param, value, raw_value)
364
+ define_metaparam_bool_methods(param, raw_bool_value, bool_value)
365
+ end
366
+ end
367
+
368
+ # Initilizes the before_me instance variable with a list of Resources
369
+ # that must be ordered before this object.
370
+ # @return [Array] The list of Resources that must be ordered before this object.
371
+ def initialize_before_me
372
+ ctrls = @controls ? calculate_ordered_controls('before_me') : []
373
+ this = calculate_self_ordering('require', 'subscribe')
374
+ @before_me = normalize_resource_array(this.concat(ctrls))
375
+ @before_me
376
+ end
377
+
378
+ # Initializes the after_me instance variable with a list of Resources
379
+ # that must be ordered after this object.
380
+ # @return [Array] The list of Resources that must be ordered after this object.
381
+ def initialize_after_me
382
+ ctrls = @controls ? calculate_ordered_controls('after_me') : []
383
+ this = calculate_self_ordering('notify', 'subscribe')
384
+ @after_me = normalize_resource_array(this.concat(ctrls))
385
+ @after_me
386
+ end
387
+
388
+ # This method adds the supplied Resource to the inverse ordering list of this
389
+ # object based on the supplied metaparameter. This method is never directly used
390
+ # by an object on itself, rather it is called by other objects when they establish
391
+ # ordering relationships with this object. Because this method is private, other
392
+ # objects must use `send` to call it.
393
+ # @param metaparam [String] The metaparameter to inverse
394
+ # @param resource [Resource] The Resource to be added to the inverse ordering list.
395
+ def add_inverse_ordered_resource(metaparam, resource)
396
+ if %w[require subscribe].include?(metaparam)
397
+ add_after_me(resource)
398
+ elsif %w[before notify].include?(metaparam)
399
+ add_before_me(resource)
400
+ end
401
+ end
402
+
403
+ # This method calculates the ordering of this object based on the
404
+ # ordering of the controls that are defined for this object.
405
+ # @param order_function [String] The function to use to calculate the ordering (before_me or after_me).
406
+ # @return [Array] The list of Resources gathered from the order function return of all controls.
407
+ def calculate_ordered_controls(order_function)
408
+ @controls.each_with_object([]) do |control, ary|
409
+ ary << control.send(order_function.to_sym)
410
+ end
411
+ end
412
+
413
+ # This method calculates the ordering of this object based on the
414
+ # the supplied metaparameters. This function is used with "like pairs"
415
+ # of metaparameters, such as "require" and "subscribe".
416
+ # @param metaparameters [Array] The metaparameters to use to calculate the ordering.
417
+ # @return [Array] The list of Resources gathered from this object's metaparameters.
418
+ def calculate_self_ordering(*metaparams)
419
+ ordered = metaparams.each_with_object([]) do |mparam, ary|
420
+ next unless send("#{mparam}?".to_sym)
421
+
422
+ ordered_resources = send(mparam.to_sym)
423
+ ordered_resources.each { |r| r.send(:add_inverse_ordered_resource, mparam, self) }
424
+
425
+ ary << ordered_resources
426
+ end
427
+ normalize_resource_array(ordered)
428
+ end
429
+
430
+ # Returns appropriate values for instance variables of the given metaparam based off the supplied value.
431
+ # @param value [Array] The metaparameter declaration value from Hiera.
432
+ # @param control_maps [Array] The relevant control maps used in Resource creation.
433
+ # @return [Array] Values for the instance variables of the given metaparam. The order of the values
434
+ # is: Resource collection value, boolean value.
435
+ def parse_metaparam(value, control_maps)
436
+ return [nil, false] unless not_nil_or_empty?(value)
437
+
438
+ return parse_dependent_param(value) if value.is_a?(Array)
439
+
440
+ objects = value.each_with_object([]) do |(k, v), a|
441
+ a << AbideDataProcessor::Parser.new_resource(k, v, control_maps)
442
+ end
443
+ [normalize_resource_array(objects), !objects.empty?]
444
+ end
445
+
446
+ # Adds a each dependent control from a list of dependent controls to the
447
+ # @dependent instance variable.
448
+ # @param value [Array] The dependent controls to be added to the @dependent instance variable.
449
+ def parse_dependent_param(value)
450
+ value.each { |x| @dependent.add(x) }
451
+ end
452
+
453
+ # Returns appropriate raw value for instance variables of the given metaparam based off the supplied value.
454
+ # The raw value is the text values for the metaparameter declaration supplied via the resource data.
455
+ # @param data [Hash] The resource data to be parsed.
456
+ # @param param [String] The metaparameter to be parsed.
457
+ # @return [Array] Values for the instance variables of the given metaparam. The order of the values
458
+ # is: raw value, boolean raw value.
459
+ def parse_raw_metaparam(data, param)
460
+ raw_value = data.fetch(param, nil)
461
+ [raw_value, (!raw_value.nil? && !raw_value.empty?)]
462
+ end
463
+
464
+ # Sets the instance variables of the given metaparam based off the supplied values.
465
+ # @param param [String] The metaparameter to be set.
466
+ # @param value [Array] The Resource value to be set.
467
+ # @param raw_value [Array] The raw value to be set.
468
+ def set_metaparam_instance_vars(param, value, raw_value)
469
+ instance_variable_set("@#{param}", value)
470
+ instance_variable_set("@#{param}_raw", raw_value)
471
+ end
472
+
473
+ # Defines singleton methods for this instance of ProcessorObject that are used to determine
474
+ # if the metaparameter is set.
475
+ # @param param [String] The metaparameter that will have boolean methods defined.
476
+ # @param raw_value [Boolean] The boolean value for the <metaparam>_raw? method.
477
+ # @param value [Boolean] The boolean value for the <metaparam>? method.
478
+ def define_metaparam_bool_methods(param, raw_value, value)
479
+ define_singleton_method("#{param}_raw?".to_sym) { raw_value }
480
+ define_singleton_method("#{param}?".to_sym) { value }
481
+ end
482
+
483
+ # Returns the mapped names for the given control identifier.
484
+ # @param identifier [String] The control identifier to be mapped.
485
+ # @return [Array] The mapped names for the given control identifier.
486
+ def find_mapped_names(identifier)
487
+ @control_maps.each do |control_map|
488
+ return control_map[identifier] if control_map.include?(identifier)
489
+ end
490
+ []
491
+ end
492
+ end
493
+
494
+ # This class represents a single control in the data structure.
495
+ class Control < ProcessorObject
496
+ attr_reader :mapped_names, :params, :param_names, :resource_params
497
+
498
+ def initialize(name, data, control_maps)
499
+ super(name, data, control_maps)
500
+ @mapped_names = find_mapped_names(@name)
501
+ @params = @data == :no_params ? {} : @data
502
+ @resource_params = @data == :no_params ? {} : @data.reject { |k, _v| METAPARAMS.include?(k) }
503
+ @param_names = @data == :no_params ? Set.new : Set.new(@params.keys)
504
+ end
505
+
506
+ def name?(name)
507
+ @name == name || @mapped_names.include?(name)
508
+ end
509
+
510
+ def param?(param_name)
511
+ @param_names.include?(param_name)
512
+ end
513
+
514
+ def param(param_name)
515
+ @params[param_name]
516
+ end
517
+
518
+ def resource_data
519
+ @resource_params
520
+ end
521
+ end
522
+ # rubocop:enable Metrics/ClassLength
523
+
524
+ # This class represents a single Puppet resource (class, defined type, etc.)
525
+ class Resource < ProcessorObject
526
+ attr_reader :name, :type, :controls, :control_names, :mapped_control_names
527
+
528
+ def initialize(name, data, control_maps)
529
+ super(name, data, control_maps)
530
+ @type = @data['type']
531
+ @controls = create_control_classes(@data['controls'])
532
+ @control_names = Set.new(@controls.map(&:name)).flatten
533
+ @mapped_control_names = Set.new(@controls.map(&:mapped_names).flatten).flatten
534
+ initialize_control_metaparams
535
+ end
536
+
537
+ # Adds overriding parameter values to controls in this resource
538
+ # if this resource has a matching control.
539
+ # @param data [Hash] The resource data to be parsed.
540
+ def add_control_configs(control_configs)
541
+ control_configs.each do |control, configs|
542
+ next unless control?(control)
543
+
544
+ @controls.each do |control_class|
545
+ next unless control_class.name?(control)
546
+
547
+ control_class.resource_params.deep_merge!(configs)
548
+ end
549
+ end
550
+ end
551
+
552
+ # Outputs a representation of this object as a Hash usable by Puppet's
553
+ # create_resources function.
554
+ def resource_data
555
+ control_params = control_parameters
556
+ METAPARAMS.each do |mparam|
557
+ next if mparam == 'dependent'
558
+
559
+ refs = resource_references(mparam, control_params)
560
+ next if refs.nil?
561
+
562
+ control_params[mparam] = refs
563
+ end
564
+ { @type => { @name => control_params } }
565
+ end
566
+
567
+ # This method returns a string representation of this Resource in the resource reference
568
+ # format used by Puppet.
569
+ # @return [String] A string representation of this Resource in the resource reference format.
570
+ def resource_reference
571
+ type_ref = @type.split('::').map(&:capitalize).join('::')
572
+ "#{type_ref}['#{@name}']"
573
+ end
574
+
575
+ # This method checks if this Resource contains the given control.
576
+ # @param control [String] The control to be checked.
577
+ # @return [Boolean] True if this Resource contains the given control, false otherwise.
578
+ def control?(control_name)
579
+ @control_names.include?(control_name) || @mapped_control_names.include?(control_name)
580
+ end
581
+
582
+ # This method checks if this Resource contains the given parameter.
583
+ # @param param_name [String] The parameter to be checked.
584
+ # @return [Boolean] True if this Resource contains the given parameter, false otherwise.
585
+ def param?(param_name)
586
+ if param_name.respond_to?(:each)
587
+ param_name.all? { |name| param?(name) }
588
+ else
589
+ @param_names.include?(param_name)
590
+ end
591
+ end
592
+
593
+ private
594
+
595
+ # This method gathers the resource data for each control this Resource contains.
596
+ # @return [Hash] The resource data for each control this Resource contains.
597
+ def control_parameters
598
+ @controls.each_with_object({}) do |control, h|
599
+ h.deep_merge(control.resource_data)
600
+ end
601
+ end
602
+
603
+ # This method gets the resource references for the given metaparameter and control parameters.
604
+ # @param mparam [String] The metaparameter to be checked.
605
+ # @param control_params [Hash] The control parameters to be checked.
606
+ # @return [Array] The resource references for the given metaparameter and control parameters.
607
+ # @return [nil] If the given metaparameter is not set on this Resource.
608
+ def resource_references(mparam, control_params)
609
+ # rubocop:disable Style/RedundantSelf
610
+ # we use self here because `require` is a metaparam and we don't want to
611
+ # call `Kernel#require` accidentally.
612
+ this_mparam = self.send(mparam.to_sym)
613
+ # rubocop:enable Style/RedundantSelf
614
+ return if this_mparam.nil? || this_mparam.compact.empty?
615
+
616
+ if control_params.key?(mparam)
617
+ control_params[mparam].concat(this_mparam.map(&:resource_reference))
618
+ else
619
+ this_mparam.map(&:resource_reference)
620
+ end
621
+ end
622
+
623
+ # Adds a Resource to the before_me list.
624
+ # @param resource [Resource] The Resource to be added to the before_me list.
625
+ def add_before_me(resource)
626
+ before_me.append(resource)
627
+ end
628
+
629
+ # Adds a Resource to the after_me list.
630
+ # @param resource [Resource] The Resource to be added to the after_me list.
631
+ def add_after_me(resource)
632
+ after_me.append(resource)
633
+ end
634
+
635
+ # Initializes all metaparameter values of all controls that this Resource contains
636
+ # and brings those values into the scope of this Resource. Also initializes the
637
+ # @before_me and @after_me instance variables.
638
+ def initialize_control_metaparams
639
+ METAPARAMS.each { |mparam| initialize_control_metaparameter(mparam) }
640
+ @before_me = initialize_before_me
641
+ @after_me = initialize_after_me
642
+ end
643
+
644
+ # Initializes a single supplied metaparameter for all controls that this Resource
645
+ # contains and brings those values into the scope of this Resource.
646
+ # @param mparam [String] The metaparameter to be initialized.
647
+ def initialize_control_metaparameter(mparam)
648
+ ctrl_objects = @controls.map { |c| c.send(mparam.to_sym) }.flatten
649
+ return if ctrl_objects.empty?
650
+
651
+ current_objects = instance_variable_get("@#{mparam}") || []
652
+ all_meta_objects = ctrl_objects.concat(current_objects)
653
+ instance_variable_set("@#{mparam}", all_meta_objects.flatten.compact.uniq)
654
+ define_singleton_method("#{mparam}?".to_sym) { all_meta_objects.any? }
655
+ end
656
+
657
+ # Creates a new Control class for each control in the data structure if that Control class
658
+ # does not already exist in the cache.
659
+ # @param control_data [Array] The control data of the resource from the Hiera data.
660
+ def create_control_classes(control_data)
661
+ case control_data.class.to_s
662
+ when 'Hash'
663
+ control_data.map { |cname, cdata| AbideDataProcessor::Parser.new_control(cname, cdata, @control_maps) }
664
+ when 'Array'
665
+ control_data.map { |cname| AbideDataProcessor::Parser.new_control(cname, :no_params, @control_maps) }
666
+ else
667
+ raise ArgumentError, "Cannot create control because control data is not the expected type. Data type is #{control_data.class}"
668
+ end
669
+ end
670
+ end
671
+
672
+ class << self
673
+ # Creates a new Resource object. If an object with the same resource name, resource data, and control maps
674
+ # already exists, it will be returned instead of creating a new one.
675
+ # @param resource_name [String] The name of the resource.
676
+ # @param resource_data [Hash] The data for the resource.
677
+ # @param control_maps [Array] The control maps for the resource.
678
+ # @return [Resource] The new or cached Resource object.
679
+ def new_resource(resource_name, resource_data, control_maps)
680
+ cache_key = [Resource.name, resource_name, resource_data, control_maps]
681
+ cached = cache_get(cache_key)
682
+ return cached unless cached.nil?
683
+
684
+ new_resource = Resource.new(resource_name, resource_data, control_maps)
685
+ cache_add(cache_key, new_resource)
686
+ new_resource
687
+ end
688
+
689
+ # Creates a new Control object. If an object with the same control name, control data, and control maps
690
+ # already exists, it will be returned instead of creating a new one.
691
+ # @param control_name [String] The name of the control.
692
+ # @param control_data [Hash] The data for the control.
693
+ # @param control_maps [Array] The control maps for the control.
694
+ # @return [Control] The new or cached Control object.
695
+ def new_control(control_name, control_data, control_maps)
696
+ cache_key = [Control.name, control_name, control_data, control_maps]
697
+ cached = cache_get(cache_key)
698
+ return cached unless cached.nil?
699
+
700
+ new_control = Control.new(control_name, control_data, control_maps)
701
+ cache_add(cache_key, new_control)
702
+ new_control
703
+ end
704
+
705
+ # Clears the current cache. Used in testing.
706
+ def clear_cache
707
+ @object_cache = {}
708
+ end
709
+
710
+ private
711
+
712
+ # Helper method to add a ProcessorObject (or subclass of one) to the cache.
713
+ # @param key [Array] The key for the cache. An array comprised of the object name, object data,
714
+ # and control maps.
715
+ # @param resource [ProcessorObject] The object to add to the cache.
716
+ def cache_add(key, object)
717
+ object_cache[key] = object
718
+ end
719
+
720
+ # Helper method to retrieve a ProcessorObject from the cache.
721
+ # @param key [Array] The key for the cache. An array comprised of the resource name, resource data, and control maps.
722
+ # @return [ProcessorObject] The object from the cache, or nil if the object doesn't exist.
723
+ def cache_get(key)
724
+ object_cache.fetch(key, nil)
725
+ end
726
+
727
+ # Holds the object cache. If the object cache doesn't exist, it will be created.
728
+ def object_cache
729
+ @object_cache ||= {}
730
+ end
731
+ end
732
+ end
733
+ end
@@ -1,283 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'deep_merge'
4
- require 'set'
5
- require 'pry'
3
+ require 'abide-data-processor/parser'
6
4
 
7
5
  module AbideDataProcessor
8
6
  module Processor
9
- # Here lies the class that will be use to create/extract resources
10
- class ResourceCreator
11
-
12
- # @param control_maps: The control mappings to valid IDs
13
- # @param module_name: The name of the module
14
- # @param logger: The logger that we will use to log information for the user
15
- def initialize(control_maps, logger)
16
- @control_maps = control_maps
17
- @logger = logger
18
- end
19
-
20
- # control_key_maps
21
- # Gets all control key maps from Hiera for indexed control ID permutation searches
22
- # @return An array of four control ID maps, each indexed by one of the four different valid permutations of a control ID
23
- def self.control_key_maps(module_name)
24
- key_prefix = "#{module_name}::mappings::cis"
25
- %w[hiera_title hiera_title_num number title].each_with_object([]) do |key, ary|
26
- ary << [key_prefix, key].join('::')
27
- end
28
- end
29
-
30
- def cis_hiera_key(prefix, key)
31
- "#{prefix}::#{key}"
32
- end
33
-
34
- # create_resources
35
- # @param resources_hash: the hash of controls to be enforces, user will provide this
36
- # @param only: the list of controls to be enforce only, pulled from cis.pp
37
- # @param ignore: the list of controls to be ignore, pulled from cis.pp
38
- # @param control_configs: the custom control configurations pulled from cis.pp
39
- # Return a hash to be convert to Puppet code.
40
- def create_resources(resources_hash, only, ignore, control_configs)
41
- resources = real_resources(resources_hash, only.to_set, ignore.to_set, control_configs)
42
- ordered_resources = order_resources(resources)
43
-
44
- mutate_ordering_params!(ordered_resources[1])
45
- ordered_resources
46
- end
47
-
48
- # Everything else except the create_resource function will be private
49
- private
50
-
51
- # real_resources
52
- # Formats a Hiera resources hash into a hash used by order_resources()
53
- # @param resources_hash The raw resources hash pulled from hiera
54
- # @param only The $only parameter from cis.pp
55
- # @param ignore The $ignore parameter from cis.pp
56
- # @param control_configs The $control_configs parameter from cis.pp
57
- def real_resources(resources_hash, only, ignore, control_configs)
58
- real_resources = {}
59
- all_controls_name = Set.new # subject to change
60
-
61
- # Grabbing all the control name here into a set
62
- resources_hash.each do |_title, data|
63
- all_controls_name |= data['controls'].keys.to_set
64
- end
65
-
66
- resources_hash.each do |title, data|
67
- resource_params = if data.key?('controls')
68
- extract_control_params(data['controls'], only, ignore, control_configs, all_controls_name)
69
- else
70
- {}
71
- end
72
- if real_resources.key?(data['type']) && real_resources[data['type']].key?(title)
73
- real_resources[data['type']][title].deep_merge!(resource_params, merge_hash_arrays: true)
74
- else
75
- real_resources[data['type']] = { title => resource_params }
76
- end
77
- end
78
- real_resources
79
- end
80
-
81
- # extract_control_params
82
- # Extracts resource parameters from a Hiera resource hash item's `controls` key
83
- # @param control_data The resource hash item's `controls` key-value pair (i.e. data['controls'])
84
- # @param only The $only parameter from cis.pp
85
- # @param ignore The $ignore parameter from cis.pp
86
- # @param control_configs The $control_configs parameter from cis.pp
87
- # @param all_controls_name: All of the controls name
88
- def extract_control_params(control_data, only, ignore, control_configs, all_controls_name)
89
- control_params = {}
90
- control_data.each do |name, params|
91
- name_map = map_for_control_name(name, @control_maps)
92
- next if name_map.nil?
93
- # Only and ignore list check
94
- # The name_map that got passed in here is a hash
95
- next unless only_and_ignore_check(name, name_map, only, ignore)
96
-
97
- # Control dependent check
98
- if params.key?('dependent')
99
- unless dependent_check(all_controls_name, params['dependent'], ignore, only)
100
- # Below is just a sure fire way to make sure that we will never use the resource
101
- only.delete(name) # Remove from the only list
102
- ignore.add(name) # Add the name of the current control to the ignore list if we're not gonna enforce it
103
- @logger.inform("Control #{name} will not be enforced because the controls that it depends on is invalid.")
104
- next
105
- end
106
- end
107
- # Find if there are any custom control configs from the cis.pp based on the control's name and its permutation
108
- customized = find_control_customization(name, name_map[name], control_configs) # Check for failuer here
109
- params.deep_merge!(customized, merge_hash_arrays: true)
110
- control_params.deep_merge!(params, merge_hash_arrays: true)
111
- end
112
- control_params
113
- end
114
-
115
- # dependent_check
116
- # @param all_controls_name: Set of all controls name that parsed from the hiera data
117
- # @param all_dependent_resources: An array of all the resources that is relied upon
118
- # @param ignore: List of controls to be ignore
119
- # @param only: List of only controls that need to be enforce
120
- # return true if a dependent control is
121
- def dependent_check(all_controls_name, all_dependent_resources, ignore, only)
122
- all_dependent_resources.each do |resource_name|
123
- valid_resource_name = map_for_control_name(resource_name, @control_maps)
124
- # Bounce immediately if it is not a part of the controls we're enforcing
125
- return false unless filter_function(resource_name, valid_resource_name, all_controls_name)
126
-
127
- if !ignore.empty?
128
- return false if filter_function(resource_name, valid_resource_name, ignore)
129
- elsif !only.empty?
130
- return false unless filter_function(resource_name, valid_resource_name, only)
131
- end
132
- end
133
- end
134
-
135
- # order_resources
136
- # A work in progress to integrate more metaparamenters in
137
- # Checks for and creates resources based off of `before`, `after`, `notify`, `require` parameters
138
- # specified in a controls hash
139
- # @param resources Output of real_resources()
140
- # @return An array of resource hashes indexed in the order their contents should be created
141
- def order_resources(resources)
142
- before = {}
143
- after = {}
144
- req = {}
145
- notify = {}
146
- resources.each do |_, data|
147
- create_ordered_resource!('before', before, data)
148
- create_ordered_resource!('notify', notify, data)
149
- create_ordered_resource!('after', after, data)
150
- create_ordered_resource!('require', req, data)
151
- end
152
-
153
- before.deep_merge!(notify)
154
- after.deep_merge!(req)
155
-
156
- [before, resources, after]
157
- end
158
-
159
- # filter_function
160
- # A general function to see if a control name is in a supply list of control name
161
- # @param name: The name of the control that we have
162
- # @param name_map: Hash that contains all valid control ID permutation of the param name
163
- # @set_of_control: Either the ignore or the only list to go through
164
- # return true if control ID is found in set_of_control
165
- def filter_function(name, name_map, set_of_control)
166
- name_list = name_map[name] # Grab the array that contain all valid permutation of the ID
167
- return true if set_of_control.include?(name)
168
-
169
- name_list.each do |n|
170
- return true if set_of_control.include?(n)
171
- end
172
-
173
- false
174
- end
175
-
176
- # only_and_ignore_check
177
- # @param name: name of the control to check if it's in either only or ignore list
178
- # @param name_map: a hash of the name map of valid ID permutation for the `name` param
179
- # @param only: the list of controls that will get enforced only
180
- # @param ignore: the list of controls that will be ignored
181
- # @return false when control is either not in the only list or is in the ignore list.
182
- # else return true
183
- def only_and_ignore_check(name, name_map, only, ignore)
184
- if !only.empty? && !filter_function(name, name_map, only)
185
- @logger.inform("Control #{name} will be skipped because it is not in the only list.")
186
- return false
187
- end
188
-
189
- if !ignore.empty? && filter_function(name, name_map, ignore)
190
- @logger.inform("Control #{name} will be skipped because it is in the ignore list.")
191
- return false
192
- end
193
- true
194
- end
195
-
196
- # create_ordered_resource!
197
- # Creates a resource hash from a resource declaration found in a `before`, `after`, `require`, or `notify` parameter
198
- # @param order_key Either 'before', 'after', `notify`, or `require`
199
- # @param container Either the before hash, the notify hash, the require hash or the after hash.
200
- # The container is modified in place.
201
- # @param res_data Resource data from the real_resources hash
202
- def create_ordered_resource!(order_key, container, res_data)
203
- res_data.each do |_, data|
204
- next unless data.key?(order_key)
205
-
206
- data[order_key].each do |title, params|
207
- container[params['type']] = {} unless container.key?(params['type'])
208
- container[params['type']][title] = params.reject { |k, _| k == 'type' }
209
- end
210
- end
211
- end
212
-
213
- # mutate_ordering_params!
214
- # This takes the Hiera resource declarations in a `before` or `after` param and transforms
215
- # them into and array of Puppet resource references. Puppet resource references take the
216
- # form: Resource::Type['<resource title'].
217
- # @param resources Output from real_resources()
218
- def mutate_ordering_params!(resources)
219
- resources.each do |res_type, res_data|
220
- %w[before notify after require].each do |order_key|
221
- res_data.each do |res_title, params|
222
- next unless params.key?(order_key)
223
-
224
- references = []
225
- params[order_key].each do |k, v|
226
- references << resource_reference(v['type'], k)
227
- end
228
- resources[res_type][res_title][order_key] = references
229
- end
230
- end
231
- end
232
- end
233
-
234
- # resource_reference
235
- # Returns a Puppet resource reference string
236
- # @param res_type A Puppet resource type
237
- # @param title A Puppet resource title
238
- def resource_reference(res_type, title)
239
- type_ref = res_type.split('::').map(&:capitalize).join('::')
240
- "#{type_ref}[#{title}]"
241
- end
242
-
243
- # find_control_customization
244
- # Finds any control parameter customizations passed in via control_configs
245
- # @param name The control name (or other valid permutation)
246
- # @param control_configs The $control_configs parameter from cis.pp
247
- # @param name_map: The array of valid permutation of name
248
- # @return A hash of customized parameters. If none were found, nil
249
- def find_control_customization(name, name_map, control_configs)
250
- return {} if control_configs.empty?
251
-
252
- mapped_key(control_configs, name, name_map)
253
- end
254
-
255
- # map_for_control_name
256
- # Returns a hash of all valid permutations of the given control id
257
- # @param name The control name or other valid permutation
258
- # @param maps All maps
259
- def map_for_control_name(name, maps)
260
- maps.each do |map|
261
- return map if map&.fetch(name, false) # returns the map if fetch returns false
262
- end
263
- nil
264
- end
265
-
266
- # mapped_key
267
- # Finds an item in the given hash that matches one of the values in name_map
268
- # @param hsh The hash to search i.e the custom config hash
269
- # @param name The name of the current control that we're looking to see if it has any custom configs
270
- # @param name_map An array name for valid control permutations
271
- # @return The value from the hash if found, or nil
272
- def mapped_key(hsh, name, name_map)
273
- return hsh[name] if hsh&.fetch(name, false)
274
-
275
- name_map.each do |pkey|
276
- return hsh[pkey] if hsh&.fetch(pkey, false)
277
- end
278
- nil
279
- end
280
-
7
+ def self.create_resources(resources_hash, control_maps, only, ignore, control_configs)
8
+ unfrozen_resources = Marshal.load(Marshal.dump(resources_hash))
9
+ AbideDataProcessor::Parser.parse(unfrozen_resources, control_maps, only: only, ignore: ignore, control_configs: control_configs)
281
10
  end
282
11
  end
283
12
  end
@@ -1,3 +1,3 @@
1
1
  module AbideDataProcessor
2
- VERSION = "0.2.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,4 +1,6 @@
1
1
  require 'abide-data-processor/version'
2
2
  require 'abide-data-processor/processor'
3
+ require 'abide-data-processor/logger'
4
+
3
5
  # Root namespace for all modules / classes
4
6
  module AbideDataProcessor; end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abide-data-processor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - abide-team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-19 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: puppet
14
+ name: deep_merge
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '6.23'
19
+ version: '1.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rgl
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: '6.23'
40
+ version: '0.5'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -241,6 +255,7 @@ files:
241
255
  - bin/setup
242
256
  - lib/abide-data-processor.rb
243
257
  - lib/abide-data-processor/logger.rb
258
+ - lib/abide-data-processor/parser.rb
244
259
  - lib/abide-data-processor/processor.rb
245
260
  - lib/abide-data-processor/version.rb
246
261
  homepage: https://github.com/puppetlabs/abide-data-processor