🧪 Experimental features

Can you spare 4 or 5 minutes to help us improve our documentation?

Most larger Bolt features are released initially in an experimental or unstable state. This allows the Bolt team to gather feedback from real users quickly while iterating on new functionality. Almost all experimental features are eventually stabilized in future releases. While a feature is experimental, its API may change, requiring the user to update their code or configuration. The Bolt team attempts to make these changes painless by providing useful warnings around breaking behavior where possible.

ResourceInstance data type

This feature was introduced in Bolt 2.10.0.

Bolt has had a limited ability to interact with Puppet's Resource Abstraction Layer. You could use the apply function to generate catalogs and return events, and the get_resources plan function can be used to query resources on a target. The ResourceInstance data type is the first step in enabling plan authors to build resource-based logic into their plans to enable a discover-inspect-execute workflow for interacting with resources on remote systems.

Use the ResourceInstance data type is used to store information about a single resource on a target, including its observed state, desired state, and any related events.

Note:: The ResourceInstance data type does not interact with or modify resources in any way. It is only used to store information about a resource.

Creating ResourceInstance objects


The recommended way to create ResourceInstance objects is by setting them directly on a Target object using the Target.set_resources function. Use the function to set one or more resources on a target at a time. You can read more about this function in Bolt plan functions.

The Target.set_resources function can set existing ResourceInstance objects on a target, or take hashes of parameters to create new ResourceInstance objects and automatically set them on a target.

When setting resources using a hash of parameters, you can pass either a single hash or an array of hashes:

