Creating Ansible Roles from Scratch: Part 2

Creating Ansible Roles from Scratch: Part 2

In part one of this series, we created the outline of an Ansible role to install Packer with ansible-galaxy, and then filled it in. In this post, we’ll apply the role against a virtual machine, and ultimately, install Packer!

A Playbook for Applying the Role

After all of the modifications from the previous post, the directory structure for our role should look like:

├── defaults
│ └── main.yml
├── meta
│ └── main.yml
└── tasks
└── main.yml

Now, let’s alter the directory structure a bit to make room for a top level playbook and virtual machine definition to test the role. For the virtual machine definition, we’ll use Vagrant.

To accommodate the top level playbook, let’s move the azavea.packer directory into a roles directory. At the same level as roles, let’s also create a site.yml playbook and a Vagrantfile. After those changes are made, the directory structure should look like:

├── Vagrantfile
├── roles
│ └── azavea.packer
│ ├──
│ ├── defaults
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ └── tasks
│ └── main.yml
└── site.yml

The contents of the site.yml should contain something like:

- hosts: all
sudo: yes
- { role: "azavea.packer" }

This instructs Ansible to apply the azavea.packer role to all hosts using sudo.

And the contents of the Vagrantfile should look like:

# -*- mode: ruby -*-
# vi: set ft=ruby :


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| = "ubuntu/trusty64"

config.vm.provision "ansible" do |ansible|
ansible.playbook = "site.yml"

Here we’re making use of the ubuntu/trusty64 box on Vagrant Cloud, along with the Ansible provisioner for Vagrant.

Running vagrant up from the same directory that contains the Vagrantfile should bring up a Ubuntu 14.04 virtual machine, and then attempt use ansible-playbook to apply site.yml. Unfortunately, that attempt will fail, and we’ll be met with the follow error:

ERROR: cannot find role in /Users/hector/Projects/blog/roles/azavea.unzip or
/Users/hector/Projects/blog/azavea.unzip or /etc/ansible/roles/azavea.unzip

Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.

Where is this reference to azavea.unzip coming from? Oh, that’s right, we had it listed as a dependency in the Packer role metadata…

Role Dependencies

Role dependencies are references to other Ansible roles needed for a role to function properly. In this case, we need unzip installed in order to extract the Packer binaries from

To resolve the dependency, azavea.unzip needs to exist in the same roles directory that currently houses azavea.packer. We could create that role the same way we did azavea.packer, but azavea.unzip already exists within Ansible Galaxy (actually, so does azavea.packer).

In order to install azavea.unzip into the roles directory, we can use the ansible-galaxy command again:

$ ansible-galaxy install azavea.unzip -p roles
downloading role 'unzip', owned by azavea
no version specified, installing 0.1.0
- downloading role from
- extracting azavea.unzip to roles/azavea.unzip
azavea.unzip was installed successfully

Now, if we try to reprovision the virtual machine, the Ansible run should complete successfully:

$ vagrant provision
==> default: Running provisioner: ansible...

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [default]

TASK: [azavea.unzip | Install unzip] ******************************************
changed: [default]

TASK: [azavea.packer | Download Packer] ***************************************
changed: [default]

TASK: [azavea.packer | Extract and install Packer] ****************************
changed: [default]

PLAY RECAP ********************************************************************
default : ok=4 changed=3 unreachable=0 failed=0

Before we celebrate, let’s connect to the virtual machine and ensure that Packer was installed properly:

$ vagrant ssh
vagrant@vagrant-ubuntu-trusty-64:~$ packer
usage: packer [--version] [--help] []

Available commands are:
build build image(s) from template
fix fixes templates from old versions of packer
inspect see components of a template
validate check that a template is valid

Globally recognized options:
-machine-readable Machine-readable output format.

Excellent! The Packer role we created has successfully installed Packer!

More Ansible

Check out this post about Running Vagrant with Ansible Provisioning on Windows to learn more about how to create project-specific development environments.  Adding Ansible as a provisioner makes setting up a development environment wonderfully smooth – we’ll walk you through the process.