Monday 12 July 2021

Introducing Puppet Bolt Part 2: Understanding tasks

Introduction

In the last post we discussed the motivation behind using Puppet Bolt in your environment and demonstrated how to install Puppet Bolt and run one off ad hoc commands using some of the options provided by the tool. In this post we'll take things a little further from running commands and start creating and running tasks.

What is a task?
Tasks are basically scripts that perform single ad-hoc functions. Tasks can however be orchestrated using plans. All tasks are stored in Puppet modules. In case you do not wish to create your own tasks you could also download them from Puppet forge or GitHub and use them directly. You can also pass arguments to Bolt tasks.

Display available tasks:
Bolt comes with a couple of pre-installed tasks that you could use out of the box. To view a list of available tasks type:

[sahil@bolt-lab ~]$ bolt tasks show
Expected subcommand 'tasks' to be one of command, script, task, plan, file, puppetfile, secret, apply
[sahil@bolt-lab ~]$ bolt task show
facts                    Gather system facts
package                  Manage and inspect the state of packages
puppet_agent::install    Install the Puppet agent package
puppet_agent::version    Get the version of the Puppet agent package installed. Returns nothing if none present.
puppet_conf              Inspect puppet agent configuration settings
reboot                   Reboots a machine
reboot::last_boot_time   Gets the last boot time of a Linux or Windows system
service                  Manage and inspect the state of services

MODULEPATH:
/home/sahil/.puppetlabs/bolt/modules:/home/sahil/.puppetlabs/bolt/site-modules:/home/sahil/.puppetlabs/bolt/site

Use `bolt task show <task-name>` to view details and parameters for a specific task.
[sahil@bolt-lab ~]$

To view information about a particular task just append the task name at the end of the above executed command. Here's an example.

[sahil@bolt-lab ~]$ bolt task show facts

facts - Gather system facts

USAGE:
bolt task run --nodes <node-name> facts

MODULE:
built-in module
[sahil@bolt-lab ~]$


Executing a task:
To demonstrate how to execute tasks, lets take use the service task.

[sahil@bolt-lab ~]$ bolt task show service

service - Manage and inspect the state of services

USAGE:
bolt task run --nodes <node-name> service action=<value> name=<value> provider=<value>

PARAMETERS:
- action: Enum[start, stop, restart, enable, disable, status]
    The operation (start, stop, restart, enable, disable, status) to perform on the service.
- name: String[1]
    The name of the service to operate on.
- provider: Optional[String[1]]
    The provider to use to manage or inspect the service, defaults to the system service manager. Only used when the 'puppet-agent' feature is available on the target so we can leverage Puppet.

MODULE:
built-in module

The above description states that we need to pass the action and name parameters to tell bolt the name of the service we want to work with and the action we want to take on the service. Let's run use the service task to check the status of the nfs service.

[sahil@bolt-lab ~]$ bolt task run --nodes bolt-lab service name=nfs action=status --user sahil
Started on bolt-lab...
Finished on bolt-lab:
  {
    "status": "MainPID=0,LoadState=loaded,ActiveState=active",
    "enabled": "enabled"
  }
Successful on 1 node: bolt-lab
Ran on 1 node in 1.45 seconds
[sahil@bolt-lab ~]$


Before we can start writing tasks we need to understand what is a module?
A puppet module consists of self contained code and data residing in a simple file structure. Modules can easily be shared and reused. You could even distribute your own modules as tar.gz files.

Given below are some rules we need to adhere to while creating puppet modules:

  • The directory name of the module is the name of the module itself.
  • It should contain a manifests directory with an init.pp file.
  • The init.pp file must contain a single class definition the same as the module's name.
  • A metadata.json file should be present in the parent directory.

If you do not intend to distribute your modules and use them primarily for running tasks then you could afford to ignore most of the above mentioned rules.


Creating our first task:
Since a module is basically some files arranged in a directory hierarchy, to create a module we just need to create that directory structure.

For our first module and task we'll be keeping things simple and create a very basic script to work with packages using yum.

We'll be naming our task my_pkg. When you run the 'bolt task show' command it'll show you the default directories where Bolt looks for modules. We could use a different directory and then specify that with the --modulepath parameter while using Bolt. but for this demonstration we'll use one of the default ones.

Let's create a directory named my_pkg under one of the default module paths.

[sahil@bolt-lab ~]$ mkdir -p /home/sahil/.puppetlabs/bolt/modules/my_pkg

Now we'll create a tasks sub-directory under this directory to store the tasks that we'll be creating under this module.

[sahil@bolt-lab ~]$ mkdir -p /home/sahil/.puppetlabs/bolt/modules/my_pkg/tasks

I would like to pass some parameters to the task that I'll be creating. To add parameters to your task as environment variables, pass the argument prefixed with the Puppet task prefix PT_ . There are more ways to pass parameters to Puppet tasks but for now we'll stick to this approach using environment variables.

I've created a small bash script named yum in the tasks directory and populated it with the following content:

[sahil@bolt-lab ~]$ cat /home/sahil/.puppetlabs/bolt/modules/my_pkg/tasks/yum.bash
#!/bin/bash

action="$PT_action"
name="$PT_name"

yum $action $name

[sahil@bolt-lab tasks]$
$

