From c7ef3a0ad79fb329619d493eb2b0f34ee02d4736 Mon Sep 17 00:00:00 2001 From: griggi-ws Date: Wed, 25 Feb 2026 15:59:57 -0500 Subject: [PATCH 1/2] add: testing for Deferred resolution of Puppet-language functions Signed-off-by: griggi-ws --- .../pops/evaluator/deferred_resolver_spec.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/spec/unit/pops/evaluator/deferred_resolver_spec.rb b/spec/unit/pops/evaluator/deferred_resolver_spec.rb index 4cb98cc798..f55c75d228 100644 --- a/spec/unit/pops/evaluator/deferred_resolver_spec.rb +++ b/spec/unit/pops/evaluator/deferred_resolver_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' require 'puppet_spec/compiler' +require 'puppet_spec/files' Puppet::Type.newtype(:test_deferred) do newparam(:name) @@ -8,8 +9,14 @@ describe Puppet::Pops::Evaluator::DeferredResolver do include PuppetSpec::Compiler + include PuppetSpec::Files - let(:environment) { Puppet::Node::Environment.create(:testing, []) } + let(:env_dir) do + dir_containing('testing', 'modules' => { + 'testmod' => { 'functions' => { 'test.pp' => 'function testmod::test($x) { "Got: ${x}" }' } } + }) + end + let(:environment) { Puppet::Node::Environment.create(:testing, [File.join(env_dir, 'modules')]) } let(:facts) { Puppet::Node::Facts.new('node.example.com') } def compile_and_resolve_catalog(code, preprocess = false) @@ -95,4 +102,14 @@ def compile_and_resolve_catalog(code, preprocess = false) resource = catalog.resource(:test_deferred, 'deferred') expect(resource.sensitive_parameters).to eq([:value]) end + + it 'resolves deferred values that call Puppet language functions' do + catalog = compile_and_resolve_catalog(<<~END, true) + notify { "deferred": + message => Deferred("testmod::test", ["hello"]) + } + END + + expect(catalog.resource(:notify, 'deferred')[:message]).to eq('Got: hello') + end end From 409b81a1b24b6a31537a1561e4354f4e2efad1e1 Mon Sep 17 00:00:00 2001 From: griggi-ws Date: Wed, 25 Feb 2026 16:01:53 -0500 Subject: [PATCH 2/2] fix: ensure global_context is available in Deferred resolution of Puppet-lang functions Signed-off-by: griggi-ws --- lib/puppet/pops/evaluator/deferred_resolver.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/puppet/pops/evaluator/deferred_resolver.rb b/lib/puppet/pops/evaluator/deferred_resolver.rb index ace0400dff..27a72a7059 100644 --- a/lib/puppet/pops/evaluator/deferred_resolver.rb +++ b/lib/puppet/pops/evaluator/deferred_resolver.rb @@ -48,7 +48,10 @@ def self.resolve_and_replace(facts, catalog, environment = catalog.environment_i # # Server facts are always about the local node's version etc. # @scope.set_server_facts(node.server_facts) - resolver.resolve_futures(catalog) + # Must be wrapped in with_context_overrides to ensure global_scope is valid for Puppet-language functions + compiler.with_context_overrides do + resolver.resolve_futures(catalog) + end nil end