The merits of continuous delivery (CD) in this highly disruptive and innovative age is unquestionable; disrupt, or be disrupted. For several years now, the Linux world has dominated in this landscape and continues to press forward at the speed of thought (read: Docker), however doing this is now quite achievable on Windows.
In a recent YOW! Nights tour of Australia Warner Godfrey, a fellow DiUS colleague, and Terrence Benade an Agile Architect at SEEK and I shared our experiences in continuously delivering applications on Windows platforms at SEEK, and whilst we have shared the video and our slides, there is only so much detail you can pass on in these forms.
In this 3 part series, I will take you through practical examples of my component of the talk – Machine Factories – with real source code, so that you can take these concepts and practices with you to your next CD project.
A set of AWS Credentials for your account (Consider using credulous to manage your keys).
A subnet and optionally, a VPC, to load the application into.
If you are on Windows, this gist will install Vagrant, Virtualbox and the Packer setup you need.
Avoiding the token “Hello World”, we’re going to build a basic URL shortening service with a twist and deploy it to IIS. Yes, we could build it on Mono as a self-hosted application and deploy it to Linux on a < 20mb Docker container – but that would spoil all of the fun – there is a heap of utility in applying this to applications that may not be candidates for this treatment.
Part 1: Setting up a local development environment with Vagrant
I’m a big fan of the 12 Factor App concept of environment parity. Repeatable, isolated development environments ensure code that works locally works the same in Prod, and it saves us the daily battle of ensuring our neighbours setup matches our own.
This is where Vagrant comes in, it is a tool to “Create and configure lightweight, reproducible, and portable development environments”. We will use Vagrant to run our local development environment and provision it with PowerShell DSC – a configuration management tool for Windows. The end result will be a repeatable, isolated development runtime (a Virtualbox virtual machine) running Windows that will be configured from the same recipe we configure all of our other environments.
Let’s get started. To begin, clone the accompanying tutorial so you can follow along.
1. Creating a Vagrant Machine with Packer
Doing things by hand is great, if you don’t have a life, so from the outset we are going to automate everything we can – including the setup of Vagrant. For this, we use a tool called Packer, a tool to create machine images from a single source configuration. As Packer expects to provision via SSH, we will use a number of community built Windows plugins to provision via native WinRM.
Packer uses a simple JSON DSL, and we will use the following to create our Vagrant box in two steps.
In the first step, we shall create a VirtualBox Windows 2012r2 image with a Vagrant user and the guest additions installed and then pop that aside for later use. This is good practice when you are iterating on a new machine, as booting and installing the OS can be quite time consuming and it’s likely you will make some mistakes in your machine provisioning. In the second step, we take the Base image as an input and then provision it to create a development machine image.
Here is our Packer file, you can see the two builders corresponding to the two images we were just referring to – basebox-vbox and devbox-vbox:
You should be able to get a rough idea of what we are doing by reading through this file: We are installing Chocolatey and 7zip, running a number of provisioning scripts (installing chocolatey packages, rsync, etc.) and then compressing the disk to make the resultant Vagrant box as small as possible, and then finally we generate a Vagrant box from the image. Take this opportunity to read through the scripts that are being run in order to get a sense for what’s happening.
Let’s create the box, shall we?
Now would be a good time to get some coffee – the ISO download will probably take a while!
If all goes well, you should have a file in the working directory with the name “machinefactory-api-virtualbox-1.0.0.box”. All we need to do now is add it to Vagrant’s local box registry and then we can use it!
2. Configuring Windows with PowerShell DSC
Now that we have a Vagrant box with all of the software we need on it, we need to configure it for our application to run. This is where DSC comes in: we can use it to easily, and declaratively set the desired state of our server including Windows Features, Firewall rules and Web Applications. The out-of-the-box resources are lacking, so we are pulling in the feature-rich SEEK modules to do some of the heavy lifting.
There are two main bits here – our Configuration file (MyWebsite.ps1) and a custom DSC Module for our Application:
Again, DSC is fairly readable when kept simple. You can see that we are opening the firewall for port 80, ensuring IIS and Application Development features are installed and then configures an AppPool & Website for our site to run under, including a host entry.
We will see this in action when we run Vagrant shortly, but the great thing here is that we can run DSC as many times as we like without breaking things, meaning iterating on a new configuration is easy.
3. Running Vagrant
Now all we need is a Vagrant configuration file to coordinate spinning up our VirtualBox image & running our DSC scripts:
Here we create a private network on the IP 10.0.0.30, running on hostname urlsvc.dev and we use rsync to share the current working directory into c:\vagrant on the Windows guest machine. We need to use rsync here as IIS does not work with VirtualBox shared folders. We then use the vagrant-dsc plugin to run our DSC scripts from Vagrant. This is really neat, because when we want to change our DSC configuration we can simple modify the files and then issue a vagrant provision –provision-with dsc to re-run the DSC provisioner only.
Now all we need to do is run vagrant:
This will import our new development machine image, provision it with DSC and sync the working directory into the guest – this means you can use Visual Studio, Xamarin or whatever to author your code and it will run remotely in your VM. We have also installed the Visual Studio remote debugger and opened up port 4018 so you can debug remotely. Nice.
You should now be able to navigate to http://urlsvc.dev from your host or guest machine, and hit our URL shortening service!
NOTE: we need to run vagrant rsync-auto to continually sync the working directory. This is only required when rsync is used as the shared folder type.
Using Packer, Vagrant and DSC we have managed to automate our entire development environment and have laid the foundations for the rest of our CD pipeline. Packer has bootstrapped a Windows machine from scratch and turned it into a Vagrant VirtualBox image that can be re-used by others. We used Vagrant to run this image, and configure our development runtime with DSC and can now develop in a clean, isolated and repeatable environment.
In the next installment, we will use Packer to build our Production and Build servers in Amazon from the same source configuration.