From c47de0311f851b8512183efa44b42c5ac04989b0 Mon Sep 17 00:00:00 2001 From: tvpartytonight Date: Mon, 29 Jul 2024 14:06:57 -0700 Subject: [PATCH] (PUP-12046) Send facts for `puppet catalog download` Facts were not always sent with the catalog request when using the catalog face. This change allows the face to send facts for the request so that the catalog returned is compiled with the correct set of facts. --- lib/puppet/face/catalog.rb | 32 +++++++++++++++------ lib/puppet/interface/action_manager.rb | 2 +- spec/unit/face/catalog_spec.rb | 39 ++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 spec/unit/face/catalog_spec.rb diff --git a/lib/puppet/face/catalog.rb b/lib/puppet/face/catalog.rb index 3a7ea1a975b..8966c38b4c9 100644 --- a/lib/puppet/face/catalog.rb +++ b/lib/puppet/face/catalog.rb @@ -25,13 +25,27 @@ deactivate_action(:destroy) deactivate_action(:search) - find = get_action(:find) - find.summary "Retrieve the catalog for the node from which the command is run." - find.arguments "" - find.returns <<-'EOT' - A serialized catalog. When used from the Ruby API, returns a - Puppet::Resource::Catalog object. - EOT + action(:find) do + summary _("Retrieve the catalog for the node from which the comamand is run.") + arguments ", " + option("--facts_for_catalog") do + summary _("Not yet implemented for the CLI; facts will be collected internally.") + end + returns <<-'EOT' + A serialized catalog. When used from the Ruby API, returns a + Puppet::Resource::Catalog object. + EOT + + when_invoked do |*args| + # Default the key to Puppet[:certname] if none is supplied + if args.length == 1 + key = Puppet[:certname] + else + key = args.shift + end + call_indirection_method :find, key, args.first + end + end action(:apply) do summary "Find and apply a catalog." @@ -135,9 +149,11 @@ when_invoked do |_options| Puppet::Resource::Catalog.indirection.terminus_class = :rest Puppet::Resource::Catalog.indirection.cache_class = nil + facts = Puppet::Face[:facts, '0.0.1'].find(Puppet[:certname]) catalog = nil retrieval_duration = thinmark do - catalog = Puppet::Face[:catalog, '0.0.1'].find(Puppet[:certname]) + catalog = Puppet::Face[:catalog, '0.0.1'].find(Puppet[:certname], + { facts_for_catalog: facts }) end catalog.retrieval_duration = retrieval_duration catalog.write_class_file diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb index f2c8a83baad..431a5b1be28 100644 --- a/lib/puppet/interface/action_manager.rb +++ b/lib/puppet/interface/action_manager.rb @@ -19,7 +19,7 @@ module Puppet::Interface::ActionManager # @dsl Faces def action(name, &block) @actions ||= {} - Puppet.warning _("Redefining action %{name} for %{self}") % { name: name, self: self } if action?(name) + Puppet.debug _("Redefining action %{name} for %{self}") % { name: name, self: self } if action?(name) action = Puppet::Interface::ActionBuilder.build(self, name, &block) diff --git a/spec/unit/face/catalog_spec.rb b/spec/unit/face/catalog_spec.rb new file mode 100644 index 00000000000..1f1282de79d --- /dev/null +++ b/spec/unit/face/catalog_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' +require 'puppet/face' +require 'puppet/indirector/facts/facter' +require 'puppet/indirector/facts/rest' + +describe Puppet::Face[:catalog, '0.0.1'] do + + describe '#download' do + let(:model) { Puppet::Node::Facts } + let(:test_data) { model.new('puppet.node.test', {test_fact: 'catalog_face_request_test_value'}) } + let(:catalog) { Puppet::Resource::Catalog.new('puppet.node.test', Puppet::Node::Environment.remote(Puppet[:environment].to_sym)) } + + before(:each) do + Puppet[:facts_terminus] = :memory + Puppet::Node::Facts.indirection.save(test_data) + allow(Puppet::Face[:catalog, "0.0.1"]).to receive(:save).once + + Puppet.settings.parse_config(<<-CONF) +[main] +server=puppet.server.test +certname=puppet.node.test +CONF + + # Faces start in :user run mode + Puppet.settings.preferred_run_mode = :user + end + + it "adds facts to the catalog request" do + stub_request(:post, 'https://puppet.server.test:8140/puppet/v3/catalog/puppet.node.test?environment=*root*') + .with( + headers: { 'Content-Type' => 'application/x-www-form-urlencoded' }, + body: hash_including(facts: URI.encode_www_form_component(Puppet::Node::Facts.indirection.find('puppet.node.test').to_json)) + ).to_return(:status => 200, :body => catalog.render(:json), :headers => {'Content-Type' => 'application/json'}) + subject.download + end + end +end + +