$init_hash = {
  'target'        => Optional[Target],
  'type'          => Variant[String[1], Type[Resource]],
  'title'         => String[1],
  'state'         => Optional[Hash[String[1], Data]],
  'desired_state' => Optional[Hash[String[1], Data]],
  'events'        => Optional[Array[Hash[String[1], Data]]]

  Variant[Hash[String[1], Any], Array[Hash[String[1], Any]]] init_hash

Note: When passing a data hash to Target.set_resources, the target parameter is optional. If the target parameter is not specified, the function automatically sets the target to the target the function is called on.

Note: If the target parameter is any target other than the one you are setting the resource on, Bolt will raise an error.

When setting resources using existing ResourceInstance objects, you can pass either a single ResourceInstance or an array of ResourceInstance objects.

$resource = ResourceInstance.new(...)

  Variant[ResourceInstance, Array[ResourceInstance]] resource

Note: If the target for a ResourceInstance does not match the target it is being set on, Bolt will raise an error.

A target can only have a single instance of a given resource. If you set a duplicate resource on a target, Bolt shallow merges the state and desired_state of the duplicate resource with the state and desired_state of the existing resource and adds any events for the duplicate resource to the existing resource.


You can also create standalone ResourceInstance objects without setting them directly on a target using the new function.

The new function accepts either positional arguments:

  Target                                 target,
  Variant[String[1], Type[Resource]]     type,
  String[1]                              title,
  Optional[Hash[String[1], Data]]        state,
  Optional[Hash[String[1], Data]]        desired_state,
  Optional[Array[Hash[String[1], Data]]] events

or a hash of arguments:

$init_hash = {
  'target'        => Target,
  'type'          => Variant[String[1], Type[Resource]],
  'title'         => String[1],
  'state'         => Optional[Hash[String[1], Data]],
  'desired_state' => Optional[Hash[String[1], Data]],
  'events'        => Optional[Array[Hash[String[1], Data]]]

  Hash[String[1], Any] init_hash

Accessing ResourceInstance object on a Target

You can retrieve a specific ResourceInstance object stored on a Target in a plan using the resource() function:

$packages = $target.get_resources(Package).first['resources']
$resource = $target.resource(Package, 'openssl')


Each ResourceInstance has the following attributes:

targetThe target that the resource is for.Target
typeThe type of the resource. This can be either the stringified name of the resource type or the actual type itself. For example, both "file" and File are acceptable.Variant[String[1], Type[Resource]]
titleThe title, or namevar, of the resource.String[1]
stateThe observed state of the resource. This is the point-in-time state of the resource when it is queried.Hash[String[1], Data]
desired_stateThe desired state of the resource. This is the state that you want the resource to be in.Hash[String[1], Data]
eventsResource events that are generated from reports.Array[Hash[String[1], Data]]

A ResourceInstance is identified by its target, type, and title. As such, these three parameters must be specified when creating a new ResourceInstance and are immutable. Since Target.set_resources will automatically set the target when passing a hash of parameters, the target parameter can be ommitted.

The state, desired_state, and events parameters are optional when creating a ResourceInstance. If you do not specify state and desired_state, they default to empty hashes, while events defaults to an empty array. You can modify each of these attributes during the lifetime of the ResourceInstance using the data type's functions.


The ResourceInstance data type has several built-in functions. These range from accessing the object's attributes to modifying and overwriting state. For a full list of the available functions, see Bolt data types.

Example usage

You can easily set a resource on a set of targets. For example, if you want to ensure that a file is present on each target:

$resource = {
  'type'  => File,
  'title' => '/etc/puppetlabs/bolt.yaml',
  'desired_state' => {
    'ensure'  => 'present',
    'content' => "..."

$targets.each |$target| {

You can also combine the get_resources plan function with Target.set_resources to query resources on a target and set them on the corresponding Target objects:

$results = $targets.get_resources([Package, User])

$results.each |$result| {

The set_resources function will return an array of ResourceInstance objects, which can be used to easily examine attributes for multiple resources and perform actions based on those attributes. For example, you can iterate over an array of resources to determine which users need to have their maxium password age modified:

$results = $target.get_resources(User)

$results.each |$result| {
  $resources = $result.target.set_resources($result['resources'])

  $users = $resources.filter |$resource| { $resource.state['password_max_age'] > 90 }
                     .map |$resource| { $resource.title }

  run_task('update_password_max_age', $result.target, 'users' => $users)

Apply blocks will also return results with reports. These reports have resource data hashes that can be used to set resources on a target:

$apply_results = apply($targets) {
  File { '/etc/puppetlabs':
    ensure => present
  Package { 'openssl':
    ensure => installed

$apply_results.each |$result| {

Native SSH transport

This feature was introduced in Bolt 2.10.0.

Bolt's SSH transport uses the ruby library net-ssh, which is a pure ruby implementation of the SSH2 client protocol. While robust, the library lacks support for some features and algorithms that are available in native SSH. When you use the native SSH transport, Bolt uses the SSH executable you've specified instead of using net-ssh. Essentially, using the native SSH transport is the same as running SSH on your command line, but with Bolt managing the connections.

To use the native SSH transport, set ssh-command: <SSH> in bolt.yaml, where <SSH> is the SSH command to run. For example:

  ssh-command: 'ssh'

The value of ssh-command can be either a string or an array, and you can provide any command-line options to the command. Bolt will append Bolt-configuration settings to the command, as well as the specified target, when connecting. Not all Bolt configuration options are supported using the native SSH transport, but you can configure most options in your OpenSSH Config. See bolt configuration reference for the list of supported Bolt SSH options.

Bolt transports have two main functions: executing remotely, and copying files to the remote targets. ssh-command is what configures the remote execution, and copy-command configures the copy command. The default is scp -r, and rsync is not supported at this time.

For example:

  ssh-command: 'ssh'
  copy-command: 'scp -r -F ~/ssh-config/myconf'

Connecting with SSH configuration not supported by net-ssh

You can use the native SSH transport to connect to targets using configuration that isn't supported by the Ruby net-ssh library. Configure the settings for the transport in your inventory file, or use your local SSH config.

Using an inventory file to specify SSH configuration

To encrypt SSH connections using the unsupported algorithm chacha20-poly1305@openssh.com, add the SSH command and cypher option to your inventory file:

# inventory.yaml
      - 'ssh'
      - '-o Ciphers=chacha20-poly1305@openssh.com'

Using ~/.ssh/config to specify SSH configuration

To encrypt SSH connections using the unsupported algorithm chacha20-poly1305@openssh.com:

  1. Store the following config in your SSH config at ~/.ssh/config as:

  2. In your inventory file, configure Bolt to use the SSH shell command:

    # inventory.yaml
        ssh-command: 'ssh'

Note: While some OpenSSH config options are supported in net-ssh, such as Ciphers, the specific algorithms you want to use may not be supported and you will still need to use the ssh-command option to shell out to SSH. See the net-ssh README for a list of supported algorithms.

bolt plan new command

This feature was introduced in Bolt 2.22.0.

Use the bolt plan new command or New-BoltPlan PowerShell cmdlet to generate a new project-level YAML plan. The command accepts a single argument: the name of the plan. To use the bolt plan new command or New-BoltPlan PowerShell cmdlet, you must have a named Bolt project.

Naming plans

The plan name is used to identify and call the plan from the Bolt command line or from other plans. Plan names are composed of one or more name segments separated by a double colon ::.

Each plan name segment must begin with a lowercase letter, and may only include lowercase letters, digits, and underscores.

Additionally, the first name segment of any new plan must match the name of the project itself. For example, given a project named myproject, the following plan names are valid:

  • myproject

  • myproject::myplan

  • myproject::my_plan

And the following plan names are invalid:

  • myplan

  • myproject::MyPlan

  • myproject::1_myplan

  • myproject::my-plan

init plans

Plan names that match the project name will create a special init plan. For example, if you have a project named myproject and run the command bolt plan new myproject, a plan will be created at <PROJECT DIRECTORY>/plans/init.yaml.

You can reference the init plan using the project's name. For example, you would run this plan using bolt plan run myproject.

Puppet sites use proprietary and third-party cookies. By using our sites, you agree to our cookie policy.