Skip to content

Commit

Permalink
Evaluate confine block in case-insensitive way
Browse files Browse the repository at this point in the history
Prior to this commit when a user provided a confine block, Facter would
downcase the value when evaluating it.

For example:

confine :kernel do |value|
  value == "Linux"
end

While Facter's public documentation states that this is a valid way to
write a confine block, it would incorrectly and unexpectedly evaluate
as false on Linux systems.

However, these other styles of confine would return true:

confine :kernel => "Linux"

confine kernel: "Linux"

This downcasing behavior was introduced in 7a81945 as a way of comparing
values in a case-insensitive way. However when block confines were
introduced in e4c8689, it added block evaluation before value
comparison, making the case-insensitive comparison moot with blocks.

This commit retains existing behavior of evaluating a confine block with
a downcased fact value, while adding evaluation with the raw fact value
to ensure expected behavior.
  • Loading branch information
mhashizume committed Apr 15, 2024
1 parent 5335371 commit 2d118cb
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
6 changes: 4 additions & 2 deletions lib/facter/custom_facts/util/confine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def to_s
end

# Evaluate the fact, returning true or false.
# if we have a block paramter then we only evaluate that instead
# if we have a block parameter then we only evaluate that instead
def true?
if @block && !@fact
begin
Expand All @@ -54,9 +54,11 @@ def true?

return false if value.nil?

# We call the block with both the downcased and raw fact value for
# backwards-compatibility.
if @block
begin
return !!@block.call(value)
return !!@block.call(value) || !!@block.call(fact.value) # rubocop:disable Style/DoubleNegation
rescue StandardError => e
log.debug "Confine raised #{e.class} #{e}"
return false
Expand Down
14 changes: 14 additions & 0 deletions spec/custom_facts/util/confine_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,20 @@ def confined(fact_value, *confines)
expect(confine.true?).to be true
end

it 'accepts and evaluate a block argument against the fact while respecting case' do
allow(fact).to receive(:value).and_return 'Foo'
confine = LegacyFacter::Util::Confine.new(:yay) { |f| f == 'Foo' }
expect(confine.true?).to be true
end

it 'accepts and evaluate multiple block arguments' do
allow(fact).to receive(:value).and_return 'bar'
first_confine = LegacyFacter::Util::Confine.new(:yay) { |f| f == 'foo' }
second_confine = LegacyFacter::Util::Confine.new(:yay) { |f| f == 'bar' }
expect(first_confine.true?).to be false
expect(second_confine.true?).to be true
end

it 'returns false if the block raises a StandardError when checking a fact' do
allow(fact).to receive(:value).and_return 'foo'
confine = LegacyFacter::Util::Confine.new(:yay) { |_f| raise StandardError }
Expand Down

0 comments on commit 2d118cb

Please sign in to comment.