summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/network/http/handler.rb5
-rw-r--r--lib/puppet/network/http/mongrel.rb10
-rw-r--r--lib/puppet/network/http/mongrel/rest.rb13
-rw-r--r--lib/puppet/network/http/webrick.rb25
-rw-r--r--lib/puppet/network/http/webrick/rest.rb4
-rw-r--r--lib/puppet/network/server.rb6
-rw-r--r--spec/integration/network/server.rb85
-rw-r--r--spec/unit/network/http/mongrel.rb4
-rw-r--r--spec/unit/network/server.rb53
9 files changed, 175 insertions, 30 deletions
diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb
index 773381c8d..7679bf320 100644
--- a/lib/puppet/network/http/handler.rb
+++ b/lib/puppet/network/http/handler.rb
@@ -1,4 +1,5 @@
-class Puppet::Network::HTTP::Handler
+module Puppet::Network::HTTP::Handler
+
def initialize(args = {})
raise ArgumentError unless @server = args[:server]
raise ArgumentError unless @handler = args[:handler]
@@ -77,7 +78,7 @@ class Puppet::Network::HTTP::Handler
%r{/#{@handler.to_s}s$}.match(path(request))
end
- # methods specific to a given web server
+ # methods to be overridden by the including web server class
def register_handler
raise NotImplementedError
diff --git a/lib/puppet/network/http/mongrel.rb b/lib/puppet/network/http/mongrel.rb
index d948836cd..941ef0e43 100644
--- a/lib/puppet/network/http/mongrel.rb
+++ b/lib/puppet/network/http/mongrel.rb
@@ -13,20 +13,20 @@ class Puppet::Network::HTTP::Mongrel
raise ArgumentError, ":address must be specified." unless args[:address]
raise ArgumentError, ":port must be specified." unless args[:port]
raise "Mongrel server is already listening" if listening?
-
+
@protocols = args[:protocols]
@handlers = args[:handlers]
- @server = Mongrel::HttpServer.new(args[:address], args[:port])
-
+ @server = Mongrel::HttpServer.new(args[:address], args[:port])
setup_handlers
- @server.run
@listening = true
+ @server.run
end
def unlisten
raise "Mongrel server is not listening" unless listening?
- @server.graceful_shutdown
+ @server.stop
+ @server = nil
@listening = false
end
diff --git a/lib/puppet/network/http/mongrel/rest.rb b/lib/puppet/network/http/mongrel/rest.rb
index 6c24e360c..7cb6f67bf 100644
--- a/lib/puppet/network/http/mongrel/rest.rb
+++ b/lib/puppet/network/http/mongrel/rest.rb
@@ -1,36 +1,45 @@
require 'puppet/network/http/handler'
-class Puppet::Network::HTTP::MongrelREST < Puppet::Network::HTTP::Handler
+class Puppet::Network::HTTP::MongrelREST < Mongrel::HttpHandler
+
+ include Puppet::Network::HTTP::Handler
private
-
+
+ # have this mongrel @server listen for /foo and /foos REST endpoints
def register_handler
@server.register('/' + @handler.to_s, self)
@server.register('/' + @handler.to_s + 's', self)
end
+ # which HTTP verb was used in this request
def http_method(request)
request.params[Mongrel::Const::REQUEST_METHOD]
end
+ # what path was requested?
def path(request)
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = '/' + request.params[Mongrel::Const::REQUEST_PATH].split('/')[1]
end
+ # return the key included in the request path
def request_key(request)
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = request.params[Mongrel::Const::REQUEST_PATH].split('/')[2]
end
+ # return the request body
def body(request)
request.body
end
+ # return the query params for this request
def params(request)
Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"])
end
+ # produce the body of the response
def encode_result(request, response, result, status = 200)
response.start(status) do |head, body|
body.write(result)
diff --git a/lib/puppet/network/http/webrick.rb b/lib/puppet/network/http/webrick.rb
index 894e12473..3fd643612 100644
--- a/lib/puppet/network/http/webrick.rb
+++ b/lib/puppet/network/http/webrick.rb
@@ -1,10 +1,12 @@
require 'webrick'
require 'webrick/https'
require 'puppet/network/http/webrick/rest'
+require 'thread'
class Puppet::Network::HTTP::WEBrick
def initialize(args = {})
@listening = false
+ @mutex = Mutex.new
end
def listen(args = {})
@@ -12,24 +14,33 @@ class Puppet::Network::HTTP::WEBrick
raise ArgumentError, ":protocols must be specified." if !args[:protocols] or args[:protocols].empty?
raise ArgumentError, ":address must be specified." unless args[:address]
raise ArgumentError, ":port must be specified." unless args[:port]
- raise "WEBrick server is already listening" if listening?
@protocols = args[:protocols]
@handlers = args[:handlers]
@server = WEBrick::HTTPServer.new(:BindAddress => args[:address], :Port => args[:port])
setup_handlers
- @server.start
- @listening = true
+
+ @mutex.synchronize do
+ raise "WEBrick server is already listening" if @listening
+ @listening = true
+ @thread = Thread.new { @server.start }
+ end
end
def unlisten
- raise "WEBrick server is not listening" unless listening?
- @server.shutdown
- @listening = false
+ @mutex.synchronize do
+ raise "WEBrick server is not listening" unless @listening
+ @server.shutdown
+ @thread.join
+ @server = nil
+ @listening = false
+ end
end
def listening?
- @listening
+ @mutex.synchronize do
+ @listening
+ end
end
private
diff --git a/lib/puppet/network/http/webrick/rest.rb b/lib/puppet/network/http/webrick/rest.rb
index 8cda079e2..923e002e3 100644
--- a/lib/puppet/network/http/webrick/rest.rb
+++ b/lib/puppet/network/http/webrick/rest.rb
@@ -1,6 +1,8 @@
require 'puppet/network/http/handler'
-class Puppet::Network::HTTP::WEBrickREST < Puppet::Network::HTTP::Handler
+class Puppet::Network::HTTP::WEBrickREST
+
+ include Puppet::Network::HTTP::Handler
# WEBrick uses a service() method to respond to requests. Simply delegate to the handler response() method.
def service(request, response)
diff --git a/lib/puppet/network/server.rb b/lib/puppet/network/server.rb
index 9e6b82469..cab14519b 100644
--- a/lib/puppet/network/server.rb
+++ b/lib/puppet/network/server.rb
@@ -1,3 +1,5 @@
+require 'puppet/network/http'
+
class Puppet::Network::Server
attr_reader :server_type, :protocols, :address, :port
@@ -8,7 +10,7 @@ class Puppet::Network::Server
raise(ArgumentError, "Must specify :address or configure Puppet :bindaddress.")
@port = args[:port] || Puppet[:masterport] ||
raise(ArgumentError, "Must specify :port or configure Puppet :masterport")
- @protocols = []
+ @protocols = [ :rest ]
@listening = false
@routes = {}
self.register(args[:handlers]) if args[:handlers]
@@ -38,8 +40,8 @@ class Puppet::Network::Server
def listen
raise "Cannot listen -- already listening." if listening?
- http_server.listen(@routes.dup)
@listening = true
+ http_server.listen(:address => address, :port => port, :handlers => @routes.keys, :protocols => protocols)
end
def unlisten
diff --git a/spec/integration/network/server.rb b/spec/integration/network/server.rb
new file mode 100644
index 000000000..932161b08
--- /dev/null
+++ b/spec/integration/network/server.rb
@@ -0,0 +1,85 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/network/server'
+require 'socket'
+
+describe Puppet::Network::Server do
+ describe "when using webrick" do
+ before :each do
+ Puppet[:servertype] = 'webrick'
+ @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :node ] }
+ end
+
+ describe "before listening" do
+ it "should not be reachable at the specified address and port" do
+ lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error
+ end
+ end
+
+ describe "when listening" do
+ it "should be reachable on the specified address and port" do
+ @server = Puppet::Network::Server.new(@params.merge(:port => 34343))
+ @server.listen
+ lambda { TCPSocket.new('127.0.0.1', 34343) }.should_not raise_error
+ end
+
+ it "should not allow multiple servers to listen on the same address and port" do
+ @server = Puppet::Network::Server.new(@params.merge(:port => 34343))
+ @server.listen
+ @server2 = Puppet::Network::Server.new(@params.merge(:port => 34343))
+ lambda { @server2.listen }.should raise_error
+ end
+
+ after :each do
+ @server.unlisten if @server.listening?
+ end
+ end
+
+ describe "after unlistening" do
+ it "should not be reachable on the port and address assigned" do
+ @server = Puppet::Network::Server.new(@params.merge(:port => 34343))
+ @server.listen
+ @server.unlisten
+ lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error(Errno::ECONNREFUSED)
+ end
+ end
+ end
+
+ describe "when using mongrel" do
+ before :each do
+ Puppet[:servertype] = 'mongrel'
+ @params = { :address => "127.0.0.1", :port => 34346, :handlers => [ :node ] }
+ @server = Puppet::Network::Server.new(@params)
+ end
+
+ describe "before listening" do
+ it "should not be reachable at the specified address and port" do
+ lambda { TCPSocket.new('127.0.0.1', 34346) }.should raise_error(Errno::ECONNREFUSED)
+ end
+ end
+
+ describe "when listening" do
+ it "should be reachable on the specified address and port" do
+ @server.listen
+ lambda { TCPSocket.new('127.0.0.1', 34346) }.should_not raise_error
+ end
+
+ it "should not allow multiple servers to listen on the same address and port" do
+ @server.listen
+ @server2 = Puppet::Network::Server.new(@params)
+ lambda { @server2.listen }.should raise_error
+ end
+ end
+
+ describe "after unlistening" do
+ it "should not be reachable on the port and address assigned" do
+ @server.listen
+ @server.unlisten
+ lambda { TCPSocket.new('127.0.0.1', 34346) }.should raise_error(Errno::ECONNREFUSED)
+ end
+ end
+
+ after :each do
+ @server.unlisten if @server.listening?
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/unit/network/http/mongrel.rb b/spec/unit/network/http/mongrel.rb
index a837c9daa..cd23ed9e1 100644
--- a/spec/unit/network/http/mongrel.rb
+++ b/spec/unit/network/http/mongrel.rb
@@ -106,13 +106,13 @@ describe Puppet::Network::HTTP::Mongrel, "when turning off listening" do
it "should order mongrel server to stop" do
@server.listen(@listen_params)
- @mock_mongrel.expects(:graceful_shutdown)
+ @mock_mongrel.expects(:stop)
@server.unlisten
end
it "should not be listening" do
@server.listen(@listen_params)
- @mock_mongrel.stubs(:graceful_shutdown)
+ @mock_mongrel.stubs(:stop)
@server.unlisten
@server.should_not be_listening
end
diff --git a/spec/unit/network/server.rb b/spec/unit/network/server.rb
index 3e29807ad..e4afbc3c2 100644
--- a/spec/unit/network/server.rb
+++ b/spec/unit/network/server.rb
@@ -161,8 +161,12 @@ describe Puppet::Network::Server, "in general" do
Proc.new { @server2.unregister(:bar) }.should raise_error(ArgumentError)
end
- it "should provide a means of determining which style of service is being offered to clients" do
- @server.protocols.should == []
+ it "should provide a means of determining which protocols are in use" do
+ @server.should respond_to(:protocols)
+ end
+
+ it "should only support the REST protocol at this time" do
+ @server.protocols.should == [ :rest ]
end
it "should provide a means of determining the listening address" do
@@ -230,23 +234,54 @@ describe Puppet::Network::Server, "when listening is being turned on" do
@mock_http_server_class = mock('http server class')
Puppet::Network::HTTP.stubs(:server_class_by_type).returns(@mock_http_server_class)
Puppet.stubs(:[]).with(:servertype).returns(:suparserver)
- @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+ @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337, :handlers => [:node])
@mock_http_server = mock('http server')
@mock_http_server.stubs(:listen)
end
- it "should fetch an instance of an HTTP server when listening is turned on" do
- mock_http_server_class = mock('http server class')
- mock_http_server_class.expects(:new).returns(@mock_http_server)
- @server.expects(:http_server_class).returns(mock_http_server_class)
+ it "should fetch an instance of an HTTP server" do
+ @server.stubs(:http_server_class).returns(@mock_http_server_class)
+ @mock_http_server_class.expects(:new).returns(@mock_http_server)
@server.listen
end
- it "should cause the HTTP server to listen when listening is turned on" do
+ it "should cause the HTTP server to listen" do
+ @server.stubs(:http_server).returns(@mock_http_server)
@mock_http_server.expects(:listen)
- @server.expects(:http_server).returns(@mock_http_server)
@server.listen
end
+
+ it "should pass the listening address to the HTTP server" do
+ @server.stubs(:http_server).returns(@mock_http_server)
+ @mock_http_server.expects(:listen).with do |args|
+ args[:address] == '127.0.0.1'
+ end
+ @server.listen
+ end
+
+ it "should pass the listening port to the HTTP server" do
+ @server.stubs(:http_server).returns(@mock_http_server)
+ @mock_http_server.expects(:listen).with do |args|
+ args[:port] == 31337
+ end
+ @server.listen
+ end
+
+ it "should pass a list of handlers to the HTTP server" do
+ @server.stubs(:http_server).returns(@mock_http_server)
+ @mock_http_server.expects(:listen).with do |args|
+ args[:handlers] == [ :node ]
+ end
+ @server.listen
+ end
+
+ it "should pass a list of protocols to the HTTP server" do
+ @server.stubs(:http_server).returns(@mock_http_server)
+ @mock_http_server.expects(:listen).with do |args|
+ args[:protocols] == [ :rest ]
+ end
+ @server.listen
+ end
end
describe Puppet::Network::Server, "when listening is being turned off" do