Pull out port collision detection/correction into the CheckPortCollision middleware
This commit is contained in:
parent
4e547becab
commit
d80ff0a27f
|
@ -38,10 +38,12 @@ module Vagrant
|
||||||
#
|
#
|
||||||
# @param [Class] middleware The middleware class
|
# @param [Class] middleware The middleware class
|
||||||
def use(middleware, *args, &block)
|
def use(middleware, *args, &block)
|
||||||
if middleware.kind_of?(Builder)
|
|
||||||
# Prepend with a environment setter if args are given
|
# Prepend with a environment setter if args are given
|
||||||
self.use(Env::Set, *args, &block) if !args.empty? && args.first.is_a?(Hash)
|
if !args.empty? && args.first.is_a?(Hash) && middleware != Env::Set
|
||||||
|
self.use(Env::Set, args.shift, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
if middleware.kind_of?(Builder)
|
||||||
# Merge in the other builder's stack into our own
|
# Merge in the other builder's stack into our own
|
||||||
self.stack.concat(middleware.stack)
|
self.stack.concat(middleware.stack)
|
||||||
else
|
else
|
||||||
|
|
|
@ -20,6 +20,7 @@ module Vagrant
|
||||||
Builder.new do
|
Builder.new do
|
||||||
use General::Validate
|
use General::Validate
|
||||||
use VM::CheckAccessible
|
use VM::CheckAccessible
|
||||||
|
use VM::CheckPortCollisions, :port_collision_handler => :correct
|
||||||
use VM::CleanMachineFolder
|
use VM::CleanMachineFolder
|
||||||
use VM::ClearForwardedPorts
|
use VM::ClearForwardedPorts
|
||||||
use VM::ForwardPorts
|
use VM::ForwardPorts
|
||||||
|
|
|
@ -4,12 +4,15 @@ module Vagrant
|
||||||
# A middleware which just sets up the environment with some
|
# A middleware which just sets up the environment with some
|
||||||
# options which are passed to it.
|
# options which are passed to it.
|
||||||
class Set
|
class Set
|
||||||
def initialize(app,env,options=nil)
|
def initialize(app, env, options=nil)
|
||||||
@app = app
|
@app = app
|
||||||
env.merge!(options || {})
|
@options = options || {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
|
# Merge the options that were given to us
|
||||||
|
env.merge!(@options)
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,17 +9,62 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
existing = env[:vm].driver.read_used_ports
|
# For the handlers...
|
||||||
|
@env = env
|
||||||
|
|
||||||
|
# Figure out how we handle port collisions. By default we error.
|
||||||
|
handler = env[:port_collision_handler] || :error
|
||||||
|
|
||||||
|
existing = env[:vm].driver.read_used_ports
|
||||||
env[:vm].config.vm.forwarded_ports.each do |name, options|
|
env[:vm].config.vm.forwarded_ports.each do |name, options|
|
||||||
if existing.include?(options[:hostport].to_i)
|
if existing.include?(options[:hostport].to_i)
|
||||||
# We have a collision!
|
# We have a collision! Handle it
|
||||||
raise Errors::ForwardPortCollisionResume
|
send("handle_#{handler}".to_sym, name, options, existing)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Handles a port collision by raising an exception.
|
||||||
|
def handle_error(name, options, existing_ports)
|
||||||
|
raise Errors::ForwardPortCollisionResume
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handles a port collision by attempting to fix it.
|
||||||
|
def handle_correct(name, options, existing_ports)
|
||||||
|
if !options[:auto]
|
||||||
|
# Auto fixing is disabled for this port forward, so we
|
||||||
|
# must throw an error so the user can fix it.
|
||||||
|
raise Errors::ForwardPortCollision, :name => name,
|
||||||
|
:host_port => options[:hostport].to_s,
|
||||||
|
:guest_port => options[:guestport].to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get the auto port range and get rid of the used ports and
|
||||||
|
# ports which are being used in other forwards so we're just
|
||||||
|
# left with available ports.
|
||||||
|
range = @env[:vm].config.vm.auto_port_range.to_a
|
||||||
|
range -= @env[:vm].config.vm.forwarded_ports.collect { |n, o| o[:hostport].to_i }
|
||||||
|
range -= existing_ports
|
||||||
|
|
||||||
|
if range.empty?
|
||||||
|
raise Errors::ForwardPortAutolistEmpty, :vm_name => @env[:vm].name,
|
||||||
|
:name => name,
|
||||||
|
:host_port => options[:hostport].to_s,
|
||||||
|
:guest_port => options[:guestport].to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# Set the port up to be the first one and add that port to
|
||||||
|
# the used list.
|
||||||
|
options[:hostport] = range.shift
|
||||||
|
existing_ports << options[:hostport]
|
||||||
|
|
||||||
|
# Notify the user
|
||||||
|
@env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.fixed_collision",
|
||||||
|
:name => name,
|
||||||
|
:new_port => options[:hostport]))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,6 @@ module Vagrant
|
||||||
@env = env
|
@env = env
|
||||||
|
|
||||||
threshold_check
|
threshold_check
|
||||||
external_collision_check
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
@ -26,56 +25,6 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method checks for any port collisions with any VMs
|
|
||||||
# which are already created (by Vagrant or otherwise).
|
|
||||||
# report the collisions detected or will attempt to fix them
|
|
||||||
# automatically if the port is configured to do so.
|
|
||||||
def external_collision_check
|
|
||||||
existing = @env[:vm].driver.read_used_ports
|
|
||||||
@env[:vm].config.vm.forwarded_ports.each do |name, options|
|
|
||||||
if existing.include?(options[:hostport].to_i)
|
|
||||||
handle_collision(name, options, existing)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Handles any collisions. This method will either attempt to
|
|
||||||
# fix the collision automatically or will raise an error if
|
|
||||||
# auto fixing is disabled.
|
|
||||||
def handle_collision(name, options, existing_ports)
|
|
||||||
if !options[:auto]
|
|
||||||
# Auto fixing is disabled for this port forward, so we
|
|
||||||
# must throw an error so the user can fix it.
|
|
||||||
raise Errors::ForwardPortCollision, :name => name,
|
|
||||||
:host_port => options[:hostport].to_s,
|
|
||||||
:guest_port => options[:guestport].to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the auto port range and get rid of the used ports and
|
|
||||||
# ports which are being used in other forwards so we're just
|
|
||||||
# left with available ports.
|
|
||||||
range = @env[:vm].config.vm.auto_port_range.to_a
|
|
||||||
range -= @env[:vm].config.vm.forwarded_ports.collect { |n, o| o[:hostport].to_i }
|
|
||||||
range -= existing_ports
|
|
||||||
|
|
||||||
if range.empty?
|
|
||||||
raise Errors::ForwardPortAutolistEmpty, :vm_name => @env[:vm].name,
|
|
||||||
:name => name,
|
|
||||||
:host_port => options[:hostport].to_s,
|
|
||||||
:guest_port => options[:guestport].to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
# Set the port up to be the first one and add that port to
|
|
||||||
# the used list.
|
|
||||||
options[:hostport] = range.shift
|
|
||||||
existing_ports << options[:hostport]
|
|
||||||
|
|
||||||
# Notify the user
|
|
||||||
@env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.fixed_collision",
|
|
||||||
:name => name,
|
|
||||||
:new_port => options[:hostport]))
|
|
||||||
end
|
|
||||||
|
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
# Execution
|
# Execution
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
|
|
@ -51,21 +51,16 @@ describe Vagrant::Action::Builder do
|
||||||
data[:one].should == true
|
data[:one].should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be able to set additional variables if using another builder" do
|
it "should be able to set additional variables when using" do
|
||||||
data = { }
|
data = { }
|
||||||
proc1 = Proc.new { |env| env[:data] += 1 }
|
proc1 = Proc.new { |env| env[:data] += 1 }
|
||||||
|
|
||||||
# Build the first builder
|
# Build the first builder
|
||||||
one = described_class.new
|
one = described_class.new
|
||||||
one.use proc1
|
one.use proc1, :data => 5
|
||||||
|
one.call(data)
|
||||||
|
|
||||||
# Add it to this builder
|
data[:data].should == 6
|
||||||
two = described_class.new
|
|
||||||
two.use one, :data => 10
|
|
||||||
|
|
||||||
# Call the 2nd and verify results
|
|
||||||
two.call(data)
|
|
||||||
data[:data].should == 11
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue