Guidelines

This site is for tech Q&A. Please keep your posts focused on the subject at hand.

Ask one question at a time. Don't conflate multiple problems into a single question.

Make sure to include all relevant information in your posts. Try to avoid linking to external sites.

Links to documentation are fine, but in addition you should also quote the relevant parts in your posts.

0 votes
291 views
291 views

We're using Puppet Bolt for orchestrating jobs on our Puppet-managed systems. One of these jobs can be run either sequentially in parallel on the target systems:

if $sequential {
  $results = $nodes.each |$node| {
    run_task('my::job', $node, $params)
  }
} else {
  $results = run_task('my::job', $nodes, $params)
}

Parallel execution works fine and I get the results I expect. Sequential execution, however, gives me an error with the following message:

Evaluation Error: Unknown function: 'ok'.

This is the part of the code that throws the error:

unless $results.ok {
  # error-handling code
}

What am I doing wrong?

in Scripting
by (100)
1 13 28
edit history

Please log in or register to answer this question.

1 Answer

0 votes
 

run_task() returns a ResultSet, but if you inspect the $results after sequential execution (e.g. via notice($results)) you'll see that the each method mangled the list of ResultSet objects into a string array. To preserve the ResultSet objects from the task execution you need to replace each with map.

That alone won't solve the problem, though, because you'd then have an array of ResultSet objects that still doesn't have an ok method. To fix this you need to construct a new ResultSet object from all the returned results. The canonical approach to that would be to fetch all the results from each returned ResultSet object, then flatten the resulting jagged array before constructing the new ResultSet object. flatten() is needed here because without it you'd get another error that the ResultSet constructor doesn't accept a tuple as its argument.

$results = ResultSet(flatten($nodes.map |$node| {
  run_task('my::job', $node, $params).results
}))

However, in your particular case it would probably suffice to just pick the first result from each set, since you're running the task individually on each node so that each set will most likely contain just a single result anyway.

$results = ResultSet($nodes.map |$node| {
  run_task('my::job', $node, $params).first
})

edited by
by (100)
1 13 28
edit history
...