Skip to content

Commit

Permalink
Provide filter_results to refine a search
Browse files Browse the repository at this point in the history
rspec-puppet-facts has a pattern where it does a lot of small searches
for every OS. By doing a single complex FacterDB.get_facts call to get
the only supported operating systems and then further refining that
result it can use the cache provided by FacterDB.get_facts.

This is quite hacky now because it duplicates internals from JGrep to
avoid serializing to JSON and parsing that again.
  • Loading branch information
ekohl committed Sep 13, 2024
1 parent 8931e84 commit 6f98c73
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 0 deletions.
18 changes: 18 additions & 0 deletions lib/facterdb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,22 @@ def self.get_facts(filter = nil, cache = true, symbolize_keys: true)
end
result
end

# @param results [Array[Hash]] The results from a get_facts call
# @param filter [Object] The filter to convert to jgrep string
# @return [Array[Hash[Symbol, Any]]]
# Array of hashes of facts when symbolize_keys is true
# @return [Array[Hash[String, Any]]]
# Array of hashes of facts when symbolize_keys is false
def self.filter_results(results, filter, symbolize_keys: true)
database = symbolize_keys ? results.map { |hash| hash.transform_keys(&:to_s) } : results

# TODO: This duplicates JGrep.jgrep to avoid JSON.parse(database.to_json)
# JGrep should provide an API for that
expression = generate_filter_str(filter)
call_stack = JGrep::Parser.new(expression).execution_stack
filtered = database.filter { |document| JGrep.eval_statement(document, call_stack) }

symbolize_keys ? filtered.map { |hash| hash.transform_keys(&:to_sym) } : filtered
end
end
18 changes: 18 additions & 0 deletions spec/facter_db_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,22 @@
end
end
end

describe '.filter_results' do
subject(:filtered) { FacterDB.filter_results(results, filter) }

let(:filters) { 'osfamily=Debian or osfamily=RedHat' }
let(:results) { FacterDB.get_facts(filters) }

# Just to make sure our results set contains what we want
it 'has both Debian and Red Hat in the unfiltered result' do
expect(results).to include(hash_including(osfamily: 'Debian')).and include(hash_including(osfamily: 'RedHat'))
end

context 'with filter for Debian' do

Check failure on line 304 in spec/facter_db_spec.rb

View workflow job for this annotation

GitHub Actions / rubocop

RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [7/6] (https://rspec.rubystyle.guide/#let-blocks, https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers)
let(:filter) { 'osfamily=Debian' }

it { is_expected.to include(hash_including(osfamily: 'Debian')).and not_include(hash_including(osfamily: 'RedHat')) }
end
end
end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

RSpec::Matchers.define_negated_matcher :not_be_nil, :be_nil
RSpec::Matchers.define_negated_matcher :not_be_empty, :be_empty
RSpec::Matchers.define_negated_matcher :not_include, :include

def project_dir
File.dirname File.dirname(File.expand_path(__FILE__))
Expand Down

0 comments on commit 6f98c73

Please sign in to comment.