vagrant-auto_network 0.2.2 → 1.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NzlhOTk0NThjMzA5MTNkYzZhYzFiNTJkZDU1ODQzOGE0YWU2NDU4Mg==
5
- data.tar.gz: !binary |-
6
- YzIxNzVkYzI0N2RlMTkyZjAyYjA3OWNlNjgzMjhlN2JhZTcyMDlkYg==
2
+ SHA1:
3
+ metadata.gz: 1d671793aef1384eda1a6563c8c5c82fb5ef080f
4
+ data.tar.gz: d1e246dfdc649d07761ae4d778557ff796fb66af
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NGUxNjYyM2JlYTRmZTEwOTI4ZjMxZGJkMmIxMzljYjRhZjUxMzBjNmQ1NGRj
10
- YTg4NjVjY2ZlNzdiOGM3ZTZhNmM4Yjk5N2QwZmIyZTAwOGY2MjNlMDFkOTVm
11
- NTlmYjBlN2JiMWI3MGY4Yjg3OWUwYTQ0NWQyMjg3ZTFkYTY1MTc=
12
- data.tar.gz: !binary |-
13
- NjgwZTBlYmMwMmZlZTUyNjM2YTUxMWY5NDgwZDg2ZmU3ZjllYTNjNmMzOGE2
14
- ZDE3NDNlNjhjZDZmNDc0MDA1MzZlNGQ2MTg5OTExOTFjMjJjMWY2YzhkMmU1
15
- YjY2YTMyODY2ZmI0NjM4MmI0ZjM1YTQ4NTRiNGRkNGY2Y2QzODU=
6
+ metadata.gz: de702cdcb9d60ab2d1f55116b9a6d7a4cd4f392892e49fba9ae4764c87fe2c0024e6916f439f963e2bec84b77d568a6b73bef3abd427e1f0a1499bb19a7a8d77
7
+ data.tar.gz: e83c9eb3a06775ccf5fa59e5ab837a6d05f767f36babc1ce9ee7a5f08a1826a7ea18107df9df2df230032cc792cb377fc1da20e67538b1c53ada63f0b1c64e5d
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/CHANGELOG CHANGED
@@ -1,6 +1,32 @@
1
1
  vagrant-auto_network
2
2
  ====================
3
3
 
4
+ 1.0.0
5
+ -----
6
+
7
+ 2014-05-05
8
+
9
+ This is a mostly-backwards compatible feature release.
10
+
11
+ For this release, serialization format has been completely re-written to add
12
+ support for multiple providers and to better manage global state and guard
13
+ against race conditions. Care has been taken to support existing AutoNetwork
14
+ environments, but it is possible that some breakage will occur.
15
+
16
+ Specifically, the following issues have been addressed:
17
+
18
+ * (GH-12) Support for more than just the VirtualBox provider. The
19
+ implementation has been tested against the VMware Fusion provider but
20
+ should be general enough to support other providers as well.
21
+
22
+ * (GH-2) The infamous `0.0.0.0` hack is no longer necessary when using
23
+ AutoNetwork.
24
+
25
+ * (GH-6) The IP address pools managed by AutoNetwork are now backed by a
26
+ storage mechanism that offers more resiliance to race conditions and data
27
+ loss from aborted actions.
28
+
29
+
4
30
  0.2.2
5
31
  -----
6
32
 
data/Gemfile CHANGED
@@ -1,3 +1,12 @@
1
1
  source 'https://rubygems.org'
2
+ ruby '2.0.0'
2
3
 
3
4
  gemspec
5
+
6
+ group :development do
7
+ gem 'vagrant', :github => 'mitchellh/vagrant', :tag => 'v1.5.4'
8
+ end
9
+
10
+ if File.exists? "#{__FILE__}.local"
11
+ eval(File.read("#{__FILE__}.local"), binding)
12
+ end
data/lib/auto_network.rb CHANGED
@@ -7,6 +7,7 @@ module AutoNetwork
7
7
  require 'auto_network/mixin'
8
8
  require 'auto_network/plugin'
9
9
  require 'auto_network/version'
10
+ require 'auto_network/pool_manager'
10
11
  end
11
12
 
12
13
  I18n.load_path << File.expand_path('../templates/locales/en.yml', File.dirname(__FILE__))
@@ -50,7 +50,7 @@ class AutoNetwork::Action::FilterNetworks
50
50
  def assign_address(machine)
51
51
  machine_auto_networks(machine).each do |net|
52
52
  addr = @pool.address_for(machine)
53
- @logger.info "Reassigning #{addr.inspect} to existing machine #{machine.id}"
53
+ @logger.info "Reassigning #{addr.inspect} to existing machine #{machine.name}"
54
54
  filter_private_network(net, addr)
55
55
  end
56
56
  end
@@ -1,5 +1,4 @@
1
1
  require 'auto_network'
2
- require 'yaml'
3
2
 
4
3
  class AutoNetwork::Action::LoadPool
5
4
 
@@ -23,7 +22,6 @@ class AutoNetwork::Action::LoadPool
23
22
  setup_ivars
24
23
  deserialize!
25
24
  @app.call(@env)
26
- serialize!
27
25
  else
28
26
  @app.call(@env)
29
27
  end
@@ -41,21 +39,6 @@ class AutoNetwork::Action::LoadPool
41
39
  end
42
40
 
43
41
  def deserialize!
44
- pool = nil
45
- if @statefile.exist?
46
- pool = YAML.load(@statefile.read)
47
- else
48
- range = AutoNetwork.default_pool
49
- @env[:ui].info "No auto_network pool available, generating a pool with the range #{range}"
50
- pool = AutoNetwork::Pool.new(range)
51
- end
52
- @env[:auto_network_pool] = pool
53
- end
54
-
55
- def serialize!
56
- @config_path.mkpath unless @config_path.exist?
57
-
58
- pool_data = YAML.dump(@env[:auto_network_pool])
59
- @statefile.open('w') { |fh| fh.write(pool_data) }
42
+ @env[:auto_network_pool] = AutoNetwork::PoolManager.new(@statefile)
60
43
  end
61
44
  end
@@ -31,7 +31,7 @@ class AutoNetwork::Action::Release
31
31
 
32
32
  def release_network_addresses
33
33
  addr = @pool.address_for(@machine)
34
- @env[:ui].info "Releasing #{addr.inspect} from #{@machine.id}", :prefix => true
34
+ @env[:ui].info "Releasing #{addr.inspect} from #{@machine.name}", :prefix => true
35
35
  @pool.release(@machine)
36
36
  end
37
37
  end
@@ -32,7 +32,7 @@ class AutoNetwork::Action::Request
32
32
  def request_address
33
33
  machine_auto_networks(@machine).each do |net|
34
34
  addr = @pool.request(@machine)
35
- @env[:ui].info "Assigning #{addr.inspect} to '#{@machine.id}'", :prefix => true
35
+ @env[:ui].info "Assigning #{addr.inspect} to '#{@machine.name}'", :prefix => true
36
36
  filter_private_network(net, addr)
37
37
  end
38
38
  end
@@ -19,14 +19,18 @@ module AutoNetwork
19
19
  hook.after(action, AutoNetwork::Action::FilterNetworks)
20
20
  end
21
21
 
22
- action_hook('Auto network: request address', :machine_action_up) do |hook|
23
- action = VagrantPlugins::ProviderVirtualBox::Action::Network
22
+ action_hook('Auto network: request address') do |hook|
23
+ action = Vagrant::Action::Builtin::ConfigValidate
24
24
  hook.before(action, AutoNetwork::Action::Request)
25
25
  end
26
26
 
27
27
  action_hook('Auto network: release address', :machine_action_destroy) do |hook|
