From charlesreid1

Vagrant is a command line interface to VirtualBox that allows you to create virtual machines from the command line and manage them. This is a convenient way of testing Ansible scripts locally without using the AWS or Google Cloud platforms.

Ansible can wrap around Vagrant and use it to automate the management of remote machines. This is useful for testing Ansible locally if you need to test it with multiple machines or particular architectures.

Details of how to connect to vagrant boxes can be added to the Ansible hosts file (see Ansible/Vagrant/Static Inventory for an example static inventory (hosts) file), or machines can be managed using a dynamic inventory script (see Ansible/Vagrant/Dynamic Inventory for an example Vagrant dynamic inventory script). This will allow Ansible to connect to the remote machines and execute commands.

Before you begin: set up vagrant box

See the Basic Startup and Shutdown Procedure section of the Vagrant page for steps to set up a Vagrant box, and connect to it via SSH.

Briefly:

To clear everything out and destroy all old vagrant boxes:

vagrant destroy --force

To initialize a vagrant box:

vagrant init ubuntu/xenial64

this will result in a Vagrantfile.

To bring it up:

vagrant up

For info about the ssh configuration of the box:

vagrant ssh-config

To ssh into the box:

vagrant ssh

To halt the machine:

vagrant halt

Note: for multiple vagrant boxes, see the guide on the Ansible/Full Stack Playbook page.

Connect Ansible to Vagrant

Use the hosts file to tell Ansible how to connect to the (Vagrant) hosts.

Managing hosts file by hand

See Ansible/Vagrant/Static Inventory

Managing hosts dynamically

A dynamic inventory executable file can be used by specifying the path to the executable dynamic inventory script using the -i flag when running ansible:

ansible -i dynamic_vagrant.py ...

Shortcuts: configuring ansible

To make the ansible commands being executed slightly simpler, you can define default values for flags and options.

See Ansible/Configuration

Ping Vagrant box

To ping the Vagrant machine (that Ansible is managing), use Ansible's ping module.

Call Ansible and the name of the machine (must be listed in the hosts file).

Pass it the inventory file name with the -i flag, and the ping module with the -m flag:

ansible myvagrantbox -i hosts -m ping

or if you're using a dynamic inventory file,

ansible myvagrantbox -i hosts -m ping

You should see some output like this:

myvagrantbox | success >> {
    "changed": false,
    "ping": "pong"
}

If it did not succeed, re-run with the -vvvv flag for max verbosity to help debug the issue.

This is a basic module that runs a ping test; the server should respond with a pong on the other end.

The "'changed': false" indicates that Ansible is not changing the state of the machine.


Use a config file

The inventory file (hosts) required lots of details, and if we have many nodes to deal with that is not going to scale well.

To make it easier to deal with, we can use the ansible.cfg file to set some defaults and variables.

Where to put ansible.cfg? Here is where Ansible looks:

  • ANSIBLE_CONFIG env var (specifies the config file)
  • /ansible.cfg (current directory)
  • ~/.ansible.cfg (.ansible.cfg in your home directory
  • /etc/ansible/ansible.cfg

A good place for it is alongside the playbooks, in the current directory.

This dir structure allows you to place the config file, plus the playbooks, under version control in a single repo.

Example config file

To specify default values for SSH key, username, and inventory filename, use this config file:

ansible.cfg:

[defaults]
inventory = hosts
remote_user = vagrant
private_key_file = .vagrant/machines/default/virtualbox/private_key
host_key_checking = False

Now we can also simplify the hosts file:

playbooks/hosts:

myvagrantbox ansible_host=127.0.0.1 ansible_port=2222

Now that the Ansible config file specifies that the inventory file is called hosts, we don't need to specify that with the -i flag anymore:

$ ansible myvagrantbox -m ping

Executing arbitrary commands

We have already seen the -m flag used with ansible to specify an ansible module.

We can use the command module to run arbitrary commands on the vagrant machines that ansible is managing.

To run a command on the remote machine via ansible:

ansible myvagrantbox -m command -a <the command to run>

For example, to run the uptime command:

ansible myvagrantbox -m command -a uptime

Results in:

testserver | success | rc=0 >>
 17:14:07 up  1:16,  1 user,  load average: 0.16, 0.05, 0.04

Important Note

The command module is actually the default module!!! So we don't need to specify -m command, that is the default value:

ansible myvagrantbox -a <the command to run>

For example:

ansible myvagrantbox -a uptime

If the command has spaces in it, use quotes:

ansible myvagrantbox -a "tail /var/log/dmesg"

Executing root commands

To run commands that require root access, pass the -b flag to BECOME the root user:

$ ansible myvagrantbox -b -a "tail /var/log/syslog"

Installing packages

The apt module is useful for installing packages. Here's how you would install nginx:

ansible myvagrantbox -b -m apt -a name=nginx

IMPORTANT: The first apt module command you give should also run the equivalent of apt-get update before the package is installed. To do that, change the name to name="nginx update_cache=yes":

ansible myvagrantbox -b -m apt -a name="nginx update_cache=yes"

Starting services

Once nginx is installed, the service can be started using the service module:

ansible myvagrantbox -b -m service -a "name=nginx state=restarted"

equivalent of running sudo service nginx restart


Flags