Skip to content

Commit 11a770a

Browse files
authored
Merge pull request #2556 from AriaXLi/FACT-3194/facter_ordering
(FACT-3194) Difference in Facter 3 & 4 ordering
2 parents 9351ff0 + 6298f97 commit 11a770a

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

lib/facter.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,14 @@ def to_hash
380380
resolved_facts = Facter::FactManager.instance.resolve_facts
381381
resolved_facts.reject! { |fact| fact.type == :custom && fact.value.nil? }
382382
collection = Facter::FactCollection.new.build_fact_collection!(resolved_facts)
383-
Hash[collection]
383+
384+
# Ensures order of keys in hash returned from Facter.to_hash() and
385+
# Facter.resolve() is always stable
386+
if collection.empty?
387+
Hash[collection]
388+
else
389+
Hash[Facter::Utils.sort_hash_by_key(collection)]
390+
end
384391
end
385392

386393
# Check whether printing stack trace is enabled
@@ -510,8 +517,10 @@ def queried_facts(user_query)
510517
resolved_facts = Facter::FactManager.instance.resolve_facts(user_query)
511518
resolved_facts.reject! { |fact| fact.type == :custom && fact.value.nil? }
512519

520+
# Ensures order of keys in hash returned from Facter.to_hash() and
521+
# Facter.resolve() is always stable
513522
if user_query.count.zero?
514-
Facter::FactCollection.new.build_fact_collection!(resolved_facts)
523+
Facter::Utils.sort_hash_by_key(Facter::FactCollection.new.build_fact_collection!(resolved_facts))
515524
else
516525
FormatterHelper.retrieve_facts_to_display_for_user_query(user_query, resolved_facts)
517526
end

spec/facter/facter_spec.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,18 @@
88
# note the type is the :nil symbol
99
Facter::ResolvedFact.new('missing_fact', nil, :nil, 'missing_fact')
1010
end
11+
let(:hash_fact) do
12+
Facter::ResolvedFact.new('mountpoints', { '/boot' => { 'filesystem' => 'ext4', 'device' => 'dev1' },
13+
'/' => { 'filesystem' => 'ext4', 'device' => 'dev2' } },
14+
:core, 'mountpoints')
15+
end
1116

1217
let(:logger) { instance_spy(Facter::Log) }
1318
let(:config_reader_double) { class_spy(Facter::ConfigReader) }
1419

20+
sorted_fact_hash = { 'mountpoints' => { '/' => { 'device' => 'dev2', 'filesystem' => 'ext4' },
21+
'/boot' => { 'device' => 'dev1', 'filesystem' => 'ext4' } } }
22+
1523
before do
1624
allow(Facter::ConfigReader).to receive(:init).and_return(config_reader_double)
1725
allow(config_reader_double).to receive(:cli).and_return(nil)
@@ -56,13 +64,32 @@ def stub_no_fact
5664
expect(Facter.resolve('')).to be_an_instance_of(Hash)
5765
end
5866

67+
context 'when user query in arguments' do
68+
it 'returns a stable order hash' do
69+
stub_facts([hash_fact])
70+
expect(Facter.resolve('mountpoints')).to eq(sorted_fact_hash)
71+
end
72+
end
73+
5974
context 'when user query and options in arguments' do
6075
it 'returns one resolved fact' do
6176
stub_facts([os_fact])
6277

6378
expect(Facter.resolve('os.name --show-legacy')).to eq('os.name' => 'ubuntu')
6479
end
6580
end
81+
82+
context 'when there is no user query' do
83+
let(:hash_fact_no_user_query) do
84+
Facter::ResolvedFact.new('mountpoints', { '/boot' => { 'filesystem' => 'ext4', 'device' => 'dev1' },
85+
'/' => { 'filesystem' => 'ext4', 'device' => 'dev2' } }, :core, '')
86+
end
87+
88+
it 'returns a stable order hash' do
89+
stub_facts([hash_fact_no_user_query])
90+
expect(Facter.resolve('')).to eq(sorted_fact_hash)
91+
end
92+
end
6693
end
6794

6895
describe '#to_hash' do
@@ -85,6 +112,11 @@ def stub_no_fact
85112
expect(Facter.to_hash).to eq({})
86113
end
87114
end
115+
116+
it 'returns a stable order hash' do
117+
stub_facts([hash_fact])
118+
expect(Facter.to_hash).to eq(sorted_fact_hash)
119+
end
88120
end
89121

90122
describe '#to_user_output' do

0 commit comments

Comments
 (0)