Plans in PE versus Bolt plans

Some plan language functions, features, and behaviors are different in PE compared to Bolt. If you are used to Bolt plans, familiarize yourself with some of these key differences and limitations before you attempt to write or run plans in PE.

Unavailable plan language functions

The following Bolt plan functions don't work in PE because they haven’t been implemented yet or cause issues during plan runs:
  • add_to_group
  • background
  • dir::children
  • download_file
  • file::exists
  • file::read
  • file::readable
  • file::write
  • get_resources
  • out::verbose
  • parallelize
  • prompt
  • prompt::menu
  • remove_from_group
  • resolve_references
  • resource
  • run_task_with
  • set_config
  • set_feature
  • set_resources
  • set_var
  • system::env
  • wait
  • write_file

Apply blocks

The apply feature, including apply_prep, only works for targets using the PXP agent and the PCP transport. It fails on remote devices and on targets connected via SSH or WinRM.

Target groups

Support for target groups is unavailable in PE. Using add_to_group causes a plan to fail and referencing a group name in get_targets doesn't return any nodes. When using get_targets you must reference either node certnames or supply a PuppetDB query. Here is an example of a plan using get targets with node certnames:
plan example::get_targets_example () {
  $nodes = get_targets([‘’, ‘’])
  run_command(‘whoami’, $nodes)

Target behaviors

  • PE assumes all target references can be matched to either a connected agent with a certname or an entry in the PE inventory service. Target names must match either a certname or an entry in the PE inventory service.
  • New targets cannot be added to the inventory service inside a plan. Any new target objects created in a plan won’t be able to connect as PE won’t recognize them.
  • Targets return an empty hash when asked about connection information.

Target configuration

While you can set up node transport configuration through the PE inventory for nodes to use SSH or WinRM, you can't change the configuration settings for targets from within a plan. Using the set_config function in a plan causes the plan to fail and referencing a target object’s configuration hash always returns an empty hash.

The use of URIs in a target name to override the transport is also not supported. All references to targets (i.e. when using get_targets) must be either PuppetDB queries or valid certnames that are already in the PE inventory.

Here is an example of a plan that uses get_targets correctly:
plan example::get_targets_example () {
  ## NOTE! If you used ssh:// as the first entry, this plan would fail!
  $nodes = get_targets([‘’, ‘’])
  run_command(‘whoami’, $nodes)

The localhost target

The special target localhost is not available for plans in PE. Using localhost anywhere in a plan results in a plan failure. If you need to run a plan on the primary server host, use the primary server's certname to reference it.

For example, you can use the following plan for the primary server host
plan example::referencing_the_primary_server(){
  # Note that if you tried to use `localhost` instead of `my-primary-server` this plan would fail!
  run_command(‘whoami’, ‘’)

The _run_as parameter

Plans in PE do not support the _run_as parameter for changing the user that accesses hosts or executes actions. If this parameter is supplied to any plan function, the plan runs but the user doesn't change.

For example, the following plan is valid, but can't run as other_user:
plan example::run_as_example (TargetSpec $nodes) {
  run_command(‘whoami’, $nodes, _run_as => ‘other_user’)

Script and file sources

When using run_script, download_file, or file::read the source location for the files must be from a module that uses a modulename/filename selector for a file or directory in $MODULEROOT/files. PE does not support file sources that reference absolute paths.

Here is an example of a module structure and a plan that correctly uses the modulename/filename selector:

├── files
└── plans
plan example::run_script_example (TargetSpec $nodes) {
  run_script(‘example/’, $nodes)

Code deployment for plans

For plans in PE to work, you must have code manager enabled to deploy code to your primary server.

Primary servers deploy a second codedir for plans to load code from. The second code location on primary servers have some effects on standard module functionality:

  • Installing modules using the puppet module install command doesn't work for plans because the puppet module tool won't install to the secondary location for plans. The puppet module install command still works for normal Puppet code executed and compiled from Puppet Server.

  • A $modulepath configuration that uses fully qualified paths might not work for plans if they reference the standard /etc/puppetlabs/code location. We recommend using relative paths in $modulepath.