“You Either Die A Hero, Or You Live Long Enough To See Yourself Become The Villain” Harvey Dent, The Dark Knight
One aspect to automation that you need to consider is distributing your code responsibly. We all know that asshole developer (AHD), the kind that will with great bravado declare that it “Works on my machine, your environment *must* be broken.” Since you will be hopefully writing and distributing code, you have the opportunity to not be that guy. There are some simple(ish) steps you can take:
- Keep your code in a Git repo, and don’t work in master branch. Let your coworkers run your code from master branch, while you work in a development branch.
- Document everything! I like keeping it all spelled out in the README.md file in the root a git repo. Markdown is a way of having pretty documents that are just plain text files. When you are making changes to the project, update the docs in the same directory at the same time.
- Actually try to deploy and run it on a machine that’s not yours.
The last one is the one I want to talk about in detail. One simple way to test is using Vagrant. Declaring a vm that you spin up, test, then throw away when you’re done sounds to be ideal. But it’s possible to fall into an AHD trap. “Wow Batman, how is that possible?” I’m glad you asked! Let’s look at a sample vagrant file.
Vagrant.configure("2") do |config| config.vm.box = "centos/7" config.vm.provision "ansible" do |ansible| ansible.playbook = "install.yml" end end
Fairly simple. Instantiate a vm running CentOS 7, and then run the play “install.yml” against it. Ansible runs from a control node against the machine in the inventory, and vagrant is no exception. It will call your
/usr/bin/ansible-playbook against the new vm. And it will run with your environment. You never actually test with a clean environment. Now let’s look at how we can improve it.
Vagrant.configure("2") do |config| config.vm.box = "centos/7" config.vm.provision "shell", inline: "sudo yum -y install epel-release" config.vm.provision "shell", inline: "sudo yum -y install ansible" config.vm.provision "shell", inline: "cd /vagrant && ansible-playbook install.yml" end
The only difference is, that instead of using a whole play to install everything from our control node; we use the shell method to run the commands directly inside the vm. The result is the vagrant vm is bootstrapping the install using only what’s inside the vm. This way you’ll get a better feel for installing from nothing. One of Vagrant’s behavior is to rsync over everything in the same directory as the Vagrantfile to your Vagrant vm. Our third shell statement leverages that behavior by calling the rsync’ed play in /vagrant.
If you want to play along with the home version, I have a git repo for you. Take a look at the sample I have up on Github