I wrote a Packer plugin ✨
It’s called Caryatid.
An Atlas is “a support sculpted in the form of a man”; a Caryatid is such a support in the form of a woman.
It lets you manage versions of Vagrant box files on local storage in a “Vagrant catalog” by automatically creating or updating that catalog at the end of your packer build. The catalog will present box version info the same way that Atlas does. In the future, it will support remote catalogs like over SSH as well. It’s basically a plugin that automates this tutorial which walks through manually setting up Vagrant catalogs.
I actually made the 1.0 release almost two months ago, but I haven’t gotten around to making a blog post til now. lol
I had never written a Packer plugin or, indeed, a single line of Go, so I’m pretty happy with how this turned out.
It’s written in Go, so it’s been tested on Windows and macOS, and it should work on Linux as well.
Example
Here is a packer template that uses Caryatid. Note that the weird {{isotime...}}
thing in the version
variable is specifying a date format of YYYYMMDDhhmmss, not the date itself.
"variables": {
"boxname": "testbox",
"version": "1.0.{{isotime \"20060102150405\"}}",
"description": "a box for testing",
"catalog_root_url": "file://{{env `HOME`}}/vagrantboxes"
},
"builders": [
{
"type": "virtualbox",
...<snip>...
}
]
...<snip>...
"post-processors": [
[
{ "type": "vagrant", },
{
"type": "caryatid",
"name": "{{user `boxname`}}",
"version": "{{user `version`}}",
"description": "{{user `description`}}",
"catalog_root_url": "{{user `catalog_root_url`}}"
}
]
]
A successful packer invocation would result in a directory structure like this:
$HOME/vagrantboxes
/testbox.json: the JSON catalog
/testbox
/testbox_1.0.0_virtualbox.box: the large VM box file itself
And the testbox.json
catalog will look like this. Note that the isotime
function call has resulted in a real date (corresponding to the time I was writing this post), which can pass for a very long component of a version number.
{
"name": "testbox",
"description": "a box for testing",
"versions": [{
"version": "1.0.201704051656",
"providers": [{
"name": "virtualbox",
"url": "file:///srv/vagrant/testbox/testbox_virtualbox_1.0.201704051656.box",
"checksum_type": "sha1",
"checksum": "d3597dccfdc6953d0a6eff4a9e1903f44f72ab94"
}]
}]
}
You can then set the config.vm.box_url
value in a Vagrantfile to point to file://$HOME/vagrantboxes/testbox.json
(you may need to expand the $HOME
variable to be its actual value, like /home/USERNAME
), and Vagrant will pull the box from there. It works with multiple builders - so, if you have a VMware and a Fusion builder in your packer template, it will result in a testbox_virtualbox_1.0.201704051656.box
and a testbox_vmware_1.0.201704051656.box
, and have both a virtualbox
and vmware
provider in the resulting Vagrant catalog. Vagrant will choose the latest version of whatever provider is set as the config.vm.provider
in the Vagrantfile.
Future
I really want to support remote Vagrant catalogs over SSH. Vagrant is supposed to support scp, but apparently doesn’t bundle a properly-built curl
yet. This means you may need to build your own curl
that supports scp, and possibly even replace your system-supplied curl with that one, in order to use catalogs hosted on scp with Vagrant. (Note that Caryatid will not rely on curl, so even if your curl is old, we will still be able to push to scp backends; the only concern is whether your system’s Vagrant can pull from them by default or not.)
I also have other ideas, like a WebDAV or S3 mode, that I’m considering.