Ansible is the “new kid on the block” of configuration management software, promoting a push-based system with orchestration as a first-class citizen, as opposed to more entrenched options such as puppet which has orchestration in the form of MCollective - an entirely different project. With the recent beta opening of Galaxy, Ansible’s answer to Puppet’s Forge, I’ve written a tutorial to take you from writing a simple module (called a role) to publishing it on Galaxy.
Creating your first role
The role I’ve selected for this demonstration is very simple: install sqlite on a machine, and have the option of provisioning databases. Unlike heavy-duty databases, sqlite only requires a client to manipulate databases and no server is needed to be setup.
From version 1.4 of Ansible and higher, the ansible-galaxy
command is available which provides the option of downloading roles from Galaxy as well as setting up the scaffolding for a new role. Let’s start by creating a role called sqlite.
You should get a message saying sqlite was created successfully and a new directory called sqlite
with a bunch of subfolders.
Inside an Ansible role
Just from the start, there are no fewer than 7 different subfolders in a role. Some of these aren’t necessary but this depends on the complexity of the role in question. We won’t need all of these in this tutoirial, but we’ll cover them all anyway.
- defaults: main.yml in this directory is where the default out-of-the-box configuration exists (for a database server, this could be data directories, port to listen on, and others). We’ll say that all sqlite databases should exist under /var/lib/sqlite, and that we have a (for now) empty list of databases to set up
It’s good practice to prefix your variables with the role name ($role_$var
), as we have.
-
files: Here we store files that aren’t templates or assets for the role. We have none of these for our sqlite role.
-
handlers: Handlers are tasks which can be set up to run on particular events, these are typically restarting a service or similar activity on configuration change. Again, we have none of these.
-
meta: main.yml under the meta subfolder is where we specify information about our module: who created it (us!), a description of the module, any other Galaxy dependencies it has, and so on. It also contains an explicit list of which platforms/versions it supports: we will come back to this later, but for now our main.yml looks like this
-
tasks: here we store the task definitions for our role, which we’ll cover in the next section
-
templates: this is where templates that get rendered by ansible get placed. These are jinja templates with access to the Ansible variables and vars that get passed in.
-
vars: We store variables in yaml files under
var
, which we can load from tasks. In the example that follows, package names differ across distributions/versions so we need to be able to install the right packages, and we achieve this by having a separate .yml file for each distribution family which gets loaded as the first task (as Ansible will know the OS that it is running on).
Creating tasks for installing sqlite
On Debian-based distros, the sqlite client is available in the sqlite3 package (there is a sqlite package, but to demonstrate vars, we will treat them differently), and on distros served by rpm, there is a sqlite package.
In tasks/main.yml we start by importing the OS-specific vars (in this case the package name) and then install depending on OS, by loading vars using the Ansible-provided ansible_os_family
variable.
Finally, we create all of the dbs we specify in our role declaration.
These two blocks form our file at tasks/main.yml
Testing the module
The convention is to include a test.yml that uses our role, so let’s try it out.
And we should end up with something that looks like this (here I actually run it as a playbook, it’s also considered good practice to “lint” the role with ansible-playbook --syntax-check -i inventory test.yml
)
Awesome!
Publishing to github and Galaxy
Now that we have a working role, we can commit the module to github (the Ansible documentation covers this), and follow the Ansible instructions for pulling down a repository. Ansible Galaxy allows sign on with multiple providers (such as Github, Facebook), and you can see this module here!
Writing your own re-usable Ansible roles is easy, and with Galaxy’s rating system we can share and use the best modules, enabling our infrastucture code to become better and less bespoke. Repository for this module is on github and comments/pull requests are welcome.