28
- action = VagrantPlugins::ProviderVirtualBox::Action::Destroy
29
- hook.before(action, AutoNetwork::Action::Release)
28
+ # This is redundant, but the VirtualBox Destroy Action flushes UUID
29
+ # values. So we double the hook here as it is our only chance to clean
30
+ # old-style IDs out of the cache.
31
+ hook.before(VagrantPlugins::ProviderVirtualBox::Action::Destroy, AutoNetwork::Action::Release)
32
+
33
+ hook.append(AutoNetwork::Action::Release)
30
34
  end
31
35
  end
32
36
  end
@@ -1,28 +1,43 @@
1
1
  require 'ipaddr'
2
+ require 'vagrant/errors'
2
3
 
3
4
  module AutoNetwork
5
+ # The Pool is a class that manages a range of IP addresses and manages the
6
+ # allocation of specific addresses to individual Vagrant machines.
4
7
  class Pool
5
8
 
9
+ # An error class raised when no allocatable addresses remain in the Pool.
10
+ #
11
+ # @api private
6
12
  class PoolExhaustedError < Vagrant::Errors::VagrantError
7
13
  error_key(:pool_exhausted, 'vagrant_auto_network')
8
14
  end
9
15
 
10
- # @param network_addr [String] The network address range to use as the
16
+ # @!attribute [r] network_range
17
+ # @return [String] The address range manged by this Pool instance.
18
+ attr_reader :network_range
19
+
20
+ # Create a new Pool object that manages a range of IP addresses.
21
+ #
22
+ # @param network_range [String] The network address range to use as the
11
23
  # address pool.
12
24
  def initialize(network_range)
13
25
  @network_range = network_range
14
26
  generate_pool
15
27
  end
16
28
 
17
- # Retrieve an IP address for the given machine. If a machine already has
18
- # an IP address requested, then return that.
29
+ # Allocate an IP address for the given machine. If a machine already has an
30
+ # IP address allocated, then return that.
19
31
  #
20
32
  # @param machine [Vagrant::Machine]
33
+ # @return [IPAddr] the IP address assigned to the machine.
34
+ # @raise [PoolExhaustedError] if no allocatable addresses remain in the
35
+ # range managed by the pool.
21
36
  def request(machine)
22
37
  if (address = address_for(machine))
23
38
  return address
24
39
  elsif (address = next_available_lease)
25
- @pool[address] = machine.id
40
+ @pool[address] = id_for(machine)
26
41
  return address
27
42
  else
28
43
  raise PoolExhaustedError,
@@ -31,20 +46,41 @@ module AutoNetwork
31
46
  end
32
47
  end
33
48
 
34
- # Release an IP address associated with a machine
49
+ # Release an IP address associated with a machine.
35
50
  #
36
51
  # @param machine [Vagrant::Machine]
52
+ # @return [nil]
37
53
  def release(machine)
38
54
  if (address = address_for(machine))
39
55
  @pool[address] = nil
40
56
  end
41
57
  end
42
58
 
59
+ # Look up the address assigned to a given machine.
60
+ #
61
+ # @param machine [Vagrant::Machine]
62
+ # @return [IPAddr] the IP address assigned to the machine.
63
+ # @return [nil] if the machine has no address assigned.
43
64
  def address_for(machine)
44
- return nil if machine.id.nil?
45
- next_addr, _ = @pool.find { |(addr, id)| machine.id == id }
65
+ machine_id = id_for(machine)
66
+ addr, _ = @pool.find do |(addr, id)|
67
+ if id.is_a?(String)
68
+ # Check for old-style UUID values. These should eventually cycle out
69
+ # as machines are destroyed.
70
+ id == machine.id
71
+ else
72
+ id == machine_id
73
+ end
74
+ end
46
75
 
47
- next_addr
76
+ addr
77
+ end
78
+
79
+ def id_for(machine)
80
+ {
81
+ 'path' => machine.env.root_path.to_s,
82
+ 'name' => machine.name.to_s,
83
+ }
48
84
  end
49
85
 
50
86
  private
