website/www: blog post on vagrant 1.5 plugin improvements
This commit is contained in:
parent
c34954479b
commit
5de2bda9d7
|
@ -0,0 +1,147 @@
|
||||||
|
---
|
||||||
|
page_title: "Vagrant 1.5 Plugin Development Improvements"
|
||||||
|
title: "Plugin Development Improvements in 1.5"
|
||||||
|
author: "Mitchell Hashimoto"
|
||||||
|
author_url: https://github.com/mitchellh
|
||||||
|
---
|
||||||
|
|
||||||
|
Vagrant has a vibrant plugin community. We're always looking
|
||||||
|
to improve the life of a plugin developer through better abstractions,
|
||||||
|
documentation, and more. In Vagrant 1.5, we made some big improvements
|
||||||
|
that should make developing plugins much, much nicer.
|
||||||
|
|
||||||
|
With Vagrant 1.1, we both helped and hurt plugin development. Plugin
|
||||||
|
development improved because plugins became a first class supported
|
||||||
|
concept with the `vagrant plugin` command and much of the core dogfooding
|
||||||
|
the API.
|
||||||
|
|
||||||
|
But plugin development was hurt because Vagrant switched to
|
||||||
|
an installer-only model, breaking many plugin development environments
|
||||||
|
and causing some frustrating edge cases.
|
||||||
|
|
||||||
|
With Vagrant 1.5, we've made some big changes that should make the
|
||||||
|
life of a plugin developer much more enjoyable. Read on to find out more.
|
||||||
|
|
||||||
|
READMORE
|
||||||
|
|
||||||
|
### Real Dependency Resolution
|
||||||
|
|
||||||
|
In prior versions of Vagrant, there was no real dependency resolution
|
||||||
|
done for plugins. Dependency resolution is the process by which all
|
||||||
|
the dependencies of a set of components are inspected, and results in
|
||||||
|
the order and versions of components that must be loaded so that all
|
||||||
|
components properly work together.
|
||||||
|
|
||||||
|
To make this concrete, we can use an example from Vagrant 1.4, where
|
||||||
|
no dependency resolution took place:
|
||||||
|
|
||||||
|
* Plugin A depends on "foo >= 1.0, < 1.5".
|
||||||
|
* Plugin B depends on "foo = 1.1"
|
||||||
|
* When Plugin A is loaded, it would load the latest version satisfying
|
||||||
|
its contraints. This might be "foo 1.4".
|
||||||
|
* When Plugin B is loaded, it would try to load "foo 1.1" but since
|
||||||
|
"foo 1.4" is already loaded, it would fail!
|
||||||
|
|
||||||
|
The frustrating part of this failure is that it should _never happen_.
|
||||||
|
Plugin A should've loaded "foo 1.1" because it still satisfies its constraints
|
||||||
|
while also allowing Plugin B to load.
|
||||||
|
|
||||||
|
With Vagrant 1.5, Vagrant performs real dependency resolution. The effect
|
||||||
|
of this is twofold. First, in the scenario above, both plugin A and plugin B would load and
|
||||||
|
everything would _just work_.
|
||||||
|
|
||||||
|
Next, if the user attempts to install a plugin that can't be loaded because
|
||||||
|
it would create an unsolvable dependency conflict, then the user
|
||||||
|
will see an error at _install time_, and the plugin will fail to install.
|
||||||
|
Additionally, the user will be notified what dependencies conflict and
|
||||||
|
in what plugins.
|
||||||
|
|
||||||
|
### Bundler Support
|
||||||
|
|
||||||
|
Prior to Vagrant 1.5, Vagrant loaded plugins out of its own internal gem
|
||||||
|
directory. Because of this, plugin development was slightly awkward since
|
||||||
|
Vagrant wouldn't load your plugins from your `Gemfile`. As a result, plugin
|
||||||
|
developers had to create Vagrantfiles that manually did a `require` of all plugins
|
||||||
|
they needed.
|
||||||
|
|
||||||
|
Now, Vagrant 1.5 will automatically load any gems in the "plugins" group
|
||||||
|
in your `Gemfile`. As an example, here is the `Gemfile` for a "vagrant-bar"
|
||||||
|
plugin:
|
||||||
|
|
||||||
|
<pre class="prettyprint">
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
group :development do
|
||||||
|
gem "vagrant",
|
||||||
|
git: "https://github.com/mitchellh/vagrant.git"
|
||||||
|
end
|
||||||
|
|
||||||
|
group :plugins do
|
||||||
|
gem "vagrant-foo",
|
||||||
|
gem "vagrant-bar", path: "."
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
With the above, Vagrant will automatically load both "vagrant-bar" and
|
||||||
|
"vagrant-foo" plugins. Because of the `path: "."` option for "vagrant-bar",
|
||||||
|
it will use the plugin in that directory, allowing you to make changes
|
||||||
|
and instantly see changes.
|
||||||
|
|
||||||
|
You no longer need to do any `Vagrant.require_plugin` silliness in your
|
||||||
|
Vagrantfiles in order to activate your plugin.
|
||||||
|
|
||||||
|
### API Compatibility
|
||||||
|
|
||||||
|
We're improving our promise on API compatibility. Prior to Vagrant 1.5,
|
||||||
|
we had no promise of API compatibility except at major versions (1.0, 2.0,
|
||||||
|
etc.). Because these versions are so far apart, we're making our promise stronger.
|
||||||
|
|
||||||
|
With Vagrant 1.5, we promise to not break API compatibility of internals
|
||||||
|
_between_ minor versions. For example, if your plugin works with 1.5.0,
|
||||||
|
it should work with a potential 1.5.7 months later. However, it is
|
||||||
|
_not_ promised to work with Vagrant 1.6.
|
||||||
|
|
||||||
|
Given this, it actually becomes quite easy to remain API compatible. As an
|
||||||
|
example, the [Vagrant VMware](/vmware) plugin is compatible back to
|
||||||
|
Vagrant 1.1. This is done through various code branching that looks like
|
||||||
|
the following:
|
||||||
|
|
||||||
|
<pre class="prettyprint lang-ruby">
|
||||||
|
if Vagrant::VERSION < "1.5.0"
|
||||||
|
# Compatibility layer
|
||||||
|
else
|
||||||
|
# New stuff available
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
If we break your plugin between minor versions, we'll treat it like a bug
|
||||||
|
so please report it as such.
|
||||||
|
|
||||||
|
### New Functionality
|
||||||
|
|
||||||
|
In addition to these major improvements, we've introduced some great
|
||||||
|
new functionality that plugin developers can take advantage of in Vagrant 1.5.
|
||||||
|
|
||||||
|
**Provider capabilities** allow providers to opt-in to provider-specific
|
||||||
|
functionality. Plugins can query whether the provider supports a certain
|
||||||
|
functionality and behave accordingly. As an example use case, the recently
|
||||||
|
announced [Vagrant Share](#)
|
||||||
|
functionality uses a provider-capability `read_ip_address` to ask
|
||||||
|
providers for an accessible IP address to the machine.
|
||||||
|
|
||||||
|
**New built-in middleware** such as `IsState` and `Message` remove a lot
|
||||||
|
of boilerplate from implementing new providers.
|
||||||
|
|
||||||
|
**A new internal class** `Vagrant::Vagrantfile` allows plugins to load
|
||||||
|
Vagrantfiles and request `Vagrant::Machine` objects from that Vagrantfile
|
||||||
|
outside of the default root Vagrantfile that is part of a
|
||||||
|
`Vagrant::Environment`.
|
||||||
|
|
||||||
|
And much, much more.
|
||||||
|
|
||||||
|
### Future Improvements
|
||||||
|
|
||||||
|
We're constantly interested in improving plugin development for Vagrant
|
||||||
|
since it is a core part of what makes Vagrant successful. We have some
|
||||||
|
improvements planned but if you see anything you want improved, please
|
||||||
|
help us out by letting us know!
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
&.blog-landing, &.blog-post {
|
&.blog-landing, &.blog-post {
|
||||||
article {
|
article {
|
||||||
|
letter-spacing: normal;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
|
|
||||||
.meta {
|
.meta {
|
||||||
|
|
Loading…
Reference in New Issue