What’s New In HashiCorp Vagrant 2.2.6
The recent HashiCorp Vagrant 2.2.6 that was released came with a couple of new and interesting features. Dependency provisioners offer a new way to control when your provisioners run for a given guest. Additionally, Vagrant and Vagrant Cloud now offer support for validating the checksum for a published box. In this post, we’ll outline these two new features of Vagrant.
» Dependency Provisioners
Provisioning has always been a core feature of Vagrant. There are many different kinds of provisioners today that use different tools to help set up and configure a Vagrant guest. However, until the introduction of Dependency Provisioners, Vagrant was only able to run provisioners in the "linear" order that they are defined within a Vagrantfile. Vagrant does not evaluate Vagrantfiles strictly top to bottom which can result in some surprising behavior. Take this Vagrantfile for example:
Vagrant.configure("2") do |config|
config.vm.box = “hashicorp/bionic64”
config.vm.provision "A", type: "shell", inline:<<-SHELL
echo 'A'
SHELL
config.vm.define “guest” do |guest|
guest.vm.provision "B", type: "shell", inline:<<-SHELL
echo 'B'
SHELL
end
config.vm.provision "C", type: "shell", inline:<<-SHELL
echo 'C'
SHELL
end
If provisioners truly ran in the order they are defined in a Vagrantfile, you would expect the output of running this Vagrantfile to print: A -> B -> C. Due to how Vagrant parses Vagrantfiles, however, the globally defined provisioners "A"
and "C"
actually run before "B"
. While this is just a basic example, dependency provisioners allow users to have finer grained control over exactly when they want a provisioner to run during the provision step. Here’s how to use a dependency provisioner:
# A dependency provisioner that runs before “Configure”
config.vm.provision "Hello", before: “Configure”, type: "shell", inline:<<-SHELL
echo 'The first provisioner!'
SHELL
# A dependency provisioner that runs after the configure
config.vm.provision "Finished", after: “Configure”, type: "shell", inline:<<-SHELL
echo 'Vagrant finished updating your system!'
SHELL
config.vm.provision "Configure", type: "shell", inline:<<-SHELL
apt-get update
apt-get install vim tmux tree -y
apt-get upgrade -y
SHELL
If a provisioner has been configured using the before
or after
options, it is considered a Dependency Provisioner. This means it has been configured to run before or after a Root Provisioner, which does not have the before
or after
options configured. Root Provisioners can be thought of as a traditional Vagrant provisioner prior to the 2.2.6 release, and behave the way provisioners have prior to this release.
By giving the before or after options a string value "Name" that refers to a Root Provisioner, a dependency provisioner can be defined to run before or after that named provisioner. Not only will these keys allow users to modify the run order for their provisioners, they will also allow users to specify if a provisioner should run more than once. Instead of giving a "Name" string, users will also be able to provide an array of strings which contain the names of multiple provisioners. This allows the provisioner to be defined once, but run before or after each of the defined named provisioners. Dependency provisioners also have two valid shortcuts for the before and after keys: :each
and :all
:
# This will run before any defined provisioner for a given Vagrant guest
config.vm.provision "Hello", before: :all, type: "shell", inline:<<-SHELL
echo 'The first provisioner!'
SHELL
# This will run after every defined provisioner for a given Vagrant guest
config.vm.provision "Next", after: :each, type: "shell", inline:<<-SHELL
echo 'The provisioner finished!'
SHELL
Now that we’ve introduced Dependency Provisioners, let’s fix our original example and have the provisioners run in A -> B -> C order:
Vagrant.configure("2") do |config|
config.vm.box = “hashicorp/bionic64”
config.vm.provision "A", type: "shell", inline:<<-SHELL
echo 'A'
SHELL
config.vm.define “guest” do |guest|
guest.vm.provision "B", after, “A”, type: "shell", inline:<<-SHELL
echo 'B'
SHELL
end
config.vm.provision "C", type: "shell", inline:<<-SHELL
echo 'C'
SHELL
end
Because this feature is experimental, you will need to enable it using the VAGRANT_EXPERIMENTAL
environment variable. For example, on Linux or macOS you would run:
VAGRANT_EXPERIMENTAL="dependency_provisioners" vagrant up guest
If you are on Windows using Powershell, you would enable this feature by exporting the same environment variable:
$env:VAGRANT_EXPERIMENTAL = "dependency_provisioners"
vagrant up guest
Running this will now make our Vagrantfile provisioners run in A -> B -> C order. It should be noted that without the experimental flag, provisioner "B"
would run like a normal provisioner from our first example.
For more information on how to use Dependency Provisioners, please check out the documentation on Vagrant Up.
» Limitations
Dependency provisioners introduce two new top-level keys for the provisioner class: before and after. Because of how the class was designed, it means that when older Vagrant clients try to parse a Vagrantfile with dependency triggers defined, it will fail to parse the dependency provisioners properly and result in a stack trace to the user.
Additionally, as of Vagrant 2.2.6, dependency provisioners cannot rely on other dependency provisioners and is considered a configuration state error in Vagrant. If you must order dependency provisioners, you can still order them by the order they are defined inside your Vagrantfile.
» Vagrant Box Checksum Validation
With this release, we have added support for Vagrant box checksums to Vagrant Cloud. When the checksum value is set, Vagrant will automatically validate that the downloaded box matches the checksum before unpacking. Vagrant versions prior to 2.2.6 will only validate MD5 and SHA1 checksums. Support for SHA256, SHA384, and SHA512 were added in the 2.2.6 release.
Checksum information can be added to boxes directly on the Vagrant Cloud website. Alternatively, they can be added using the Vagrant Cloud API, or by using the vagrant cloud
commands when creating or updating boxes.
» Conclusion
For more information about Vagrant, go to the website at vagrantup.com and read the documentation.
Sign up for the latest HashiCorp news
More blog posts like this one
Vagrant Cloud is moving to HCP
Vagrant Cloud is moving to HashiCorp Cloud Platform (HCP) as the HCP Vagrant Registry.
HashiCorp 2022 Year in Review
Before we ring in the new year, here’s a look back at some of the most important moments in 2022 for HashiCorp.
Vagrant 2.3 Introduces Go Runtime
HashiCorp Vagrant 2.3 introduces a new Vagrant executable written in Golang, tying the Vagrant architecture more closely into the broader HashiCorp ecosystem.