PuppetLabs’ Bolt is an open-source orchestration tool that allows us to run multiple ad-hoc commands on our hosts over SSH — without the need for the Puppet configuration management tool at all! Bolt also lets us run pre-written tasks and overall configuration plans across our hosts, making it an ideal option for servers that cannot or do not currently support Puppet. This also means Bolt is an ideal solution for bootstrapping any nodes we want to include in our Puppet infrastructure.
In this hands-on lab, we’ll be crafting a Bolt plan that will allow us to install Puppet on any nodes we want to pull under our Puppet Enterprise setup. By doing this, we will gain experience writing Puppet tasks and plans, using the command line tool, and configuring Bolt on our workstation.
Learning Objectives
Successfully complete this lab by achieving the following learning objectives:
- Create the Hostname Task
From the workstation:
Move into the default location for adding custom modules to Bolt:
$ cd .puppetlabs/bolt/site-modules/
Use the PDK to create a new module called
base
; move into the new module’s directory when done:$ pdk new module base
$ cd baseWe’re going to write our task using a simple Bash script. Let’s call it
hostname
:$ pdk new task hostname
$ vim tasks/hostname.shCreate a script that uses the
hostnamectl
command and a user-provided variable for the actual desiredhostname
:!/bin/sh
hostnamectl set-hostname $PT_hostname
Save and exit.
Open the associated
tasks/hostname.json
file to define the parameters for our provided variable; update any additional fields as required:$ vim tasks/hostname.json
{
"puppet_task_version": 1,
"supports_noop": false,
"description": "Sets the hostname on our node",
"parameters": {
"hostname": {
"description": "The desired hostname"
}
}
}Save and exit.
- Create the Bootstrap Plan
Since the PDK does not support writing plans at this time, create a new
plans
directory:$ mkdir plans
We’re going to write our plan using the Puppet DSL, so create and open
plans/bootstrap.pp
:$ vim plans/bootstrap.pp
We want to first create our plan declaration:
plan base::bootstrap(
) {
}Next, we want to create our first step in our plan. Let’s call our
hostname
task. Note that instead of manually assigning our targets, we create a$node
variable:plan base::bootstrap(
TargetSpec $node,
TargetSpec $hostname,
) {run_task('base::hostname', $node, hostname => $hostname)
}
Add the
run_command
steps for our installation:plan base::bootstrap(
TargetSpec $node,
TargetSpec $hostname,
) {run_task('base::hostname', $node, hostname => $hostname) run_command("curl -k https://puppet.ec2.internal:8140/packages/current/install.bash -o /tmp/install.bash", $node)
}
Finally, add a step to approve the new node via the Puppet master:
plan base::bootstrap(
TargetSpec $node,
TargetSpec $hostname,
) {
run_task(‘base::hostname’, $node, hostname => $hostname)
run_command("curl -k https://puppet.ec2.internal:8140/packages/current/install.bash -o /tmp/install.bash", $node)
run_command("bash /tmp/install.bash", $node)
run_command("puppetserver ca sign –all", "puppet.ec2.internal")
}Save and exit the file.
- Run the Plan
We first need to create a new key pair to use with our Puppet master and node; use all default options (setting no password):
$ ssh-keygen
Copy the key to both the Ubuntu node and the master:
$ ssh-copy-id cloud_user@PUBLIC_ID_OF_UBUNTU_NODE
$ ssh-copy-id cloud_user@puppet.ec2.internalLet’s now run our plan:
$ bolt plan run base::bootstrap hostname=web1.ec2.internal node=PUBLIC_ID_OF_UBUNTU_NODE –tty –run_as root –sudo_password
Note that we use
run_as
andsudo_password
to switch toroot
. Notice, too, the use of the--tty
flag to create a pseudo TTY during the creation process — this prevents an error during the installation of Puppet (especially with the use ofsudo bash
).The plan has run without issue. If we want to confirm our work further, we can log in via SSH to the Puppet master and view the available certs:
$ sudo puppetserver ca list --all