@@ -0,0 +1,130 @@
1
+ require 'auto_network/pool'
2
+ require 'auto_network/pool_storage'
3
+ require 'ipaddr'
4
+
5
+ module AutoNetwork
6
+ # The `PoolManager` class manages the mapping between providers and pools of
7
+ # IP addresses. Each `PoolManager` instance is backed by a file that persists
8
+ # state and attempts to prevent race conditions between multiple Vagrant
9
+ # processes.
10
+ #
11
+ # Once created, `PoolManager` instances proxy the public interface of the
12
+ # {AutoNetwork::Pool} instances they manage. New pools will be allocated as
13
+ # needed and all pool operations are wrapped in transactions that ensure
14
+ # state is synced to the file system.
15
+ #
16
+ # @see AutoNetwork::PoolStorage The object used to implement file-based
17
+ # persistance for this class.
18
+ # @see AutoNetwork::Pool The objects managed by this class.
19
+ class PoolManager
20
+ # Create a new `PoolManager` instance with persistent storage.
21
+ #
22
+ # @param path [String, Pathname] the location at which to persist the state
23
+ # of `AutoNetwork` pools.
24
+ def initialize(path)
25
+ # Ensure newly created files start with a skeleton data structure.
26
+ AutoNetwork::PoolStorage.init(path) unless File.file?(path)
27
+ @pool_storage = AutoNetwork::PoolStorage.new(path)
28
+ end
29
+
30
+ # Looks up the pool associated with the provider for a given machine and
31
+ # sets up a transaction where the state of the pool can be safely inspected
32
+ # or modified. If a pool does not exist for the machine provider, one will
33
+ # automatically be created.
34
+ #
35
+ # @param machine [Vagrant::Machine]
36
+ # @param read_only [Boolean] whether to create a read_only transaction.
37
+ # @yieldparam pool [AutoNetwork::Pool]
38
+ def with_pool_for(machine, read_only=false)
39
+ @pool_storage.transaction(read_only) do
40
+ pool = lookup_pool_for(machine)
41
+ pool ||= generate_pool_for(machine)
42
+
43
+ yield pool
44
+ end
45
+ end
46
+
47
+ # {include:AutoNetwork::Pool#request}
48
+ #
49
+ # @see AutoNetwork::Pool#request
50
+ def request(machine)
51
+ with_pool_for(machine) do |pool|
52
+ pool.request(machine)
53
+ end
54
+ end
55
+
56
+ # {include:AutoNetwork::Pool#release}
57
+ #
58
+ # @see AutoNetwork::Pool#release
59
+ def release(machine)
60
+ with_pool_for(machine) do |pool|
61
+ pool.release(machine)
62
+ end
63
+ end
64
+
65
+ # {include:AutoNetwork::Pool#address_for}
66
+ #
67
+ # @see AutoNetwork::Pool#address_for
68
+ def address_for(machine)
69
+ with_pool_for(machine, read_only=true) do |pool|
70
+ pool.address_for(machine)
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ # Retrieve the {AutoNetwork::Pool} assigned to the provider of a given
77
+ # machine.
78
+ #
79
+ # @note This must be executed within a transaction.
80
+ # @api private
81
+ #
82
+ # @param machine [Vagrant::Machine]
83
+ # @return [AutoNetwork::Pool] the pool associated with the machine
84
+ # provider.
85
+ # @return [nil] if no pool exists for the machine provider.
86
+ def lookup_pool_for(machine)
87
+ @pool_storage['pools'][machine.provider_name.to_s]
88
+ end
89
+
90
+ # Create an {AutoNetwork::Pool} assigned to the provider of a given
91
+ # machine.
92
+ #
93
+ # @note This must be executed within a transaction.
94
+ # @api private
95
+ #
96
+ # @param machine [Vagrant::Machine]
97
+ # @return [AutoNetwork::Pool] the pool associated with the machine
98
+ # provider.
99
+ def generate_pool_for(machine)
100
+ if lookup_pool_for(machine).nil?
101
+ @pool_storage['pools'][machine.provider_name.to_s] = AutoNetwork::Pool.new(next_pool_range)
102
+ end
103
+
104
+ lookup_pool_for(machine)
105
+ end
106
+
107
+ # Scan the list of allocated pools and determine the next usable address
108
+ # range. Assumes all Pools use a "/24" address range and share the same
109
+ # "/16" range.
110
+ #
111
+ # @note This must be executed within a transaction.
112
+ # @api private
113
+ #
114
+ # @return [String] an IP range ending in "/24".
115
+ def next_pool_range
116
+ # Fetch the list of pools under management. Return nil if no pools exist.
117
+ pools = @pool_storage.fetch('pools', nil)
118
+
119
+ if pools.empty?
120
+ # If no pools have been created, use the default range.
121
+ AutoNetwork.default_pool
122
+ else
123
+ # Look up the highest "XX.XX.YY.XX/24" range in use.
124
+ last_pool_range = IPAddr.new(pools.values.map{|v| v.network_range}.sort.last)
125
+ # Increment "YY" by one to generate a new "/24" range.
126
+ ((last_pool_range >> 8).succ << 8).to_s + '/24'
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,64 @@
1
+ require 'yaml/store'
2
+ require 'auto_network/pool'
3
+
4
+ module AutoNetwork
5
+ # This is a specialized subclass of `YAML::Store` that knows how to
6
+ # initialize and upgrade AutoNetwork Pool files.
7
+ #
8
+ # @api private
9
+ class PoolStorage < YAML::Store
10
+ POOLFILE_VERSION = 2
11
+ POOLFILE_SKELETON = {
12
+ 'poolfile_version' => POOLFILE_VERSION,
13
+ 'pools' => {},
14
+ }
15
+
16
+ # Creates a new pool file at a target location and fills it with default
17
+ # data.
18
+ #
19
+ # @param path [String, Pathname] the location of the new pool file.
20
+ # @return [void]
21
+ def self.init(path)
22
+ File.write(path, POOLFILE_SKELETON.to_yaml)
23
+ end
24
+
25
+ private
26
+
27
+ # Override the method inherited from `YAML::Store`. All `PStore` object
28
+ # expect load to strictly return a `Hash`. This override allows us to
29
+ # perform on-the-fly upgrading of data loaded from old pool files and
30
+ # ensure the right structure is returned.
31
+ #
32
+ # @api private
33
+ #
34
+ # @param content [String] serialized YAML read from the pool file.
35
+ # @return [Hash]
36
+ def load(content)
37
+ data = super(content)
38
+
39
+ if data.is_a? AutoNetwork::Pool
40
+ upgrade_from_version_1! data
41
+ else
42
+ data
43
+ end
44
+ end
45
+
46
+ # The loosely defined "version 1" of the pool file just serialized a single
47
+ # {AutoNetwork::Pool} object. All AutoNetwork releases that used Version 1
48
+ # files only supported the Vagrant VirtualBox provider, so we return a new
49
+ # Hash-based data structure that includes the old Pool.
50
+ #
51
+ # @api private
52
+ #
53
+ # @param data [AutoNetwork::Pool] the old pool object.
54
+ # @return [Hash] a hash containing the old pool object.
55
+ def upgrade_from_version_1!(data)
56
+ {
57
+ 'poolfile_version' => POOLFILE_VERSION,
58
+ 'pools' => {
59
+ 'virtualbox' => data,
60
+ },
61
+ }
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module AutoNetwork
2
- VERSION = '0.2.2'
2
+ VERSION = '1.0.0.beta1'
3
3
  end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe AutoNetwork::Pool do
