Test Environment for Ansible on a Windows System Without Linux Subsystem Support
Some weeks ago, I gave a workshop about Ansible and I was asked how to set up a local test environment for Ansible. Requirement is that this test environment can run on a Windows 10 without a Linux subsystem. I don't why, but it was not my first customer where Windows 10 could not be used with Linux subsystem (Don't ask me about reasons). So I recommend following set up.
Ansible itself requires a Linux-based system as the control machine (so-called
control node). The machine that is provisioned (so-called
managed node) can be both, Linux- or Windows-based. In my following example, the manage node is Linux-based. So when I have to develop on a Windows machine, I install two Linux-based virtual machines. One for calling the Ansible's playbooks and a second one for testing the provisioning. I set up the virtual machines with VirtualBox and Vagrant. Vagrant allows me to share the playbooks easily between host and virtual machines. That means, I can develop the playbook on the Windows system and the virtual machines can run headless. The next section shows you how to set up this tool chain.
Tool Chain Setup
At first, install VirtualBox and Vagrant on your machine. I additionally use Babun, a windows shell based on Cygwin and oh-my-zsh, for a better shell experience on Windows, but this isn't necessary. Then, go to the directory (let's called it
ansible-workspace), where your Ansible's playbooks are located. Create there a Vagrant configuration file with the command
1$ cd ansible-workspace 2$ vagrant init 3$ tree 4. 5├── deploy-app.yml 6├── host_vars 7│ └── ubuntu-server 8├── inventories 9│ ├── production 10│ └── test 11├── roles 12│ ├── deploy-on-tomcat 13│ │ ├── defaults 14│ │ │ └── main.yml 15│ │ └── tasks 16│ │ ├── cleanup-webapp.yml 17│ │ ├── deploy-webapp.yml 18│ │ ├── main.yml 19│ │ ├── start-tomcat.yml 20│ │ └── stop-tomcat.yml 21└── Vagrantfile
Now, we have to choose a so-called Vagrant Box on Vagrant Cloud. A box is the package format for a Vagrant environment. It depends on the provider and the operating system that you choose to use. In our case, it is a VirtualBox VM image based on a minimal Ubuntu 18.04 system (box name is bento/ubuntu-18.04 ). In our case, we have to configure two boxes in our Vagrantfile. Both are based on bento/ubuntu-18.04.
1Vagrant.configure("2") do |config| 2 config.vm.define "managed-node" do |ubuntu| 3 ubuntu.vm.box = "bento/ubuntu-18.04" 4 end 5 6 config.vm.define "control-node" do |vbox| 7 vbox.vm.box = "bento/ubuntu-18.04" 8 end 9end
The next step is to ensure that Python is installed on the managed node and this node is available via an IP address. For that, we use the shell provisioning, and we configure a private network in the Vagrantfile:
1# ... 2 config.vm.define "managed-node" do |ubuntu| 3 ubuntu.vm.box = "bento/ubuntu-18.04" 4 ubuntu.vm.network "private_network", ip: "192.168.33.11" 5 6 ubuntu.vm.provision "shell", inline: <<-SHELL 7 sudo apt-get update 8 sudo apt-get install python -y 9 SHELL 10 end 11# ...
In the control node, we have to ensure that Ansible is installed and that a SSH connection from control node to our managed node via SSH-key is possible. For that agian, we use the shell provisioning in the Vagrantfile:
1 # ... 2 config.vm.define "controll-node" do |vbox| 3 vbox.vm.box = "bento/ubuntu-18.04" 4 5 vbox.vm.provision "shell", inline: <<-SHELL 6 sudo apt-get update -y 7 sudo apt-get install -y software-properties-common 8 sudo apt-add-repository ppa:ansible/ansible 9 sudo apt-get update -y 10 sudo apt-get install -y ansible 11 SHELL 12 13 vbox.vm.provision "shell", privileged: false, inline: <<-SHELL 14 ssh-keygen -t rsa -q -f "/home/vagrant/.ssh/id_rsa" -N "" 15 ssh-keygen -R 192.168.33.11 16 ssh-keyscan -t rsa -H 192.168.33.11 >> /home/vagrant/.ssh/known_hosts 17 sshpass -p 'vagrant' ssh-copy-id -i /home/vagrant/.ssh/id_rsa.pub firstname.lastname@example.org 18 SHELL 19 end 20# ...
On Github's Gist you can find the whole Vagrantfile.
The last step is to configure your Ansible project, so that the playbooks can run against the managed node. Therefore, you create a new inventory file called
local-test with managed node's IP address:
1$ cat inventories/local-test 2[application_server] # name of your group that is mention in your playbook 3192.168.33.11
After setting up the tool chain let's have a look how to work with it. I write my Ansible playbook on the Windows system and run them from the control node against managed node. First at all, we have to start our Vagrant boxes.
1$ cd ansible-workspace 2$ vagrant up
When both Vagrant boxes are ready to use, we can jump into control node box with:
1$ vagrant ssh control-node
You can find the Ansible playbooks inside the box in the folder
/vagrant . In this folder run Ansible:
1$ cd /vagrant 2$ ansible-playbook -i inventories/local-test -u vagrant deploy-app.yml
It is important that you use the
Some Docker fans would prefer a container instead of a virtual machine. But remember, Docker runs on Windows in a virtual machine, therefore, I don't see a benefit for using Docker instead of a virtual machine. But of course with Windows 10 native container support a setup with Docker is a good alternative if Ansible doesn't run on the Linux subsystem.
Do you another idea or approach? Let me know and write a comment.