Skip to content

Commit

Permalink
(PUP-11937) Skip autorequire if exec's param is deferred and lazily e…
Browse files Browse the repository at this point in the history
…valuated

If an exec's 'command' parameter is deferred and lazily evaluated, then we can't
autorequire the file that the command will execute. This is because we won't
know what the command will be until the exec is evaluated. But that means it's
already too late to add a relationship from the file resource to the exec
resource. In this situation an explicit relationship must be added to ensure
the file resource is evaluated before the exec. The same is true for the
'onlyif' and 'unless' exec parameters.
  • Loading branch information
joshcooper committed Nov 14, 2023
1 parent 1145d44 commit a316b92
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 7 deletions.
22 changes: 15 additions & 7 deletions lib/puppet/type/exec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -592,13 +592,17 @@ def check(value)
cmd = self[:command]
cmd = cmd[0] if cmd.is_a? Array

cmd.scan(file_regex) { |str|
reqs << str
}
if cmd.is_a?(Puppet::Pops::Evaluator::DeferredValue)
self.debug("The 'command' parameter is deferred and cannot be autorequired")
else
cmd.scan(file_regex) { |str|
reqs << str
}

cmd.scan(/^"([^"]+)"/) { |str|
reqs << str
}
cmd.scan(/^"([^"]+)"/) { |str|
reqs << str
}
end

[:onlyif, :unless].each { |param|
tmp = self[param]
Expand All @@ -613,7 +617,11 @@ def check(value)
# unqualified files, but, well, that's a bit more annoying
# to do.
line = line[0] if line.is_a? Array
reqs += line.scan(file_regex)
if line.is_a?(Puppet::Pops::Evaluator::DeferredValue)
self.debug("The '#{param}' parameter is deferred and cannot be autorequired")
else
reqs += line.scan(file_regex)
end
end
}

Expand Down
13 changes: 13 additions & 0 deletions spec/unit/type/exec_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,19 @@ def exec_stub(options = {})
expect(dependencies.collect(&:to_s)).to eq([Puppet::Relationship.new(tmp, execer).to_s])
end

it "skips autorequire for deferred commands" do
foo = make_absolute('/bin/foo')
catalog = Puppet::Resource::Catalog.new
tmp = Puppet::Type.type(:file).new(:name => foo)
execer = Puppet::Type.type(:exec).new(:name => 'test array', :command => Puppet::Pops::Evaluator::DeferredValue.new(nil))

catalog.add_resource tmp
catalog.add_resource execer
dependencies = execer.autorequire(catalog)

expect(dependencies.collect(&:to_s)).to eq([])
end

describe "when handling the path parameter" do
expect = %w{one two three four}
{ "an array" => expect,
Expand Down

0 comments on commit a316b92

Please sign in to comment.