I used the last days of 2015 to automate the installation of our C development environment. Here are some of the ingredients:
10 days later the result was as expected. I am now able to say vagrant up and (if running for the first time) a basebox from an internal repository is downloaded and Vagrant is then running all the shell scripts I've written to install the above. This is called to provisioning step and takes place only once.
Coding the infrastructures I found my self dealing with some of the issues I only knew from ordinary coding so far.
External Dependencies
When installing software which was not provided in a nice repository (Oracle client and Eclipse ProC extension for example) I had to decide if the install scripts download some version of the software from the internet or if I should add a specific version to my Vagrant project and keep it.
I went for the latter. To reduce external dependencies (=download links at the Internet) I have the required archives and binaries locally under version control. If I want to update the software, I manually need to download the newer version and let it replace the older version.
Inside my scripts I always tried to use wildcards when it came down to file names. The goal was that a version update does not require an update of the provisioning shell scripts. A simple overwrite of the old version with the new version should do.
ECLIPSE_PURE_SDK="/vagrant/files/eclipse-SDK-*-linux-*_64.tar.gz"
...
tar xvzf ${ECLIPSE_PURE_SDK}
Feedback Loop
The general approach to codify my infrastructure setup was very similar to the way I usually go forward:
- write new code or correct existing code
- let it compile (optional, only required for compiled languages of course)
- execute
- find the error
- start from beginning
Translated into the world of Vagrant this is:
- write a new installation task or correct an erroneous existing one
- let Vagrant provision (=execute) the installation tasks
- find the error in the installation tasks
- start from beginning
Particularly the second step, provisioning the Vagrant box was painfully slow. It took about 5-7 minutes to finish this step. Going forward in small incremental steps this means a lot of 5-7 minutes forced breaks.
This time I accepted these waiting times. For the next bigger infrastructure coding job I will definitely try out one of the configuration management tools (Ansible, Puppet, Chef...). All of them give me something really helpful I was lacking this time - idempotence:
... operations [...], that can be applied multiple times without changing the result beyond the initial application. (Wikipedia)
My imaginary updated Vagrant cycle would then look like this:
- write a new installation task or correct an erroneous existing one
- execute all installation tasks, only the new or updated once run
- find the error in the installation tasks
- start from beginning
This should save me a lot of time since here only the differences of the configuration tasks are executed.