Writing Tasks

Difficulty: Basic

Time: Approximately 15 minutes

In this exercise you will write your first Bolt Tasks for use with Bolt.

Prerequisites

Complete the following before you start this lesson:

How Do Tasks Work?

Tasks are scripts with optional metadata, and can be implemented in any language that runs on your targets. Tasks are stored and shared in Puppet modules. By giving your script metadata and including it in a Puppet module, tasks make scripts easy to reuse and share. You can upload and download tasks in modules from the Puppet Forge, run them from GitHub, or use them locally to organize your regularly used commands.

Tasks are stored in the tasks directory of a module, a module being a directory with a unique name. You can have several tasks per module, but the init task is special and runs by default if you do not specify a task name.

By default tasks take arguments as environment variables prefixed with PT.

Write Your First Task in Bash

This exercise uses sh, but you can use Perl, Python, Lua, or JavaScript or any language that can read environment variables or take content on stdin.

Save the following to Boltdir/site-modules/exercise5/tasks/init.sh:

#!/bin/sh

echo $(hostname) received the message: $PT_message

By default, Bolt will search both the modules and site-modules directories in a Bolt project directory for a matching task name. Typically, any project-specific tasks will be saved to the site-modules directory.

Run the exercise5 task. Note the message argument. This will be expanded to the PT_message environment variable expected by our task. By naming parameters explicitly it’s easier for others to use your tasks.

bolt task run exercise5 message=hello --targets target1

The result:

Started on target1...
Finished on target1:
  localhost.localdomain received the message: hello
  {
  }
Successful on 1 target: target1
Ran on 1 target in 0.99 seconds

Run the Bolt command with a different value for message and see how the output changes.

Write Your First Task in PowerShell

If you’re targeting Windows targets then you might prefer to implement the task in PowerShell.

Save the following as Boltdir/site-modules/exercise5/tasks/print.ps1:

param ($message)
Write-Output "$env:computername received the message: $message"

Run the exercise5 task. Note that since the task is not named init, you must prepend the name of the task with the name of its module like so module::task.

bolt task run exercise5::print message="hello powershell" --targets windows

The result:

Started on localhost...
Finished on localhost:
  Nano received the message: hello powershell
  {
  }
Successful on 1 target: winrm://localhost:55985
Ran on 1 target in 3.87 seconds

Note:

Write Your First Task in Python

When running a task, Bolt assumes that the required runtime is already available on the targets. For the following examples to work, Python 2 or 3 must be installed on the targets. This task will also work on Windows system with Python 2 or 3 installed.

Save the following as Boltdir/site-modules/exercise5/tasks/gethost.py:

#!/usr/bin/env python

import socket
import sys
import os
import json

host = os.environ.get('PT_host')
result = { 'host': host }

if host:
    result['ipaddr'] = socket.gethostbyname(host)
    result['hostname'] = socket.gethostname()
    # The _output key is special and used by bolt to display a human readable summary
    result['_output'] = "%s is available at %s on %s" % (host, result['ipaddr'], result['hostname'])
    print(json.dumps(result))
else:
    # The _error key is special. Bolt will print the 'msg' in the error for the user.
    result['_error'] = { 'msg': 'No host argument passed', 'kind': 'exercise5/missing_parameter' }
    print(json.dumps(result))
    sys.exit(1)

Run the task using the command bolt task run <task-name>.

bolt task run exercise5::gethost host=google.com --targets linux

The result:

Started on target1...
Finished on target1:
  google.com is available at 172.217.3.206 on localhost.localdomain
  {
    "host": "google.com",
    "hostname": "localhost.localdomain",
    "ipaddr": "172.217.3.206"
  }
Successful on 1 target: target1
Ran on 1 target in 0.97 seconds

Next Steps

Now that you know how to write tasks you can move on to:

Downloading and Running Existing Tasks