Ansible with Vagrant: read inventory from Vagrantfile “extra_vars”

ansibleprovisioningvagrant

Our local dev boxes are running Virtualbox/Vagrant and are provisioned by ansible. Now we set a fixed IP address for the box and we need to use this at three different places. Our Vagrantfile looks like this:

# Set the Vagrantbox IP address
VAGRANT_NETWORK_IP = "10.0.0.10"

# Set the Ansible configuration environment variable
ENV['ANSIBLE_CONFIG'] = "./ansible/.ansible.cfg"

Vagrant.configure("2") do |config|
  config.vm.box     = "ubuntu-precise-64"
  config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-amd64-vagrant-disk1.box"
  config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.network :private_network, ip: VAGRANT_NETWORK_IP
  config.vm.synced_folder ".", "/var/www"

  config.vm.provision "ansible" do |ansible|
    ansible.playbook       = "ansible/playbook.yml"
    ansible.limit          = "all"
    ansible.inventory_path = "ansible/hosts/vagrant"
    ansible.extra_vars     = {target: VAGRANT_NETWORK_IP}
  end

end

And our ansible playbook:

---
- hosts: "{{ target }}"
  sudo: yes
  roles:
    # ...

And our inventory file:

10.0.0.10 ansible_ssh_user=vagrant ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key

We have reused the IP address in the Vagrantfile by using a variable VAGRANT_NETWORK_IP. However, we still need to set this IP address in our inventory. Is it possible to use an ansible variable as host in your inventory file? Simply using {{target}} in the inventory does not work.

Or, alternatively, is there a way to make this easier anther way? We'd like to configure the boxes IP addresses in a single file, if possible.

Best Answer

Vagrantfile is just a plain ruby file, so you can generate inventory file from it:

File.open('ansible/hosts/vagrant' ,'w') do |f|
  f.write "[default]\n"
  f.write "#{VAGRANT_NETWORK_IP} ansible_ssh_user=vagrant ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key\n"
end

By default vagrant box starts with name "default", so I usually limit ansible-managed hosts to vagrant's one (you can set ansible.limit = "default").

If you want to have several vagrant boxes with one inventory, you can define that boxes in one Vagrantfile and generate inventory for it.

Related Topic