diff options
author | Luke Kanies <luke@madstop.com> | 2008-04-11 15:21:50 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2008-04-11 15:21:50 -0500 |
commit | d834242db13a827a34340c5f2e51c8df532d5196 (patch) | |
tree | cdd98ee63103082a81dac7e91e13b60458685780 /lib/puppet | |
parent | fb05ef3c96038d67a46eb142202af186ad6cb0b3 (diff) | |
parent | d9846fc3f06f61fcb4b8806740f77747a7f6939e (diff) | |
download | puppet-d834242db13a827a34340c5f2e51c8df532d5196.tar.gz puppet-d834242db13a827a34340c5f2e51c8df532d5196.tar.xz puppet-d834242db13a827a34340c5f2e51c8df532d5196.zip |
Merge branch '0.24.x'
Conflicts:
spec/unit/network/server.rb
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/indirector/indirection.rb | 5 | ||||
-rw-r--r-- | lib/puppet/indirector/node/rest.rb | 2 | ||||
-rw-r--r-- | lib/puppet/indirector/rest.rb | 54 | ||||
-rw-r--r-- | lib/puppet/network/http/handler.rb | 32 | ||||
-rw-r--r-- | lib/puppet/network/http/mongrel.rb | 17 | ||||
-rw-r--r-- | lib/puppet/network/http/mongrel/rest.rb | 22 | ||||
-rw-r--r-- | lib/puppet/network/http/mongrel/xmlrpc.rb | 4 | ||||
-rw-r--r-- | lib/puppet/network/http/webrick.rb | 43 | ||||
-rw-r--r-- | lib/puppet/network/http/webrick/rest.rb | 17 | ||||
-rw-r--r-- | lib/puppet/network/http/webrick/xmlrpc.rb | 4 | ||||
-rw-r--r-- | lib/puppet/network/server.rb | 44 |
11 files changed, 156 insertions, 88 deletions
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb index 15358a801..05464f8c9 100644 --- a/lib/puppet/indirector/indirection.rb +++ b/lib/puppet/indirector/indirection.rb @@ -225,14 +225,14 @@ class Puppet::Indirector::Indirection request = request(:destroy, key, *args) terminus = prepare(request) - terminus.destroy(request) + result = terminus.destroy(request) if cache? and cached = cache.find(request(:find, key, *args)) # Reuse the existing request, since it's equivalent. cache.destroy(request) end - nil + result end # Search for more than one instance. Should always return an array. @@ -242,7 +242,6 @@ class Puppet::Indirector::Indirection if result = terminus.search(request) raise Puppet::DevError, "Search results from terminus %s are not an array" % terminus.name unless result.is_a?(Array) - result.each do |instance| instance.expiration ||= self.expiration end diff --git a/lib/puppet/indirector/node/rest.rb b/lib/puppet/indirector/node/rest.rb index c5d2f97fb..d8b75f6e7 100644 --- a/lib/puppet/indirector/node/rest.rb +++ b/lib/puppet/indirector/node/rest.rb @@ -1,7 +1,7 @@ require 'puppet/node' require 'puppet/indirector/rest' -class Puppet::Node::REST < Puppet::Indirector::REST +class Puppet::Node::Rest < Puppet::Indirector::REST desc "This will eventually be a REST-based mechanism for finding nodes. It is currently non-functional." # TODO/FIXME end diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb index 7b7c932c4..d33150fc2 100644 --- a/lib/puppet/indirector/rest.rb +++ b/lib/puppet/indirector/rest.rb @@ -1,8 +1,56 @@ -require 'puppet/indirector/rest' +require 'net/http' +require 'uri' # Access objects via REST class Puppet::Indirector::REST < Puppet::Indirector::Terminus - def find(name, options = {}) - indirection.model.new(name) + + def rest_connection_details + { :host => Puppet[:server], :port => Puppet[:masterport].to_i } + end + + def network_fetch(path) + network {|conn| conn.get("/#{path}").body } + end + + def network_delete(path) + network {|conn| conn.delete("/#{path}").body } + end + + def network_put(path, data) + network {|conn| conn.put("/#{path}", data).body } + end + + def find(request) + network_result = network_fetch("#{indirection.name}/#{request.key}") + raise YAML.load(network_result) if exception?(network_result) + indirection.model.from_yaml(network_result) + end + + def search(request) + network_results = network_fetch("#{indirection.name}s/#{request.key}") + raise YAML.load(network_results) if exception?(network_results) + YAML.load(network_results.to_s).collect {|result| indirection.model.from_yaml(result) } + end + + def destroy(request) + network_result = network_delete("#{indirection.name}/#{request.key}") + raise YAML.load(network_result) if exception?(network_result) + YAML.load(network_result.to_s) + end + + def save(request) + network_result = network_put("#{indirection.name}/", request.instance.to_yaml) + raise YAML.load(network_result) if exception?(network_result) + indirection.model.from_yaml(network_result) + end + + private + + def network(&block) + Net::HTTP.start(rest_connection_details[:host], rest_connection_details[:port]) {|conn| yield(conn) } + end + + def exception?(yaml_string) + yaml_string =~ %r{--- !ruby/exception} end end diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb index 773381c8d..7113c92d3 100644 --- a/lib/puppet/network/http/handler.rb +++ b/lib/puppet/network/http/handler.rb @@ -1,9 +1,9 @@ -class Puppet::Network::HTTP::Handler - def initialize(args = {}) +module Puppet::Network::HTTP::Handler + + def initialize_for_puppet(args = {}) raise ArgumentError unless @server = args[:server] raise ArgumentError unless @handler = args[:handler] @model = find_model_for_handler(@handler) - register_handler end # handle an HTTP request @@ -18,38 +18,46 @@ class Puppet::Network::HTTP::Handler end private + + def model + @model + end def do_find(request, response) key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]") args = params(request) - result = @model.find(key, args).to_yaml + result = model.find(key, args).to_yaml encode_result(request, response, result) end def do_search(request, response) args = params(request) - result = @model.search(args).collect {|obj| obj.to_yaml } + result = model.search(args).collect {|result| result.to_yaml }.to_yaml encode_result(request, response, result) end def do_destroy(request, response) key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]") args = params(request) - result = @model.destroy(key, args) + result = model.destroy(key, args) encode_result(request, response, YAML.dump(result)) end def do_save(request, response) - data = body(request) + data = body(request).to_s raise ArgumentError, "No data to save" if !data or data.empty? - args = params(request) - obj = @model.new - result = obj.save(args.merge(:data => data)).to_yaml + # args = params(request) + obj = model.from_yaml(data) + result = save_object(obj).to_yaml encode_result(request, response, result) end + + def save_object(obj) + obj.save + end def do_exception(request, response, exception, status=404) - encode_result(request, response, exception.to_s, status) + encode_result(request, response, exception.to_yaml, status) end def find_model_for_handler(handler) @@ -77,7 +85,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 8ea669531..9a4531c7a 100644 --- a/lib/puppet/network/http/mongrel.rb +++ b/lib/puppet/network/http/mongrel.rb @@ -1,7 +1,6 @@ require 'mongrel' if Puppet.features.mongrel? require 'puppet/network/http/mongrel/rest' -require 'puppet/network/http/mongrel/xmlrpc' class Puppet::Network::HTTP::Mongrel def initialize(args = {}) @@ -14,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 @@ -39,16 +38,16 @@ class Puppet::Network::HTTP::Mongrel def setup_handlers @protocols.each do |protocol| + klass = class_for_protocol(protocol) @handlers.each do |handler| - class_for_protocol(protocol).new(:server => @server, :handler => handler) + @server.register('/' + handler.to_s, klass.new(:server => @server, :handler => handler)) + @server.register('/' + handler.to_s + 's', klass.new(:server => @server, :handler => handler)) end end end - # TODO/FIXME: need a spec which forces delegation to the real class def class_for_protocol(protocol) return Puppet::Network::HTTP::MongrelREST if protocol.to_sym == :rest - return Puppet::Network::HTTP::MongrelXMLRPC if protocol.to_sym == :xmlrpc raise ArgumentError, "Unknown protocol [#{protocol}]." end end diff --git a/lib/puppet/network/http/mongrel/rest.rb b/lib/puppet/network/http/mongrel/rest.rb index 6c24e360c..2a3d4f143 100644 --- a/lib/puppet/network/http/mongrel/rest.rb +++ b/lib/puppet/network/http/mongrel/rest.rb @@ -1,36 +1,44 @@ 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 + + def initialize(args={}) + super() + initialize_for_puppet(args) + end private - - 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/mongrel/xmlrpc.rb b/lib/puppet/network/http/mongrel/xmlrpc.rb deleted file mode 100644 index 92acd4f0e..000000000 --- a/lib/puppet/network/http/mongrel/xmlrpc.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Puppet::Network::HTTP::MongrelXMLRPC - def initialize(args = {}) - end -end diff --git a/lib/puppet/network/http/webrick.rb b/lib/puppet/network/http/webrick.rb index c4b2ed3c6..3a37e2071 100644 --- a/lib/puppet/network/http/webrick.rb +++ b/lib/puppet/network/http/webrick.rb @@ -1,11 +1,17 @@ require 'webrick' require 'webrick/https' require 'puppet/network/http/webrick/rest' -require 'puppet/network/http/webrick/xmlrpc' +require 'thread' class Puppet::Network::HTTP::WEBrick def initialize(args = {}) @listening = false + @mutex = Mutex.new + end + + def self.class_for_protocol(protocol) + return Puppet::Network::HTTP::WEBrickREST if protocol.to_sym == :rest + raise "Unknown protocol [#{protocol}]." end def listen(args = {}) @@ -13,39 +19,44 @@ 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 def setup_handlers @protocols.each do |protocol| + klass = self.class.class_for_protocol(protocol) @handlers.each do |handler| - class_for_protocol(protocol).new(:server => @server, :handler => handler) + @server.mount('/' + handler.to_s, klass, handler) + @server.mount('/' + handler.to_s + 's', klass, handler) end end end - - def class_for_protocol(protocol) - return Puppet::Network::HTTP::WEBrickREST if protocol.to_sym == :rest - return Puppet::Network::HTTP::WEBrickXMLRPC if protocol.to_sym == :xmlrpc - raise ArgumentError, "Unknown protocol [#{protocol}]." - end end diff --git a/lib/puppet/network/http/webrick/rest.rb b/lib/puppet/network/http/webrick/rest.rb index 8cda079e2..b43912196 100644 --- a/lib/puppet/network/http/webrick/rest.rb +++ b/lib/puppet/network/http/webrick/rest.rb @@ -1,19 +1,22 @@ require 'puppet/network/http/handler' -class Puppet::Network::HTTP::WEBrickREST < Puppet::Network::HTTP::Handler +class Puppet::Network::HTTP::WEBrickREST < WEBrick::HTTPServlet::AbstractServlet + + include Puppet::Network::HTTP::Handler + + def initialize(server, handler) + raise ArgumentError, "server is required" unless server + super(server) + initialize_for_puppet(:server => server, :handler => handler) + end # WEBrick uses a service() method to respond to requests. Simply delegate to the handler response() method. def service(request, response) process(request, response) end - + private - def register_handler - @server.mount('/' + @handler.to_s, self) - @server.mount('/' + @handler.to_s + 's', self) - end - def http_method(request) request.request_method end diff --git a/lib/puppet/network/http/webrick/xmlrpc.rb b/lib/puppet/network/http/webrick/xmlrpc.rb deleted file mode 100644 index 793708f8a..000000000 --- a/lib/puppet/network/http/webrick/xmlrpc.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Puppet::Network::HTTP::WEBrickXMLRPC - def initialize(args = {}) - end -end diff --git a/lib/puppet/network/server.rb b/lib/puppet/network/server.rb index f2c8dc18c..cab14519b 100644 --- a/lib/puppet/network/server.rb +++ b/lib/puppet/network/server.rb @@ -10,44 +10,44 @@ 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 = [] - @listening = false - @routes = {} - self.register(args[:handlers]) if args[:handlers] + @protocols = [ :rest ] + @listening = false + @routes = {} + self.register(args[:handlers]) if args[:handlers] end def register(*indirections) - raise ArgumentError, "Indirection names are required." if indirections.empty? - indirections.flatten.each { |i| @routes[i.to_sym] = true } + raise ArgumentError, "Indirection names are required." if indirections.empty? + indirections.flatten.each { |i| @routes[i.to_sym] = true } end def unregister(*indirections) - raise "Cannot unregister indirections while server is listening." if listening? - indirections = @routes.keys if indirections.empty? - - indirections.flatten.each do |i| - raise(ArgumentError, "Indirection [%s] is unknown." % i) unless @routes[i.to_sym] - end + raise "Cannot unregister indirections while server is listening." if listening? + indirections = @routes.keys if indirections.empty? + + indirections.flatten.each do |i| + raise(ArgumentError, "Indirection [%s] is unknown." % i) unless @routes[i.to_sym] + end - indirections.flatten.each do |i| - @routes.delete(i.to_sym) - end + indirections.flatten.each do |i| + @routes.delete(i.to_sym) + end end def listening? - @listening + @listening end def listen - raise "Cannot listen -- already listening." if listening? - http_server.listen(@routes.dup) - @listening = true + raise "Cannot listen -- already listening." if listening? + @listening = true + http_server.listen(:address => address, :port => port, :handlers => @routes.keys, :protocols => protocols) end def unlisten - raise "Cannot unlisten -- not currently listening." unless listening? - http_server.unlisten - @listening = false + raise "Cannot unlisten -- not currently listening." unless listening? + http_server.unlisten + @listening = false end def http_server_class |