Installing Development Tools
Last time we customized our Vagrant box using Bash scripts. While that is simple and straightforward, a more powerful and elegant solution is to use Ansible. Packer's Ansible Local Provisioner allows us to do just that.
Ansible
Working in IT, you're likely doing the same tasks over and over. What if you could solve problems once and then automate your solutions going forward? Ansible is here to help.
I'm not going to try and teach you Ansible because there are plenty of resources out there already. What I will talk about are the key features of Ansible that might cause you to reach for it as your provisioning tool.
- convenience - Ansible has the notion of a module which is a baked-in recipe for how to accomplish a task. The module index has the building blocks needed to accomplish almost any task.
- shared knowledge - Ansible Galaxy is a repository of custom modules provided by the community, often combining many of the lower level modules into a sigle, more convenient module.
- ease of use - all Ansible needs to work is an SSH connection and legacy Python.
- templating - Ansible has many nice features but the ability to levarage Jinja2 templates is one of my favorites. I've used this feature to construct configuration files using values specified when Ansible is run. Very useful.
Tool Installation via Ansible
Let's install the same set of packages we installed using scripts/install-packages.sh
using Ansible instead.
"provisioners": [
{
"type" : "shell",
"environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
"script" : "scripts/install-ansible.sh"
},
{
"type" : "ansible-local",
"playbook_file" : "ansible/playbook.yml",
"extra_arguments" : ["--verbose"]
},
{
"type" : "shell",
"environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
"scripts" : ["scripts/prepare-for-compression.sh"]
}
],
#!/usr/bin/env bash
# there are numerous ways to install Ansible but let's use the package manager
echo "Installing Ansible via package manager..."
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get update
sudo apt-get --yes install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get --yes install ansible
ansible --version
---
- name: Install Tools
hosts: localhost
become: true
tasks:
- name: Favorite Tools
apt:
name : "{{ item }}"
state : present
update_cache: yes
with_items:
- "tree"
- "ntpdate"
- "grsync"
Conclusion
Today we learned how Ansible can simplify the customization of our Vagrant box. The Ansible playbook we created today is very simple but effective. Next time, we'll learn how to leverage other people's work, using modules pulled from Ansible Galaxy.
Full Packer File
{
"description": "Builds a Xubuntu 18.04 desktop box with various software development tools installed",
"min_packer_version": "1.2.3",
"variables": {
"ssh_name" : "vagrant",
"ssh_pass" : "vagrant",
"virtualbox_appliance": "bionic-beaver.ova",
"comment" : "Test of Vagrant Cloud upload.",
"cloud_user" : "{{env `VAGRANT_CLOUD_ACCOUNT`}}",
"cloud_token" : "{{env `VAGRANT_CLOUD_TOKEN`}}"
},
"builders": [{
"type" : "virtualbox-ovf",
"source_path" : "{{user `virtualbox_appliance`}}",
"ssh_username": "{{user `ssh_name`}}",
"ssh_password": "{{user `ssh_pass`}}",
"boot_wait" : "30s",
"format" : "ova",
"guest_additions_mode": "disable",
"headless" : false,
"keep_registered" : false,
"shutdown_command" : "sudo shutdown --poweroff now",
"shutdown_timeout" : "2m",
"skip_export" : false,
"output_directory" : "output-virtualbox-ovf",
"vboxmanage": [
["modifyvm", "{{.Name}}", "--vram", "32"],
["modifyvm", "{{.Name}}", "--memory", "2048"],
["modifyvm", "{{.Name}}", "--cpus", "1"]
],
"vm_name" : "packer-bionic-xubuntu"
}],
"provisioners": [
{
"type" : "shell",
"environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
"script" : "scripts/install-ansible.sh"
},
{
"type" : "ansible-local",
"playbook_file" : "ansible/playbook.yml",
"extra_arguments" : ["--verbose"]
},
{
"type" : "shell",
"environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
"scripts" : ["scripts/prepare-for-compression.sh"]
}
],
"post-processors": [
[
{
"compression_level" : 9,
"keep_input_artifact": false,
"output" : "vagrant/bionic-xubuntu.box",
"type" : "vagrant"
},
{
"access_token" : "{{user `cloud_token`}}",
"box_tag" : "{{user `cloud_user`}}/bionic-xubuntu",
"type" : "vagrant-cloud",
"version" : "{{isotime \"2006.01.0203\"}}",
"version_description": "{{user `comment`}}"
}
]
]
}