NOTE: this article is somewhat outdated. Please refer to Serverless Puppet with control repo, Hiera, roles and profiles and Puppet Bolt instead.
Puppet Bolt is an orchestration tool similar to Ansible. It is suitable for multiple use-cases:
- Running ad hoc commands on target nodes. We use this approach for testing Puppet feature branches before approving and merging them.
- One-off configurations written in the Puppet language
- Masterless Puppet environments (look here). You may not always have enough privileges, trust or will to manage a complete Puppet infrastructure including Puppetserver, PuppetDB and Puppet Agents.
- Orchestration, i.e. running tasks on multiple servers (example here).
There is quite a bit of documentation on Puppet Bolt, but cobbling it all together takes a bit of effort. Starting with Bolt Hands-on Lab and the official documentation is advised. This article shows how to accomplish steps 1-3, above, in the context of an existing Puppet control repository and assumes a fair bit of Puppet knowledge.
The first step is to install Puppet Bolt. After that you need to add bolt.yaml and inventory.yaml to the root of your control repository. A minimal bolt.yaml might look like this:
concurrency: 3 format: human ssh: host-key-check: false
The presence of bolt.yaml makes the "bolt" executable realize that the root of the control repository is the Boltdir.
The next step is to add inventory.yaml which can be quite simple:
---
version: 2
groups:
- name: vagrant
targets:
- bolt
Here we define a single group which contain a single (Vagrant) node. Setting up a Vagrant environment for Bolt testing is covered in the hands-on lab. If you can do "ssh bolt-test" you are ready to try Bolt for ad hoc commands from the root of the control-repository (a.k.a. "Boltdir"):
bolt command run "date" --target vagrant Started on bolt… Finished on bolt: STDOUT: Mon Mar 30 11:02:17 UTC 2020 Successful on 1 target: bolt Ran on 1 target in 0.34 sec
Now we know that connectivity and Bolt in general is working fine. The next step is to apply an ad hoc manifest. Let's add site/profile/plans/simple_file.pp with this content:
plan profile::simple_file
(
TargetSpec $nodes,
String $file_content,
)
{
$nodes.apply_prep
apply($nodes) {
file { '/foobar':
content => $file_content,
}
}
}
The TargetSpec parameters gets populated by Bolt based on the --target parameter. The $file_content parameter needs to be passed on the Bolt command-line:
$ bolt plan run profile::simple_file file_content=foobar --target vagrant --run-as root Starting: plan profile::simple_file Starting: install puppet and gather facts on bolt Finished: install puppet and gather facts with 0 failures in 4.63 sec Starting: apply catalog on bolt Finished: apply catalog with 0 failures in 6.81 sec Finished: plan profile::simple_file in 11.46 sec Plan completed successfully with no result
In this particular case we can easily check the results with an ad hoc command:
$ bolt command run "cat /foobar" --target vagrant Started on bolt… Finished on bolt: STDOUT: foobar Successful on 1 target: bolt Ran on 1 target in 0.35 sec
As we can see, the file was created successfully. However, we will immediately run into trouble if we try to use external Puppet modules. While Bolt includes Puppet's core resources and modules, it depends on a Puppetfile for the rest. For example this plan would not work out of the box:
plan profile::bash_prompt ( TargetSpec $nodes, String $prefix, ) { $nodes.apply_prep apply($nodes) { class { '::bash_prompt': prefix => $prefix, } } }
If we try to apply this we get a failure:
$ bolt plan run profile::bash_prompt prefix=foobar --target vagrant --run-as root Starting: plan profile::bash_prompt Starting: install puppet and gather facts on bolt Finished: install puppet and gather facts with 0 failures in 1.91 sec Starting: apply catalog on bolt Finished: apply catalog with 1 failure in 1.93 sec Finished: plan profile::bash_prompt in 3.86 sec Failed on bolt: Apply failed to compile for bolt: Could not find declared class ::bash_prompt (file: /home/samuli/opt/bolt-test/site/profile/plans/bash_prompt.pp, line: 10, column: 5) Failed on 1 target: bolt Ran on 1 target
Fortunately we already have a Puppetfile in our control repository, so all we have to do is to install the external modules:
$ bolt puppetfile install
That command installs all the modules in the Puppetfile locally, after which you can use them in your plans.
Bolt can also use data from Hiera - you just need to do lookups from within the apply block and ensure that you Hiera levels are useful in conjunction with nodes that don't have certificates and hence $trusted.certname.