This introduces the new network configuration syntax for Vagrant 1.1
and forward.
== The Problem
With multiple providers, the concept of networking as it stands in Vagrant
1.0.x becomes really muddy. We have `config.vm.forward_port` and
`config.vm.network :hostonly` and `config.vm.network :bridged`. But what
if someone writes an AWS provider? What is a bridged network in AWS? It
just doesn't make sense.
Networking working out of the box with Vagrant is a core part of what
makes Vagrant "magic" to new users. It is a core part of what makes Vagrant
simple to use. One option to punt networking to provider-specific
configuration was considered, but I found the whole idea of networking
too core to Vagrant to simply punt.
Because of this, a whole new method of networking is introduced.
== The Solution
The solution is to have a high-level notion of networking for Vagrant
configuration. This should cover the most _common_ cases of networking, and
every provider should do their best to implement these high-level
abstractions, to ensure the "just works" nature of Vagrant.
In addition to this high-level networking, low-level networking options
should be exposed on the provider configuration. This allows users to do
advanced provider-specific networking configuration if they want, but aren't
required to.
== High-Level Abstractions
=== Available Types
The high-level abstractions built into Vagrant will be the following:
* Forwarded ports - A mapping of host port to guest port that one can hit
using `localhost`.
* Private network - A private network, the machine should ideally be
protected from public access.
* Public network - A public network, one that is easily accessible by
others.
I'm not sure if these are the proper abstractions. They can change up
until 2.0, but these are what we have so far.
Theoretically, here is how mappings would work. Note that this is just
an example, and the mappings in practice of such providers may or
may not map to this as follows.
**VirtualBox**
* Forwarded ports - NAT network, forwared ports.
* Private network - Hostonly network, static IP assigned.
* Public network - Bridged network, IP assigned via DHCP from router.
**VMWare**
* Forwarded ports - NAT network, forwarded ports.
* Private network - Hostonly network, static IP assigned.
* Public network - Bridged network, IP assigned via DHCP from router.
**AWS**
* Forwarded ports - Unimplemented.
* Private network - Public DNS in EC2, private IP in VPC.
* Public network - Elastic IP in EC2 and VPC.
=== Syntax
Networks are configured at the top-level of a Vagrantfile:
```ruby
Vagrant.configure("2") do |config|
# ...
config.vm.network :forwarded_port, 80, 8080
config.vm.network :private_network, "192.168.1.12"
config.vm.network :public_network
end
```
Providers should do their best to honor these configurations.
=== Advanced Options
While providers should do their best to satisfy the requirements for the
high-level abstractions, it is expected that provider-specific configuration
may be possible per network, even for the high-level configurations. For
this, provider-prefixed configuration options should be done:
```ruby
config.vm.network :forwarded_port, 80, 8000,
:vmware__device => "vmnet8"
config.vm.network :public_network,
:aws__elastic_ip => "1.2.3.4",
:vmware__device => "en0"
```
If at all possible, providers should **not** require advanced options for
these to function.
== Low-level Configuration
While the high-level configuration should satisfy the common case and make
Vagrant work out of the box for most providers, one of the large benefits of
many providers is the ability to do certain networking tricks. For example,
KVM, Hyper-V, vSphere, etc. can create and be a part of true VLANs, which
may be required for certain upstream networking rules/ACLs. For things like
this, the network configuration should go directly into the provider
configuration in some way.
Examples:
```ruby
config.vm.provider :virtualbox do |vb|
vb.network_adapter 2, :hostonly
vb.network_adapter 3, :nat
end
config.vm.provider :aws do |aws|
aws.routing_table = "route-123456"
end
```
It is up to the provider implementation to define the configuration
syntax as well as the implementation details of such an option. Other
providers are unable to see provider configurations other than their own
so it is truly private to the provider.
This branch brings in a whole lot of awesome. The name does not do it
justice. The list of things that comes into play here:
* "virtualbox" is no longer hardcoded anywhere in core. It is the default
provider, yes, but it is 100% possible now to slip in another provider
and have it work.
* `vagrant up --provider` is a thing. This allows you to specify an
alternate provider. Note that the other commands don't support
`--provider` yet so its not THAT useful, but its getting really close.
* True V2 configuration is in place. That means that `Vagrant.configure`
calls now are loading a completely new configuration version, and old
1.0.x Vagrantfiles are V1 configuration. V1 configuration is upgraded
automatically internally, so backwards compatibility is maintained.
Magic, people, magic.
* `config.vm.provider` is the major new configuration option. This is
how provider-specific configuration will be done. For example, Vagrant
has always provided a way to make a pass of `VBoxManage` calls to
customize your VM via `config.vm.customize` in V1. This now exists
as a VirtualBox configuration option. See the example here:
https://gist.github.com/98f5a0df6a05286dfb73
* Unit tests no longer depend on VirtualBox being installed, because for
unit tests we slip in a "no-op" provider, which is a fully valid
Vagrant provider plug-in that does... NOTHING! Brilliant!
* Lots of core middleware executor improvements that make writing and
using middleware stacks a lot more enjoyable. Enjoy a set of "standard
library middlewares" provided by Vagrant in Vagrant::Action::Builtin.
The multi-provider is really shaping up here.
This works by registering a `config` with `:provider => true` with the
same name as your provider. Vagrant will then automatically configure
the provider when `config.vm.provider` is used.