abide-data-processor 0.2.1 → 1.1.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.
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