diff options
author | John Keiser <john@johnkeiser.com> | 2014-06-12 12:37:20 -0700 |
---|---|---|
committer | John Keiser <john@johnkeiser.com> | 2014-06-12 12:37:20 -0700 |
commit | e675050eb2f3dffe2fa646fdbbb8e2f80e93a974 (patch) | |
tree | b7f12bbea878b127403fa28734394fcbaa0985b7 | |
parent | 9a15065435c16113c018fc0d6cea521bbf981df2 (diff) | |
parent | d60221a7e5539874516bbfe75a5701d7e3b90971 (diff) | |
download | chef-zero-e675050eb2f3dffe2fa646fdbbb8e2f80e93a974.tar.gz |
Merge pull request #67 from opscode/ports
Allow server to try multiple ports
-rw-r--r-- | .travis.yml | 4 | ||||
-rw-r--r-- | Rakefile | 6 | ||||
-rwxr-xr-x | bin/chef-zero | 18 | ||||
-rw-r--r-- | lib/chef_zero/server.rb | 50 | ||||
-rw-r--r-- | spec/server_spec.rb | 28 |
5 files changed, 97 insertions, 9 deletions
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 @@ -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/bin/chef-zero b/bin/chef-zero index 6d6884f..c2b3120 100755 --- a/bin/chef-zero +++ b/bin/chef-zero @@ -10,6 +10,19 @@ require 'chef_zero/version' require 'chef_zero/server' require 'optparse' +def parse_port(port) + array = [] + port.split(',').each do |part| + a,b = part.split('-',2) + if b + array = array.concat(a.to_i.upto(b.to_i).to_a) + else + array = array.concat([a.to_i]) + end + end + array +end + options = {} OptionParser.new do |opts| @@ -19,8 +32,9 @@ OptionParser.new do |opts| options[:host] = value end - opts.on("-p", "--port PORT", Integer, "Port to listen on") do |value| - options[:port] = value + opts.on("-p", "--port PORT", "Port to listen on (e.g. 8889, or 8500-8600 or 8885,8888)") do |value| + options[:port] ||= [] + options[:port] += parse_port(value) end opts.on("--[no-]generate-keys", "Whether to generate actual keys or fake it (faster). Default: false.") do |value| 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 |