Plans in PE versus Bolt plans

Some plan language functions, features, and behaviors are different in PE than they are in 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::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 one of the following:
  • A connected agent with a certname
  • An entry in the PE inventory service
Therefore, target names must match either a certname or an entry in the PE inventory service.

New targets can't be added to the inventory service inside a plan. New target objects created in plans can't connect because PE can'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 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.

The following two code examples show a module structure and a plan that correctly use the modulename/filename selector:
├── files
└── plans
plan example::run_script_example (TargetSpec $nodes) {
  run_script(‘example/’, $nodes)

Code deployment for plans

Using plans in PE requires Managing code with Code Manager. You must enable Code Manager to deploy code to your primary server.

Primary servers deploy a second codedir from which plans load code. This secondary code location on your primary server impacts standard module functionality:
  • You can't use the puppet module install command to install modules for plans, because the puppet module tool can't install to the plan codedir. However, the puppet module install command works as usual for non-plan 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. It is more reliable to use relative paths in $modulepath.