Skip to content

Commit

Permalink
Support arrays of deferred parameter values
Browse files Browse the repository at this point in the history
If an `exec` resource's `environment` parameter was specified as an
array of values, where at least one of the values was deferred, then
validation failed with:

    undefined method `=~' for #<Puppet::Pops::Evaluator::DeferredValue:0x00007ff6913f7908

This occurred because the transaction's `resolved_resolve` assumed the
parameter's value was single-valued. As a result, the deferred value
was never resolved before calling the type's `validate` method.

This updates the transaction to support multi-valued parameters. All
deferred values will be resolved before the type's `validate` method is
called.

Fixes puppetlabs#9438
  • Loading branch information
joshcooper committed Sep 25, 2024
1 parent 1fba250 commit 351db42
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
6 changes: 3 additions & 3 deletions lib/puppet/parameter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ def unsafe_munge(value)
# @return [Object] the unmunged value
#
def unmunge(value)
return value if value.is_a?(Puppet::Pops::Evaluator::DeferredValue)
return value if value.is_a?(Puppet::Pops::Evaluator::DeferredValue) || (value.is_a?(Array) && value.any? { |v| v.is_a?(Puppet::Pops::Evaluator::DeferredValue) })

unsafe_unmunge(value)
end
Expand All @@ -438,7 +438,7 @@ def unsafe_unmunge(value)
# @return [Object] the munged (internal) value
#
def munge(value)
return value if value.is_a?(Puppet::Pops::Evaluator::DeferredValue)
return value if value.is_a?(Puppet::Pops::Evaluator::DeferredValue) || (value.is_a?(Array) && value.any? { |v| v.is_a?(Puppet::Pops::Evaluator::DeferredValue) })

begin
ret = unsafe_munge(value)
Expand Down Expand Up @@ -473,7 +473,7 @@ def unsafe_validate(value)
# @api public
#
def validate(value)
return if value.is_a?(Puppet::Pops::Evaluator::DeferredValue)
return value if value.is_a?(Puppet::Pops::Evaluator::DeferredValue) || (value.is_a?(Array) && value.any? { |v| v.is_a?(Puppet::Pops::Evaluator::DeferredValue) })

begin
unsafe_validate(value)
Expand Down
17 changes: 13 additions & 4 deletions lib/puppet/transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -473,12 +473,21 @@ def resolve_resource(resource)
deferred_validate = false

resource.eachparameter do |param|
# Puppet::Parameter#value= triggers validation and munging. Puppet::Property#value=
# overrides the method, but also triggers validation and munging, since we're
# setting the desired/should value.
if param.value.instance_of?(Puppet::Pops::Evaluator::DeferredValue)
# Puppet::Parameter#value= triggers validation and munging. Puppet::Property#value=
# overrides the method, but also triggers validation and munging, since we're
# setting the desired/should value.
resolved = param.value.resolve
# resource.notice("Resolved deferred value to #{resolved}")
param.value = resolved
deferred_validate = true
elsif param.value.is_a?(Array) && param.value.any? { |v| v.instance_of?(Puppet::Pops::Evaluator::DeferredValue) }
resolved = param.value.map do |v|
if v.instance_of?(Puppet::Pops::Evaluator::DeferredValue)
v.resolve
else
v
end
end
param.value = resolved
deferred_validate = true
end
Expand Down
17 changes: 17 additions & 0 deletions spec/integration/application/apply_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,23 @@ def bogus()
.and output(/Validation of File.* failed: You cannot specify more than one of content, source, target/).to_stderr
end

it "validates multi-valued parameters" do
manifest = <<~END
$password = Deferred('new', [Sensitive, 'opensesame'])
exec { '/usr/bin/echo \$ADMIN_PASSWORD':
logoutput => true,
environment => [
Deferred('inline_epp', ['ADMIN_PASSWORD=<%= $password %>', { 'password' => $password }]),
],
}
END
apply.command_line.args = ['-e', manifest]
expect {
apply.run
}.to exit_with(0)
.and output(%r{Exec\[/usr/bin/echo \$ADMIN_PASSWORD\]/returns: opensesame}).to_stdout
end

it "applies deferred sensitive file content" do
manifest = <<~END
file { '#{deferred_file}':
Expand Down

0 comments on commit 351db42

Please sign in to comment.