MikeMattice-Headshot-2017-10-02.jpg

Mike Mattice
/mmattice@hoegg.software

LinkedIn

 

Packer is your automation friend

It all started when...

Years ago, I built up a Windows XP machine whose sole purpose was to build/develop a Win32 based application.  I took a list of dependencies from someone that had a build environment already set up and I painstakingly poked them all into the box until the software would build.

This was the snowflakiest snowflake machine I'd ever put together.  The only way this wasn't terribly scary day to day was the fact that I was running it as a virtual machine and had snapshots of the state.  If I totally hosed it by running or installing anything, I could just roll it back.  Eventually, that box running only on my VM was considered _critical_ infrastructure by someone other than myself.  That got it a nice spot on a host in the data center instead of just my potentially disposable laptop.

While that's a huge step forward, it would have made me feel much better if I could rebuild that box as needed.  I would feel even better if I could upgrade pieces of it in some automated way and run my unit and integration tests to verify my builds still worked.

Presently, I'm helping out a large company that had someone else snowflake up a box to build a different Windows based build system.

Thankfully, [packer](https://packer.io) is a thing now.  Between Hashicorp's tool and some powershell scripting, fully automated Windows machine building is a thing.  With it, I can build a VM image that can be distributed to all the members of the cross functional team working on the software and an exceptionally similarly outfitted node to drop into a pipeline as an agent.

One also gets the ability to treat your software stack install process as code.  This means you can make those slight adjustments over time and do proper regression tests on those changes.

Now, you can also do this sort of thing with Ansible, Chef, Puppet or any number of other configuration management systems, but packer has advantages over these relatively heavy technologies in my eyes.  While it's a single binary, it still has functionality built into it to run builds on over 20 different systems and presently run 14 different provisioners, including Ansible, Chef, and Puppet.

Packer is still a relatively new technology to me and I'll be the first to admit to having a few troubles getting it do what I want on AWS, but I've worked around that for now by building VM's locally and letting Amazon convert them to AMIs for me. 

 
  ```json
    {
      "type": "shell",
      "inline": [
        "C:/ProgramData/chocolatey/choco.exe install -y cmake --version 3.7.2",
        "C:/ProgramData/chocolatey/choco.exe install -y python2 --version 2.7.14",
        "C:/ProgramData/chocolatey/choco.exe install -y git.install --version 2.14.2.20170927",
        "C:/ProgramData/chocolatey/choco.exe install -y microsoft-build-tools --version 14.0.23107.10"
      ]
    }
```

This chunk of code above goes in the `provisioners` section of the json template that Packer uses to create your machine.  It reads super easily (except for the quoting and the weird forward slashes on the paths (but, you can write out scripts on your local disk and invoke those)), yet is remarkably powerful.  `chocolatey` is a huge help here too; tasking it with installing specific versions of software that are known to work.

```powershell
$iso = 'C:\Windows\Temp\VS2102_PRO_enu.iso'
$uri = 'http://download.microsoft.com/download/D/E/8/DE8E42D8-7598-4F4E-93D4-BB011094E2F9/VS2012_PRO_enu.iso'
$wc = New-Object System.Net.WebClient
Write-Output "Downloading ${uri} to ${iso}"
$wc.DownloadFile($uri, $iso)
dir ${iso}
$drive=(Mount-DiskImage -ImagePath $iso -passthru | get-volume).driveletter
iex "${drive}:\\vs_professional.exe /adminfile ${drive}:\\AdminDeployment.xml /quiet /norestart /ProductKey ********************* | Out-Null"
DisMount-DiskImage -ImagePath $iso
rm $iso
```


```json
   {
    "type": "powershell",
    "scripts": [
      "scripts/install_vs2012.ps1"
    ]
   }
```

If you need to download some software on an ISO, you can do this magic.  This method is unnecessary if you're building machines locally, as you can make Packer tell `virtualbox` to mount an ISO image directly, like so.

```json
        [
          "storagectl", "{{.Name}}", "--name", "SataController", "--add", "sata", "--controller", "IntelAHCI"
        ],
        [
          "storageattach", "{{.Name}}", "--storagectl", "SataController", "--port", "0",
          "--device", "0", "--type", "dvddrive", "--medium", "./iso/VS2012_PRO_enu.iso"
        ]
```

The [packer-windows](https://github.com/joefitzgerald/packer-windows) repo is a great starting point for most recent versions of Windows going with little trouble.

Now, if I'd only had this tech 10 years ago...