To make Bolt aware that we've added a new module and to able to use it, we'll need to install the module. To do that we first need to create a file named Puppetfile that has the following content.

[sahil@bolt-lab ~]$ cat Puppetfile
#Local modules
mod 'my_pkg', local:true
[sahil@bolt-lab ~]$

Before we can use our Puppet file we need to move it to the default Bolt directory.

[sahil@bolt-lab ~]$ mv Puppetfile /home/sahil/.puppetlabs/bolt/
[sahil@bolt-lab ~]$ ls /home/sahil/.puppetlabs/bolt/Puppetfile
/home/sahil/.puppetlabs/bolt/Puppetfile
[sahil@bolt-lab ~]$

To install the module we need to run the below command:

[sahil@bolt-lab ~]$ bolt puppetfile install
Successfully synced modules from /home/sahil/.puppetlabs/bolt/Puppetfile to /home/sahil/.puppetlabs/bolt/modules
[sahil@bolt-lab ~]$

If we run Bolt task show again we will be able to see the my_pkg module defined with the yum task:

[sahil@bolt-lab ~]$ bolt task show
facts                    Gather system facts
my_pkg::yum
package                  Manage and inspect the state of packages
puppet_agent::install    Install the Puppet agent package
puppet_agent::version    Get the version of the Puppet agent package installed. Returns nothing if none present.
puppet_conf              Inspect puppet agent configuration settings
reboot                   Reboots a machine
reboot::last_boot_time   Gets the last boot time of a Linux or Windows system
service                  Manage and inspect the state of services

MODULEPATH:
/home/sahil/.puppetlabs/bolt/modules:/home/sahil/.puppetlabs/bolt/site-modules:/home/sahil/.puppetlabs/bolt/site

Use `bolt task show <task-name>` to view details and parameters for a specific task.
[sahil@bolt-lab ~]$

If we weren't going to pass any parameters to the task then this would be enough. But since we do intend to pass parameters and would like to inform the users about the functionality of the task, we'll add a JSON metadata file in our tasks directory and populate it with the following content:

[sahil@bolt-lab ~]$ cat /home/sahil/.puppetlabs/bolt/modules/my_pkg/tasks/yum.json
{
  "description": "Allow users to manipulate software packages using yum",
  "parameters": {
    "action": {
      "description": "Task to perofmr on the package",
      "type": "String"
    },
    "name": {
      "description": "The package name",
      "type": "String"
    }
  }
}


Now let's execute the bolt task show command for our my_pkg::yum task.

[sahil@bolt-lab tasks]$ bolt task show my_pkg::yum

my_pkg::yum - Allow users to manipulate software packages using yum

USAGE:
bolt task run --nodes <node-name> my_pkg::yum action=<value> name=<value>

PARAMETERS:
- action: String
    Task to perform on the package
- name: String
    The package name

MODULE:
/home/sahil/.puppetlabs/bolt/modules/my_pkg
[sahil@bolt-lab tasks]$


Now we are all done with the prep work. Let's run our task.

[sahil@bolt-lab tasks]$ bolt task run --nodes 10.31.19.151 my_pkg::yum action=info name=httpd --user sahil --run-as root
Started on 10.31.19.151...
Finished on 10.31.19.151:
  Loaded plugins: fastestmirror
  Loading mirror speeds from cached hostfile
   * base: mirror.aktkn.sg
   * epel: d2lzkl7pfhq30w.cloudfront.net
   * extras: mirror.aktkn.sg
   * nux-dextop: mirror.li.nux.ro
   * updates: mirror.aktkn.sg
  Available Packages
  Name        : httpd
  Arch        : x86_64
  Version     : 2.4.6
  Release     : 89.el7.centos
  Size        : 2.7 M
  Repo        : updates/7/x86_64
  Summary     : Apache HTTP Server
  URL         : http://httpd.apache.org/
  License     : ASL 2.0
  Description : The Apache HTTP Server is a powerful, efficient, and extensible
              : web server.

  {
  }
Successful on 1 node: 10.31.19.151
Ran on 1 node in 3.03 seconds
[sahil@bolt-lab tasks]$ bolt task run --nodes 10.31.19.151 my_pkg::yum action=list name=httpd --user sahil --run-as root
Started on 10.31.19.151...
Finished on 10.31.19.151:
  Loaded plugins: fastestmirror
  Loading mirror speeds from cached hostfile
   * base: mirror.aktkn.sg
   * epel: d2lzkl7pfhq30w.cloudfront.net
   * extras: mirror.aktkn.sg
   * nux-dextop: mirror.li.nux.ro
   * updates: mirror.aktkn.sg
  Available Packages
  httpd.x86_64                     2.4.6-89.el7.centos                     updates
  {
  }
Successful on 1 node: 10.31.19.151
Ran on 1 node in 3.60 seconds


As this point the action can only be info or list because I haven't added the -y option with yum to allow for install or erase operations. But we can tweak the script to suit our requirements.


Conclusion

This concludes our article on how to start writing tasks to run using Puppet Bolt. We hope you found it to be useful and look forward towards your feedback and suggestions.




No comments:

Post a Comment

Using capture groups in grep in Linux

Introduction Let me start by saying that this article isn't about capture groups in grep per se. What we are going to do here with gr...