4
+ let(:ip_range) { '10.20.1.0/24' }
5
+ let(:machine_a) do
6
+ machine = double(
7
+ :name => 'machine_a',
8
+ :id => 'some-uuid',
9
+ )
10
+ machine.stub_chain(:env, :root_path, :to_s).and_return('/some/Vagrantfile')
11
+
12
+ machine
13
+ end
14
+ let(:machine_b) do
15
+ machine = double(
16
+ :name => 'machine_b',
17
+ :id => 'some-uuid',
18
+ )
19
+ machine.stub_chain(:env, :root_path, :to_s).and_return('/some/Vagrantfile')
20
+
21
+ machine
22
+ end
23
+
24
+ subject { AutoNetwork::Pool.new(ip_range) }
25
+
26
+ describe 'requesting an address for a machine' do
27
+
28
+ it 'returns the next available address' do
29
+ expect(subject.request(machine_a)).to eq('10.20.1.2')
30
+ end
31
+
32
+ it 'is idempotent' do
33
+ subject.request(machine_a)
34
+ expect(subject.request(machine_a)).to eq('10.20.1.2')
35
+ end
36
+
37
+ context 'when the pool is full' do
38
+ subject { AutoNetwork::Pool.new('10.20.1.0/30') }
39
+
40
+ it 'raises an error' do
41
+ subject.request(machine_a)
42
+ expect { subject.request(machine_b) }.to raise_error(AutoNetwork::Pool::PoolExhaustedError)
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ describe 'releasing an address from a machine' do
49
+
50
+ it 'makes the address available' do
51
+ subject.request(machine_a)
52
+ subject.release(machine_a)
53
+ expect(subject.request(machine_b)).to eq('10.20.1.2')
54
+ end
55
+
56
+ end
57
+
58
+ describe 'looking up an address for a machine' do
59
+
60
+ it 'returns the address assigned' do
61
+ subject.request(machine_a)
62
+ expect(subject.address_for(machine_a)).to eq('10.20.1.2')
63
+ end
64
+
65
+ it 'returns nil for unassigned machines' do
66
+ expect(subject.address_for(machine_b)).to be_nil
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ require 'rspec'
4
+ require 'auto_network'
@@ -17,4 +17,6 @@ Gem::Specification.new do |gem|
17
17
  gem.require_path = 'lib'
