Skip to content

Commit beb4137

Browse files
committed
patch 2
1 parent 516870f commit beb4137

File tree

1 file changed

+38
-26
lines changed

1 file changed

+38
-26
lines changed

lib/puppet/provider/base_dsc_lite/powershell.rb

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
12
# frozen_string_literal: true
23

34
require 'pathname'
45
require 'json'
5-
require_relative '../../../puppet_x/puppetlabs/dsc_lite/powershell_hash_formatter'
66
require 'puppet/pops/evaluator/deferred_resolver'
77
require 'puppet/node/facts'
8+
require_relative '../../../puppet_x/puppetlabs/dsc_lite/powershell_hash_formatter'
89

910
Puppet::Type.type(:base_dsc_lite).provide(:powershell) do
1011
confine feature: :pwshlib
@@ -67,7 +68,9 @@ def ps_manager
6768
Pwsh::Manager.instance(command(:powershell), Pwsh::Manager.powershell_args, debug: debug_output)
6869
end
6970

70-
# Returns true if obj (or any nested value) is a DeferredValue
71+
# ===== NEW: Deferred helpers (instance methods) =====
72+
73+
# Detects if a value (or nested) contains a DeferredValue
7174
def deep_contains_deferred?(obj)
7275
case obj
7376
when Puppet::Pops::Evaluator::DeferredValue
@@ -87,47 +90,57 @@ def deep_contains_deferred?(obj)
8790
end
8891
end
8992

90-
# Resolve any lingering Deferred values in the `properties` parameter
91-
def resolve_properties_deferreds!
93+
# Force resolution of Deferreds across the catalog before script generation.
94+
# This mirrors Puppet's own preprocessing when preprocess_deferred=true.
95+
def ensure_deferreds_resolved!
96+
# (A) Prefer compiler-based resolution for properties when available
9297
props_param = resource.parameters[:properties]
93-
return unless props_param
94-
95-
props_val = props_param.value
96-
return unless deep_contains_deferred?(props_val)
97-
98-
# Prefer compiler-based resolution when available
99-
compiler = Puppet.lookup(:compiler) { nil }
100-
if compiler
101-
resolved = Puppet::Pops::Evaluator::DeferredResolver.resolve(props_val, compiler)
102-
resource[:properties] = resolved
103-
return
98+
compiler = Puppet.lookup(:compiler) { nil }
99+
100+
if props_param
101+
pv = props_param.value
102+
if deep_contains_deferred?(pv)
103+
Puppet.debug('DSC_lite: Deferred detected in properties; resolving via compiler') if compiler
104+
if compiler
105+
resolved = Puppet::Pops::Evaluator::DeferredResolver.resolve(pv, compiler)
106+
resource[:properties] = resolved
107+
end
108+
end
104109
end
105110

106-
# Fallback: resolve across the whole catalog in place (official API)
111+
# (B) Always run a full catalog resolution pass as a safety net.
107112
facts = Puppet::Node::Facts.new(
108113
(resource.catalog.respond_to?(:host) && resource.catalog.host) ||
109114
Facter.value(:fqdn) || Facter.value(:hostname) || 'localhost',
110115
Facter.to_hash,
111116
)
112117
env = resource.catalog.respond_to?(:environment_instance) ? resource.catalog.environment_instance : nil
113118

119+
Puppet.debug('DSC_lite: invoking DeferredResolver.resolve_and_replace on catalog')
114120
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(facts, resource.catalog, env, true)
115121

116-
# Refresh our local value after in-place resolution
117-
updated = resource.parameters[:properties]
118-
resource[:properties] = updated.value if updated
122+
# Post-check for diagnostics
123+
pp = resource.parameters[:properties]
124+
if pp && deep_contains_deferred?(pp.value)
125+
Puppet.debug('DSC_lite: WARNING — Deferred still present in properties after resolution pass')
126+
else
127+
Puppet.debug('DSC_lite: no Deferred values remain in properties after resolution')
128+
end
119129
rescue => e
120-
raise Puppet::Error, "DSC_lite: failed to resolve Deferred values in `properties`: #{e.class}: #{e.message}"
130+
# Raise a targeted error; this is better than failing later with "unsupported type DeferredValue"
131+
raise Puppet::Error, "DSC_lite: failed while resolving Deferred values: #{e.class}: #{e.message}"
121132
end
122133

134+
# ===== END NEW helpers =====
135+
123136
def exists?
124137
timeout = set_timeout
125138
Puppet.debug "Dsc Timeout: #{timeout} milliseconds"
126139
version = Facter.value(:powershell_version)
127140
Puppet.debug "PowerShell Version: #{version}"
128141

129-
# NEW: resolve any lingering DeferredValue in properties
130-
resolve_properties_deferreds!
142+
# NEW: ensure any lingering Deferreds are resolved before building the script
143+
ensure_deferreds_resolved!
131144

132145
script_content = ps_script_content('test')
133146
Puppet.debug "\n" + self.class.redact_content(script_content)
@@ -157,8 +170,8 @@ def create
157170
timeout = set_timeout
158171
Puppet.debug "Dsc Timeout: #{timeout} milliseconds"
159172

160-
# NEW: resolve any lingering DeferredValue in properties
161-
resolve_properties_deferreds!
173+
# NEW: ensure any lingering Deferreds are resolved before building the script
174+
ensure_deferreds_resolved!
162175

163176
script_content = ps_script_content('set')
164177
Puppet.debug "\n" + self.class.redact_content(script_content)
@@ -179,7 +192,6 @@ def create
179192
raise(data['errormessage']) unless data['errormessage'].empty?
180193

181194
notify_reboot_pending if data['rebootrequired'] == true
182-
183195
data
184196
end
185197

@@ -216,7 +228,7 @@ def self.redact_content(content)
216228
# always inside a hash table to be passed along. This means we can (currently) expect the value to
217229
# always come after an equals sign.
218230
# Note that the line may include a semi-colon and/or a newline character after the sensitive unwrap.
219-
content.gsub(%r{= '.+' # PuppetSensitive;?(\\n)?$}, "= '[REDACTED]'")
231+
content.gsub(%r{= '.+' # PuppetSensitive;?(\n)?$}, "= '[REDACTED]'")
220232
end
221233

222234
def ps_script_content(mode)

0 commit comments

Comments
 (0)