Vagrant: Require installed plugins

08 Jun 2015 in TIL

Whilst working on a project with a team that I don't normally work with, we needed a way to ensure that we're all using the same tools. One part of that was ensuring that at least a specific version of a Vagrant plugin was installed.

As the Vagrantfile is valid Ruby, we can write some code in there to make sure that our dependencies are fulfilled.

This code does not automatically install plugins as it's not fair to automatically change the state of someone's machine. Instead, it just alerts them to the fact that they need to install/update some plugins.

Vagrant 1.7.3+

Vagrant 1.7.3 isn't released yet, but this is the correct way to check plugin versions.

ruby
[
{ :name => "vagrant-omnibus", :version => ">= 1.4.1" },
{ :name => "vagrant-berkshelf", :version => ">= 4.0.3" },
{ :name => "vagrant-hostmanager", :version => ">= 1.5.0" },
{ :name => "vagrant-cachier", :version => ">= 1.2.0"}
].each do |plugin|
if not Vagrant.has_plugin?(plugin[:name], plugin[:version])
raise "#{plugin[:name]} #{plugin[:version]} is required. Please run `vagrant plugin install #{plugin[:name]}`"
end
end

Vagrant 1.7.2

Unfortunately there's a bug in Vagrant 1.7.2 that means that if the installed version of any plugin provides what you're asking for (not just the specific plugin you're asking about), the check will pass.

To work around this, we can access Vagrant::Plugin::Manager directly and perform the checks ourselves.

ruby
[
{ :name => "vagrant-omnibus", :version => ">= 1.4.1" },
{ :name => "vagrant-berkshelf", :version => ">= 4.0.3" },
{ :name => "vagrant-hostmanager", :version => ">= 1.5.0" },
{ :name => "vagrant-cachier", :version => ">= 1.2.0"}
].each do |plugin|
Vagrant::Plugin::Manager.instance.installed_specs.any? do |s|
req = Gem::Requirement.new([plugin[:version]])
if (not req.satisfied_by?(s.version)) && plugin[:name] == s.name
raise "#{plugin[:name]} #{plugin[:version]} is required. Please run `vagrant plugin install #{plugin[:name]}`"
end
end
end