18
18
 
19
19
  gem.license = 'Apache 2.0'
20
+
21
+ gem.add_development_dependency 'rspec', '~> 2.14.0'
20
22
  end
metadata CHANGED
@@ -1,21 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-auto_network
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrien Thebo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-19 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2014-05-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 2.14.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 2.14.0
13
27
  description:
14
28
  email: adrien@somethingsinistral.net
15
29
  executables: []
16
30
  extensions: []
17
31
  extra_rdoc_files: []
18
32
  files:
33
+ - .yardopts
19
34
  - CHANGELOG
20
35
  - Gemfile
21
36
  - README.markdown
@@ -30,8 +45,12 @@ files:
30
45
  - lib/auto_network/mixin.rb
31
46
  - lib/auto_network/plugin.rb
32
47
  - lib/auto_network/pool.rb
48
+ - lib/auto_network/pool_manager.rb
49
+ - lib/auto_network/pool_storage.rb
33
50
  - lib/auto_network/version.rb
34
51
  - lib/vagrant-auto_network.rb
52
+ - spec/auto_network/pool/pool_spec.rb
53
+ - spec/spec_helper.rb
35
54
  - templates/locales/en.yml
36
55
  - vagrant-auto_network.gemspec
37
56
  homepage: https://github.com/adrienthebo/vagrant-auto_network
@@ -44,19 +63,18 @@ require_paths:
44
63
  - lib
45
64
  required_ruby_version: !ruby/object:Gem::Requirement
46
65
  requirements:
47
- - - ! '>='
66
+ - - '>='
48
67
  - !ruby/object:Gem::Version
49
68
  version: '0'
50
69
  required_rubygems_version: !ruby/object:Gem::Requirement
51
70
  requirements:
52
- - - ! '>='
71
+ - - '>'
53
72
  - !ruby/object:Gem::Version
54
- version: '0'
73
+ version: 1.3.1
55
74
  requirements: []
56
75
  rubyforge_project:
57
- rubygems_version: 2.2.1
76
+ rubygems_version: 2.0.14
58
77
  signing_key:
59
78
  specification_version: 4
60
79
  summary: Automatically create an internal network for all vagrant boxes
61
80
  test_files: []
62
- has_rdoc: