Vagrant and Ansible

July 20, 2015

I’m learning Python, and have had fun automating tasks with Python scripts.

I was polluting my Macbook (Yosemite) quite a bit by installing all libraries globally, until I learned about Vagrant. Vagrant is essentially a command-line wrapper around VirtualBox. It makes it easy to create/configure/destroy virtual machines from the shell.

Vagrantfile

I installed it from here. A summary of my journey is below.

Created and jumped into a new directory:
$ mkdir newproject && cd newproject

Create a Vagrantfile. This creates a file named “Vagrantfile” and a “.vagrant folder” in the directory:
$ vagrant init

Then I edited the Vagrantfile:

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

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "hashicorp/precise64"
  config.vm.network "forwarded_port", guest: 80, host: 8000
  config.vm.network "forwarded_port", guest: 5000, host: 5000
  config.vm.synced_folder ".", "/home/vagrant/dev/twig"
  config.vm.synced_folder ".", "/vagrant", disabled: true
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
  end
end
Provision for Python

I used Ansible to provision the virtual machine. I installed it using pip. Note the config.vm.provision line in the Vagrantfile above, which specifies a “playbook.yml”. The contents of that file are below.

---
- hosts: all
  remote_user: vagrant
  sudo: yes
  tasks: 
  - name: Update the repositories (apt-get update)
    apt: update_cache=yes

  - name: Upgrade all packages non-interactively (apt-get upgrade)
    shell: DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade

  - name: Install basic packages  
    action: apt state=installed pkg={{ item }}
    with_items: 
    - python-dev
    - vim
    - python-pip
    - git
    tags:
    - packages

  - name: Install python packages
    action: pip state=present name={{ item }}
    with_items:
    - ipython
    - virtualenv
    - virtualenvwrapper
    tags:
    - pip-packages 
Biggest Hurdle

YML syntax is fussy. Whitespace matters. I got the error below plenty of times, before figuring out that the ‘-’ needs to line up directly with the word above it.

ERROR: 'action' or 'local_action' attribute missing in task "Update apt cache"
Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.

Plenty of tutorials online showed one or two space indents.

tasks:
 - name: incorrect indent 1 space

OR

tasks:
  - name: incorrect indent 2 spaces

But it should have been:

tasks
- name: correct, no indent

These are both very simple configuration files, mostly to work through with minimum errors, while getting a functional virtual machine. I expect these will grow more complex over time.

So to get a machine up and running — ensure playbook.yml is in the same folder as the Vagrantfile, then the infamous:

$ vagrant up