Skip to content

Commit

Permalink
Merge pull request #4 from simp/issue_1
Browse files Browse the repository at this point in the history
Discard cached objects when files are added
  • Loading branch information
silug authored Apr 11, 2024
2 parents 587d13a + 6fcc1ca commit 61f2f9f
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 67 deletions.
9 changes: 0 additions & 9 deletions lib/compliance_engine/ces.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ def by_oval_id
@by_oval_id
end

# Invalidate all cached data
#
# @param data [ComplianceEngine::Data, NilClass] the data to initialize the object with
# @return [NilClass]
def invalidate_cache(data = nil)
@by_oval_id = nil
super
end

private

# Returns the key of the collection in compliance engine source data
Expand Down
9 changes: 0 additions & 9 deletions lib/compliance_engine/check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,4 @@ def type
def remediation
element['remediation']
end

# Invalidate all cached data
#
# @param data [ComplianceEngine::Data, ComplianceEngine::Collection, NilClass] the data to initialize the object with
# @return [NilClass]
def invalidate_cache(data = nil)
@hiera = nil
super
end
end
18 changes: 11 additions & 7 deletions lib/compliance_engine/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ class ComplianceEngine::Collection
#
# @param data [ComplianceEngine::Data] the data to initialize the object with
def initialize(data)
@facts = data.facts
@enforcement_tolerance = data.enforcement_tolerance
@environment_data = data.environment_data
context_variables.each { |var| instance_variable_set(var, data.instance_variable_get(var)) }
@collection ||= {}
hash_key = key
data.files.each do |file|
Expand All @@ -23,15 +21,14 @@ def initialize(data)

attr_accessor :collection, :facts, :enforcement_tolerance, :environment_data

# Invalidate all cached data
# Invalidate the cache of computed data
#
# @param data [ComplianceEngine::Data, NilClass] the data to initialize the object with
# @return [NilClass]
def invalidate_cache(data = nil)
@facts = data&.facts
@enforcement_tolerance = data&.enforcement_tolerance
@environment_data = data&.environment_data
context_variables.each { |var| instance_variable_set(var, data&.instance_variable_get(var)) }
collection.each_value { |obj| obj.invalidate_cache(data) }
(instance_variables - (context_variables + [:@collection])).each { |var| instance_variable_set(var, nil) }
nil
end

Expand Down Expand Up @@ -105,6 +102,13 @@ def reject(&block)

private

# Get the context variables
#
# @return [Array<Symbol>]
def context_variables
[:@enforcement_tolerance, :@environment_data, :@facts]
end

# Returns the key of the object
#
# @return [NotImplementedError] This method is not implemented and should be overridden by subclasses.
Expand Down
30 changes: 19 additions & 11 deletions lib/compliance_engine/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,20 @@ class ComplianceEngine::Component
# @param [String] component The component key
# @param [ComplianceEngine::Data, ComplianceEngine::Collection, NilClass] data The data to initialize the object with
def initialize(name, data: nil)
unless data.nil?
@facts = data.facts
@enforcement_tolerance = data.enforcement_tolerance
@environment_data = data.environment_data
end
context_variables.each { |var| instance_variable_set(var, data&.instance_variable_get(var)) }
@component ||= { key: name, fragments: {} }
end

attr_accessor :component, :facts, :enforcement_tolerance, :environment_data

# Invalidate all cached data
# Invalidate the cache of computed data
#
# @param data [ComplianceEngine::Data, ComplianceEngine::Collection, NilClass] the data to initialize the object with
# @return [NilClass]
def invalidate_cache(data = nil)
@facts = data&.facts
@enforcement_tolerance = data&.enforcement_tolerance
@environment_data = data&.environment_data
@fragments = nil
@element = nil
context_variables.each { |var| instance_variable_set(var, data&.instance_variable_get(var)) }
cache_variables.each { |var| instance_variable_set(var, nil) }
nil
end

# Adds a value to the fragments array of the component.
Expand Down Expand Up @@ -106,6 +100,20 @@ def ces

private

# Get the context variables
#
# @return [Array<Symbol>]
def context_variables
[:@enforcement_tolerance, :@environment_data, :@facts]
end

# Get the cache variables
#
# @return [Array<Symbol>]
def cache_variables
instance_variables - (context_variables + [:@component])
end

