Exported Resources and Evaluation in Puppet

I recently ran into an interesting “gotcha” within Puppet with regards to exported resources and parameter evaluation.

For a quick refresher, Puppet defines exported resources as resources that are not evaluated and exported for collection by another catalog. Take Nagios, for example. You can create several nodes with exported Nagios configurations that are then collected by a Nagios node. For more information, review the puppet documentation on exported resources.

The Gotcha – Exported Resources and their Parameters

I encountered the problem when attempting to collect resources by a parameter, which should be valid.

For example, I built the following resource that I planned to export:

define profiles::gitlab_runner::cloud_app_config_tab::app_env
(
  String $app_name = $title,
  Array $app_env_secrets = [],
  Hash $app_env = {},
)
{ ... }

Note that I set the app_name above to default to the title of the resource. I later attempted to export an instance of that type:

@@profiles::gitlab_runner::cloud_app_config_tab::app_env { 'foobar' :
  app_env_secrets => $secrets,
  app_env         => $env,
}

For the final piece, I built a CI runner configuration that collected specific instances of that exported defined type:

Profiles::Gitlab_runner::Cloud_app_config_tab::App_env <<| app_name == 'foobar' |>>

I ran the Puppet agent on both the exporting and collecting nodes. The agent created no resources. What did I do wrong?

I queried our PuppetDB instance and found an issue- Puppet created my exported resources; but, the export only set app_env_secrets and app_env. Why?

It turns out that I’d run against a nuance of evaluation time vs export time. At export time, default parameter settings are NOT evaluated into expressions. On the other hand, Puppet stores the values of explicitly set variables so that the resource can be evaluated. This creates the problem I saw earlier: puppet doesn’t assign the value of $title to app_name until it evaluates the resource. Evaluation occurs AFTER collection.

The Solution

I solved the issue by collecting resources based on either their parameter values or the titles (since I expect titles to match the app_name parameter).

Profiles::Gitlab_runner::Cloud_app_config_tab::App_env <<| app_name == 'foobar' or title == 'foobar' |>>

When utilizing exported resources, try to keep in mind which values will be set and available at evaluation time vs export time. Puppet won’t evaluate or set any parameters to their defaults until after it collects them.

Continue Reading