From 25fe70279ea8eb89b360131e95ce65f6a8696992 Mon Sep 17 00:00:00 2001 From: John Keiser Date: Tue, 10 Jun 2014 20:43:16 -0700 Subject: Support port range in :port --- .travis.yml | 4 +++- Rakefile | 6 ++++++ lib/chef_zero/server.rb | 50 +++++++++++++++++++++++++++++++++++++++++++------ spec/server_spec.rb | 28 +++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 spec/server_spec.rb diff --git a/.travis.yml b/.travis.yml index 0837536..f3fedc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ rvm: 1.9.3 gemfile: Gemfile -script: bundle exec rake spec +script: bundle exec rake pedant matrix: include: @@ -24,6 +24,8 @@ matrix: env: CHEF_FS=true - rvm: 2.1.1 script: bundle exec rake chef_spec + - rvm: 2.1.1 + script: bundle exec rake spec allow_failures: - rvm: 1.8.7 diff --git a/Rakefile b/Rakefile index 099a270..4599e68 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,13 @@ require 'bundler/gem_tasks' require 'chef_zero/version' +task :default => :pedant + task :spec do + system('rspec spec/*_spec.rb') +end + +task :pedant do require File.expand_path('spec/run') end diff --git a/lib/chef_zero/server.rb b/lib/chef_zero/server.rb index 4955282..dbbe473 100644 --- a/lib/chef_zero/server.rb +++ b/lib/chef_zero/server.rb @@ -80,6 +80,17 @@ module ChefZero # @return [Hash] attr_reader :options + # @return [Integer] + def port + if @port + @port + elsif !options[:port].respond_to?(:each) + options[:port] + else + raise "port cannot be determined until server is started" + end + end + # @return [WEBrick::HTTPServer] attr_reader :server @@ -95,9 +106,9 @@ module ChefZero # def url @url ||= if @options[:host].include?(':') - URI("http://[#{@options[:host]}]:#{@options[:port]}").to_s + URI("http://[#{@options[:host]}]:#{port}").to_s else - URI("http://#{@options[:host]}:#{@options[:port]}").to_s + URI("http://#{@options[:host]}:#{port}").to_s end end @@ -153,14 +164,20 @@ module ChefZero output = publish.respond_to?(:puts) ? publish : STDOUT output.puts <<-EOH.gsub(/^ {10}/, '') >> Starting Chef Zero (v#{ChefZero::VERSION})... + EOH + end + + thread = start_background + + if publish + output = publish.respond_to?(:puts) ? publish : STDOUT + output.puts <<-EOH.gsub(/^ {10}/, '') >> WEBrick (v#{WEBrick::VERSION}) on Rack (v#{Rack.release}) is listening at #{url} >> Press CTRL+C to stop EOH end - thread = start_background - %w[INT TERM].each do |signal| Signal.trap(signal) do puts "\n>> Stopping Chef Zero..." @@ -185,8 +202,7 @@ module ChefZero # def start_background(wait = 5) @server = WEBrick::HTTPServer.new( - :BindAddress => @options[:host], - :Port => @options[:port], + :DoNotListen => true, :AccessLog => [], :Logger => WEBrick::Log.new(StringIO.new, 7), :StartCallback => proc { @@ -195,18 +211,40 @@ module ChefZero ) @server.mount('/', Rack::Handler::WEBrick, app) + # Pick a port + if options[:port].respond_to?(:each) + options[:port].each do |port| + begin + @server.listen(options[:host], port) + @port = port + break + rescue Errno::EADDRINUSE + end + end + if !@port + raise Errno::EADDRINUSE, "No port in :port range is available" + end + else + @server.listen(options[:host], options[:port]) + @port = options[:port] + end + + # Start the server in the background @thread = Thread.new do begin Thread.current.abort_on_exception = true @server.start ensure + @port = nil @running = false end end + # Do not return until the web server is genuinely started. while !@running && @thread.alive? sleep(0.01) end + @thread end diff --git a/spec/server_spec.rb b/spec/server_spec.rb new file mode 100644 index 0000000..575c2e2 --- /dev/null +++ b/spec/server_spec.rb @@ -0,0 +1,28 @@ +require 'chef_zero/server' + +describe ChefZero::Server do + context 'with a server bound to port 8889' do + before :each do + @server = ChefZero::Server.new(:port => 8889) + @server.start_background + end + after :each do + @server.stop + end + + it 'a second server bound to port 8889 throws EADDRINUSE' do + expect { ChefZero::Server.new(:port => 8889).start }.to raise_error Errno::EADDRINUSE + end + + it 'a server bound to range 8889-9999 binds to a port > 8889' do + server = ChefZero::Server.new(:port => 8889.upto(9999)) + server.start_background + expect(server.port).to be > 8889 + expect(URI(server.url).port).to be > 8889 + end + + it 'a server bound to range 8889-8889 throws an exception' do + expect { ChefZero::Server.new(:port => 8889.upto(8889)).start_background }.to raise_error Errno::EADDRINUSE + end + end +end -- cgit v1.2.1