From 83ae4b72eb1774e3659add417b4a3429ce5139cc Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Wed, 12 Nov 2025 15:03:11 -0800 Subject: [PATCH] include "local" facts in facts output Some years ago [a bug was filed](https://puppet.atlassian.net/browse/PUP-10717) noting that `puppet facts show` appended all local facts when called with one or more specific facts. This was resolved by simply not including local facts for this specific subcommand. This had the unfortunate side effect that something like `puppet facts show clientcert` no longer displayed anything. (note: you could still run `puppet config print certname` but that takes a LOT of institutional knowledge to know that those are the same thing.) Worse, when we added the `implementation` local fact, it also didn't display. This PR just returns to including the local facts into `puppet fact show` output, but only the ones requested or when requesting all facts. Fixes #220 --- lib/puppet/indirector/facts/facter.rb | 2 +- lib/puppet/node/facts.rb | 11 ++++++----- spec/unit/application/facts_spec.rb | 12 ++++++++++-- spec/unit/indirector/facts/facter_spec.rb | 6 ------ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/puppet/indirector/facts/facter.rb b/lib/puppet/indirector/facts/facter.rb index 8eb847db6d..1e3805a838 100644 --- a/lib/puppet/indirector/facts/facter.rb +++ b/lib/puppet/indirector/facts/facter.rb @@ -49,7 +49,7 @@ def find(request) Puppet::Node::Facts.new(request.key, facts.to_h) end - result.add_local_facts unless request.options[:resolve_options] + result.add_local_facts(request.options[:user_query]) result.sanitize result end diff --git a/lib/puppet/node/facts.rb b/lib/puppet/node/facts.rb index 583d97a66c..1492402fd4 100644 --- a/lib/puppet/node/facts.rb +++ b/lib/puppet/node/facts.rb @@ -27,11 +27,12 @@ def save(instance, key = nil, options = {}) attr_accessor :name, :values, :timestamp - def add_local_facts - values["implementation"] = Puppet.implementation - values["clientcert"] = Puppet.settings[:certname] - values["clientversion"] = Puppet.version.to_s - values["clientnoop"] = Puppet.settings[:noop] + def add_local_facts(query = []) + query = Array(query) # some use cases result in a nil being passed in + values["implementation"] = Puppet.implementation if query.empty? or query.include? 'implementation' + values["clientcert"] = Puppet.settings[:certname] if query.empty? or query.include? 'clientcert' + values["clientversion"] = Puppet.version.to_s if query.empty? or query.include? 'clientversion' + values["clientnoop"] = Puppet.settings[:noop] if query.empty? or query.include? 'clientnoop' end def initialize(name, values = {}) diff --git a/spec/unit/application/facts_spec.rb b/spec/unit/application/facts_spec.rb index c3aecd0425..004dc94001 100644 --- a/spec/unit/application/facts_spec.rb +++ b/spec/unit/application/facts_spec.rb @@ -55,7 +55,11 @@ let(:expected) { <<~END } { "filesystems": "apfs,autofs,devfs", - "macaddress": "64:52:11:22:03:2e" + "macaddress": "64:52:11:22:03:2e", + "implementation": "#{Puppet.implementation}", + "clientcert": "#{Puppet.settings[:certname]}", + "clientversion": "#{Puppet.version}", + "clientnoop": false } END @@ -81,7 +85,7 @@ end it "warns and ignores value-only when multiple fact names are specified" do - app.command_line.args << 'filesystems' << 'macaddress' << '--value-only' + app.command_line.args << 'filesystems' << 'macaddress' << 'implementation' << 'clientcert' << 'clientversion' << 'clientnoop' << '--value-only' expect { app.run }.to exit_with(0) @@ -121,6 +125,10 @@ --- filesystems: apfs,autofs,devfs macaddress: 64:52:11:22:03:2e + implementation: #{Puppet.implementation} + clientcert: #{Puppet.settings[:certname]} + clientversion: #{Puppet.version} + clientnoop: false END before :each do diff --git a/spec/unit/indirector/facts/facter_spec.rb b/spec/unit/indirector/facts/facter_spec.rb index 49f2130c96..9c5947a524 100644 --- a/spec/unit/indirector/facts/facter_spec.rb +++ b/spec/unit/indirector/facts/facter_spec.rb @@ -192,12 +192,6 @@ class Puppet::Node::Facts::Facter::MyCollection < Hash; end @facter.find(@request) end - it 'should NOT add local facts' do - expect(facts).not_to receive(:add_local_facts) - - @facter.find(@request) - end - context 'when --show-legacy flag is present' do let(:options) { { resolve_options: true, user_query: ["os", "timezone"], show_legacy: true } }