Skip to content

Commit c64132d

Browse files
Merge pull request #8940 from joshcooper/legacy_facts_11662
(PUP-11662) Allow legacy facts to be excluded
2 parents 95291a9 + 6e90bd0 commit c64132d

File tree

4 files changed

+122
-1
lines changed

4 files changed

+122
-1
lines changed

lib/puppet/defaults.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,14 @@ def self.initialize_default_settings!(settings)
17121712
new configurations, where you want to fix the broken configuration
17131713
rather than reverting to a known-good one.",
17141714
},
1715+
:include_legacy_facts => {
1716+
:type => :boolean,
1717+
:default => true,
1718+
:desc => "Whether to include legacy facts when requesting a catalog. This
1719+
option can be set to false provided all puppet manifests, hiera.yaml and hiera
1720+
configuration layers no longer access legacy facts, such as `$osfamily`, and
1721+
instead access structured facts, such as `$facts['os']['family']`."
1722+
},
17151723
:fact_name_length_soft_limit => {
17161724
:default => 2560,
17171725
:type => :integer,

lib/puppet/indirector/facts/facter.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ def find(request)
3535
result = if request.options[:resolve_options]
3636
raise(Puppet::Error, _("puppet facts show requires version 4.0.40 or greater of Facter.")) unless Facter.respond_to?(:resolve)
3737
find_with_options(request)
38-
else
38+
elsif Puppet[:include_legacy_facts]
39+
# to_hash returns both structured and legacy facts
3940
Puppet::Node::Facts.new(request.key, Puppet.runtime[:facter].to_hash)
41+
else
42+
# resolve does not return legacy facts unless requested
43+
Puppet::Node::Facts.new(request.key, Puppet.runtime[:facter].resolve(''))
4044
end
4145

4246
result.add_local_facts unless request.options[:resolve_options]

spec/integration/application/agent_spec.rb

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,4 +897,103 @@ def copy_fixtures(sources, dest)
897897
end
898898
end
899899
end
900+
901+
context "legacy facts" do
902+
let(:mod_dir) { tmpdir('module_dir') }
903+
let(:custom_dir) { File.join(mod_dir, 'lib') }
904+
let(:external_dir) { File.join(mod_dir, 'facts.d') }
905+
906+
before(:each) do
907+
# don't stub facter behavior, since we're relying on
908+
# `Facter.resolve` to omit legacy facts
909+
Puppet::Node::Facts.indirection.terminus_class = :facter
910+
911+
facter_dir = File.join(custom_dir, 'facter')
912+
FileUtils.mkdir_p(facter_dir)
913+
File.write(File.join(facter_dir, 'custom.rb'), <<~END)
914+
Facter.add(:custom) { setcode { 'a custom value' } }
915+
END
916+
917+
FileUtils.mkdir_p(external_dir)
918+
File.write(File.join(external_dir, 'external.json'), <<~END)
919+
{"external":"an external value"}
920+
END
921+
922+
# avoid pluginsync'ing contents
923+
FileUtils.mkdir_p(Puppet[:vardir])
924+
FileUtils.cp_r(custom_dir, Puppet[:vardir])
925+
FileUtils.cp_r(external_dir, Puppet[:vardir])
926+
end
927+
928+
def mounts
929+
{
930+
# the server needs to provide metadata that matches what the agent has
931+
# so that the agent doesn't delete them during pluginsync
932+
file_metadatas: -> (req, res) {
933+
path = case req.path
934+
when /pluginfacts/
935+
external_dir
936+
when /plugins/
937+
custom_dir
938+
else
939+
raise "Unknown mount #{req.path}"
940+
end
941+
request = Puppet::FileServing::Metadata.indirection.request(
942+
:search, path, nil, recurse: true
943+
)
944+
data = Puppet::FileServing::Metadata.indirection.terminus(:file).search(request)
945+
res.body = formatter.render(data)
946+
res['Content-Type'] = formatter.mime
947+
},
948+
catalog: -> (req, res) {
949+
data = CGI.unescape(req.query['facts'])
950+
facts = Puppet::Node::Facts.convert_from('json', data)
951+
node.fact_merge(facts)
952+
953+
catalog = compile_to_catalog(<<~MANIFEST, node)
954+
notify { "legacy $osfamily": }
955+
notify { "custom ${facts['custom']}": }
956+
notify { "external ${facts['external']}": }
957+
MANIFEST
958+
959+
res.body = formatter.render(catalog)
960+
res['Content-Type'] = formatter.mime
961+
}
962+
}
963+
end
964+
965+
it "includes legacy facts by default" do
966+
server.start_server(mounts: mounts) do |port|
967+
Puppet[:serverport] = port
968+
969+
agent.command_line.args << '--test'
970+
expect {
971+
agent.run
972+
}.to exit_with(2)
973+
.and output(
974+
match(/defined 'message' as 'legacy [A-Za-z]+'/)
975+
.and match(/defined 'message' as 'custom a custom value'/)
976+
.and match(/defined 'message' as 'external an external value'/)
977+
).to_stdout
978+
end
979+
end
980+
981+
it "can exclude legacy facts" do
982+
server.start_server(mounts: mounts) do |port|
983+
Puppet[:serverport] = port
984+
Puppet[:include_legacy_facts] = false
985+
986+
agent.command_line.args << '--test'
987+
expect {
988+
agent.run
989+
}.to exit_with(2)
990+
.and output(
991+
match(/defined 'message' as 'legacy '/)
992+
.and match(/defined 'message' as 'custom a custom value'/)
993+
.and match(/defined 'message' as 'external an external value'/)
994+
).to_stdout
995+
.and output(/Warning: Unknown variable: 'osfamily'/).to_stderr
996+
end
997+
end
998+
end
900999
end

spec/unit/indirector/facts/facter_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@
8383

8484
@facter.find(@request)
8585
end
86+
87+
it "can exclude legacy facts" do
88+
Puppet[:include_legacy_facts] = false
89+
90+
facts = Puppet::Node::Facts.new("foo")
91+
expect(Puppet::Node::Facts).to receive(:new).and_return(facts)
92+
expect(Puppet.runtime[:facter]).to receive(:resolve).with('')
93+
94+
@facter.find(@request)
95+
end
8696
end
8797

8898
it 'should fail when saving facts' do

0 commit comments

Comments
 (0)