Skip to content

Commit

Permalink
Collect facts iteratively
Browse files Browse the repository at this point in the history
Rather than getting the facts for every filter spec and then discarding
that, this stores the found facts in an array and uses that.

This eliminates a call to FacterDB::get_facts with a very complex
filter.

A quick test in puppet-nginx reduces loading of tests by about 2 seconds
(from ~9 to ~7).
  • Loading branch information
ekohl committed Jul 20, 2023
1 parent 1c8a717 commit 58fa0a4
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 15 deletions.
11 changes: 5 additions & 6 deletions lib/rspec-puppet-facts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,18 @@ def on_supported_os_implementation(opts = {})
strict_requirement = RspecPuppetFacts::facter_version_to_strict_requirement(facterversion)

loose_requirement = RspecPuppetFacts::facter_version_to_loose_requirement(facterversion)
received_facts = []

# 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.
filter.each do |filter_spec|
versions = FacterDB.get_facts(filter_spec).map { |facts| Gem::Version.new(facts[:facterversion]) }.sort.reverse
next unless versions.any?
versions = FacterDB.get_facts(filter_spec).to_h { |facts| [Gem::Version.new(facts[:facterversion]), facts] }

version = versions.detect { |v| strict_requirement =~ v }
version, facts = versions.select { |v, _f| strict_requirement =~ v }.max_by { |v, _f| v }

unless version
version = versions.detect { |v| loose_requirement =~ v } if loose_requirement
version, facts = versions.select { |v, _f| loose_requirement =~ v }.max_by { |v, _f| v } if loose_requirement
next unless version

if RspecPuppetFacts.spec_facts_strict?
Expand All @@ -137,10 +137,9 @@ def on_supported_os_implementation(opts = {})
RspecPuppetFacts.warning "No facts were found in the FacterDB for Facter v#{facterversion} on #{filter_spec}, using v#{version} instead"
end

filter_spec[:facterversion] = "/\\A#{Regexp.escape(version.to_s)}\\Z/"
received_facts << facts
end

received_facts = FacterDB::get_facts(filter)
unless received_facts.any?
RspecPuppetFacts.warning "No facts were found in the FacterDB for: #{filter.inspect}"
return {}
Expand Down
15 changes: 6 additions & 9 deletions spec/rspec_puppet_facts_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -662,19 +662,16 @@

before do
allow(described_class).to receive(:warning).with(a_string_matching(/no facts were found/i))
allow(FacterDB).to receive(:get_facts).and_call_original
end

it 'escapes the parens in the filter' do
filter = [
include(
:operatingsystem => "IOS",
:operatingsystemrelease => "/^12\\.2\\(25\\)EWA9/",
:hardwaremodel => "x86_64",
),
]
filter = {
:operatingsystem => "IOS",
:operatingsystemrelease => "/^12\\.2\\(25\\)EWA9/",
:hardwaremodel => "x86_64",
}

expect(FacterDB).to receive(:get_facts).with(filter)
expect(FacterDB).to receive(:get_facts).with(filter).once
subject
end

Expand Down

0 comments on commit 58fa0a4

Please sign in to comment.