From 5fcc51c8c76ddb4b3684b064aeb8063e4724d314 Mon Sep 17 00:00:00 2001 From: Ewoud Kohl van Wijngaarden Date: Thu, 20 Jul 2023 17:43:09 +0200 Subject: [PATCH 1/2] Use a single FacterDB.get_facts call The major cost is FacterDB.get_facts. Instead of calling it once for every OS version this instead calls it once with a complex filter. It then uses JGrep to simulate another smaller DB and futher query that. In my non-scientific test this reduces the load time of puppet-example from 3.5 to 2.5 seconds. --- lib/rspec-puppet-facts.rb | 13 ++++++++++--- spec/rspec_puppet_facts_spec.rb | 17 ++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/rspec-puppet-facts.rb b/lib/rspec-puppet-facts.rb index 2c7b5d8..07474dc 100644 --- a/lib/rspec-puppet-facts.rb +++ b/lib/rspec-puppet-facts.rb @@ -113,13 +113,20 @@ def on_supported_os_implementation(opts = {}) loose_requirement = RspecPuppetFacts.facter_version_to_loose_requirement(facterversion) received_facts = [] + db = FacterDB.get_facts(filter, symbolize_keys: false) + unless db.any? + RspecPuppetFacts.warning "No facts were found in the FacterDB for: #{filter.inspect}" + return {} + end + # FacterDB may have newer versions of facter data for which it contains a subset of all possible # facter data (see FacterDB 0.5.2 for Facter releases 3.8 and 3.9). In this situation we need to # cycle through and downgrade Facter versions per platform type until we find matching Facter data. - facterversion_key = RSpec.configuration.facterdb_string_keys ? 'facterversion' : :facterversion + json_db = db.to_json filter.each do |filter_spec| - versions = FacterDB.get_facts(filter_spec, symbolize_keys: !RSpec.configuration.facterdb_string_keys).to_h do |facts| - [Gem::Version.new(facts[facterversion_key]), facts] + versions = JGrep.jgrep(json_db, FacterDB.generate_filter_str(filter_spec)).to_h do |facts| + result = RSpec.configuration.facterdb_string_keys ? facts : facts.transform_keys(&:to_sym) + [Gem::Version.new(facts['facterversion']), result] end version, facts = versions.select { |v, _f| strict_requirement =~ v }.max_by { |v, _f| v } diff --git a/spec/rspec_puppet_facts_spec.rb b/spec/rspec_puppet_facts_spec.rb index bfbb8a0..d71ab15 100644 --- a/spec/rspec_puppet_facts_spec.rb +++ b/spec/rspec_puppet_facts_spec.rb @@ -610,13 +610,13 @@ end it 'escapes the parens in the filter' do - filter = { + filter = [{ 'os.name' => 'IOS', 'os.release.full' => '/^12\\.2\\(25\\)EWA9/', 'os.hardware' => 'x86_64', - } + }] - expect(FacterDB).to receive(:get_facts).with(filter, symbolize_keys: true).once + expect(FacterDB).to receive(:get_facts).with(filter, symbolize_keys: false).once.and_return([]) subject end @@ -742,11 +742,14 @@ end before do - allow(FacterDB).to receive(:get_facts).and_call_original allow(FacterDB).to receive(:get_facts).with( - { 'os.name' => 'CentOS', 'os.release.full' => '/^9/', 'os.hardware' => 'x86_64' }, symbolize_keys: true - ).and_wrap_original do |m, *args| - m.call(*args).reject { |facts| facts[:facterversion].start_with?('4.6.') } + [ + { 'os.name' => 'CentOS', 'os.release.full' => '/^9/', 'os.hardware' => 'x86_64' }, + { 'os.name' => 'Debian', 'os.release.full' => '/^12/', 'os.hardware' => 'x86_64' }, + ], + symbolize_keys: false, + ).and_wrap_original do |m, *args, **kwargs| + m.call(*args, **kwargs).reject { |facts| facts.dig('os', 'name') == 'CentOS' && facts['facterversion'].start_with?('4.6.') } end end From 70f4c3360484cbc66cd1f3623b7d3d9418c83a31 Mon Sep 17 00:00:00 2001 From: Ewoud Kohl van Wijngaarden Date: Fri, 21 Jul 2023 12:16:14 +0200 Subject: [PATCH 2/2] Use FacterDB.filter_results --- Gemfile | 2 ++ lib/rspec-puppet-facts.rb | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index f494abb..6701f38 100644 --- a/Gemfile +++ b/Gemfile @@ -13,3 +13,5 @@ group :coverage, optional: ENV['COVERAGE'] != 'yes' do gem 'codecov', require: false gem 'simplecov-console', require: false end + +gem 'facterdb', github: 'ekohl/facterdb', branch: 'filter-results' diff --git a/lib/rspec-puppet-facts.rb b/lib/rspec-puppet-facts.rb index 07474dc..55a33b1 100644 --- a/lib/rspec-puppet-facts.rb +++ b/lib/rspec-puppet-facts.rb @@ -122,9 +122,8 @@ def on_supported_os_implementation(opts = {}) # FacterDB may have newer versions of facter data for which it contains a subset of all possible # facter data (see FacterDB 0.5.2 for Facter releases 3.8 and 3.9). In this situation we need to # cycle through and downgrade Facter versions per platform type until we find matching Facter data. - json_db = db.to_json filter.each do |filter_spec| - versions = JGrep.jgrep(json_db, FacterDB.generate_filter_str(filter_spec)).to_h do |facts| + versions = FacterDB.filter_results(db, filter_spec).to_h do |facts| result = RSpec.configuration.facterdb_string_keys ? facts : facts.transform_keys(&:to_sym) [Gem::Version.new(facts['facterversion']), result] end