# Compare a fact value against a confine value
#
# @param [Object] fact The fact value
Expand Down
90 changes: 59 additions & 31 deletions lib/compliance_engine/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,46 @@ def initialize(*paths, facts: nil, enforcement_tolerance: nil)

# Set the object data
# @param [Hash] data The data to initialize the object with
def data=(data)
@data = data
def data=(value)
@data = value
invalidate_cache
end

# Set the facts
# @param [Hash] facts The facts to initialize the object with
def facts=(facts)
@facts = facts
def facts=(value)
@facts = value
invalidate_cache
end

# Set the enforcement tolerance
# @param [Hash] enforcement_tolerance The enforcement tolerance to initialize
def enforcement_tolerance=(enforcement_tolerance)
@enforcement_tolerance = enforcement_tolerance
def enforcement_tolerance=(value)
@enforcement_tolerance = value
invalidate_cache
end

# Set the environment data
# @param [Hash] environment_data The environment data to initialize the object with
def environment_data=(environment_data)
@environment_data = environment_data
def environment_data=(value)
@environment_data = value
invalidate_cache
end

# Invalidate all cached data
# Invalidate the cache of computed data
#
# @return [NilClass]
def invalidate_cache
[profiles, checks, controls, ces].each { |obj| obj.invalidate_cache(self) }
@hiera = nil
@confines = nil
@mapping = nil
@check_mapping = nil
collection_variables.each { |var| instance_variable_get(var)&.invalidate_cache(self) }
cache_variables.each { |var| instance_variable_set(var, nil) }
end

# Discard all parsed data other than the top-level data
#
# @return [NilClass]
def reset_collection
# Discard any cached objects
(instance_variables - (data_variables + context_variables)).each { |var| instance_variable_set(var, nil) }
end

# Scan paths for compliance data files
Expand Down Expand Up @@ -97,7 +102,6 @@ def open(*paths)
#
# @param [String] file The path to the compliance data file
def update(file)
# debug "Scanning #{file}"
# If we've already scanned this file, and the size and modification
# time of the file haven't changed, skip it.
size = File.size(file)
Expand All @@ -106,25 +110,25 @@ def update(file)
return
end

data[file] = {
size: size,
mtime: mtime,
}
data[file] = begin
parse(file)
rescue => e
warn e.message
{}
end

begin
data[file] = parse(file)
rescue => e
warn e.message
end
data[file][:size] = size
data[file][:mtime] = mtime

reset_collection
end

# Get a list of files with compliance data
#
# @return [Array<String>]
def files
# FIXME: This needs to be recalculated when files are added or updated.
# return @files unless @files.nil?
@files = data.select { |_file, data| data.key?(:content) }.keys
return @files unless @files.nil?
@files = data.select { |_, file| file.key?(:content) }.keys
end

# Get the compliance data for a given file
Expand All @@ -141,31 +145,27 @@ def get(file)
#
# @return [ComplianceEngine::Profiles]
def profiles
# FIXME: This needs to be recalculated when files are added or updated.
@profiles ||= ComplianceEngine::Profiles.new(self)
end

# Return a collection of CEs
#
# @return [ComplianceEngine::CEs]
def ces
# FIXME: This needs to be recalculated when files are added or updated.
@ces ||= ComplianceEngine::Ces.new(self)
end

# Return a collection of checks
#
# @return [ComplianceEngine::Checks]
def checks
# FIXME: This needs to be recalculated when files are added or updated.
@checks ||= ComplianceEngine::Checks.new(self)
end

# Return a collection of controls
#
# @return [ComplianceEngine::Controls]
def controls
# FIXME: This needs to be recalculated when files are added or updated.
@controls ||= ComplianceEngine::Controls.new(self)
end

Expand Down Expand Up @@ -250,6 +250,34 @@ def check_mapping(profile_or_ce)

private

# Get the collection variables
#
# @return [Array<Symbol>]
def collection_variables
[:@profiles, :@checks, :@controls, :@ces]
end

# Get the data variables
#
# @return [Array<Symbol>]
def data_variables
[:@data]
end

# Get the context variables
#
# @return [Array<Symbol>]
def context_variables
[:@enforcement_tolerance, :@environment_data, :@facts]
end

# Get the cache variables
#
# @return [Array<Symbol>]
def cache_variables
instance_variables - (data_variables + collection_variables + context_variables)
end

# Return true if the check is mapped to the profile or CE
#
# @param [ComplianceEngine::Check] check The check
Expand Down

0 comments on commit 61f2f9f

Please sign in to comment.