summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/indirector/request.rb36
-rw-r--r--lib/puppet/indirector/rest.rb40
-rwxr-xr-xspec/unit/indirector/request.rb31
-rwxr-xr-xspec/unit/indirector/rest.rb80
4 files changed, 141 insertions, 46 deletions
diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb
index 98fa38885..f1d02cead 100644
--- a/lib/puppet/indirector/request.rb
+++ b/lib/puppet/indirector/request.rb
@@ -5,6 +5,8 @@ require 'puppet/indirector'
class Puppet::Indirector::Request
attr_accessor :indirection_name, :key, :method, :options, :instance, :node, :ip, :authenticated
+ attr_accessor :server, :port, :uri, :protocol
+
# Is this an authenticated request?
def authenticated?
# Double negative, so we just get true or false
@@ -28,7 +30,15 @@ class Puppet::Indirector::Request
end
if key.is_a?(String) or key.is_a?(Symbol)
- @key = key
+ # If the request key is a URI, then we need to treat it specially,
+ # because it rewrites the key. We could otherwise strip server/port/etc
+ # info out in the REST class, but it seemed bad design for the REST
+ # class to rewrite the key.
+ if key.to_s =~ /^\w+:\/\// # it's a URI
+ set_uri_key(key)
+ else
+ @key = key
+ end
else
@instance = key
@key = @instance.name
@@ -39,4 +49,28 @@ class Puppet::Indirector::Request
def indirection
Puppet::Indirector::Indirection.instance(@indirection_name)
end
+
+ private
+
+ # Parse the key as a URI, setting attributes appropriately.
+ def set_uri_key(key)
+ @uri = key
+ begin
+ uri = URI.parse(URI.escape(key))
+ rescue => detail
+ raise ArgumentError, "Could not understand URL %s: %s" % [source, detail.to_s]
+ end
+ @server = uri.host if uri.host
+
+ # If the URI class can look up the scheme, it will provide a port,
+ # otherwise it will default to '0'.
+ if uri.port.to_i == 0 and uri.scheme == "puppet"
+ @port = Puppet.settings[:masterport].to_i
+ else
+ @port = uri.port.to_i
+ end
+
+ @protocol = uri.scheme
+ @key = uri.path.sub(/^\//, '')
+ end
end
diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb
index 4389dfb7e..a2bfc5d9a 100644
--- a/lib/puppet/indirector/rest.rb
+++ b/lib/puppet/indirector/rest.rb
@@ -1,8 +1,33 @@
require 'net/http'
require 'uri'
+require 'puppet/network/http_pool'
+
# Access objects via REST
class Puppet::Indirector::REST < Puppet::Indirector::Terminus
+
+ class << self
+ attr_reader :server_setting, :port_setting
+ end
+
+ # Specify the setting that we should use to get the server name.
+ def self.use_server_setting(setting)
+ @server_setting = setting
+ end
+
+ def self.server
+ return Puppet.settings[server_setting || :server]
+ end
+
+ # Specify the setting that we should use to get the port.
+ def self.use_port_setting(setting)
+ @port_setting = setting
+ end
+
+ def self.port
+ return Puppet.settings[port_setting || :masterport].to_i
+ end
+
# Figure out the content type, turn that into a format, and use the format
# to extract the body of the response.
def deserialize(response, multiple = false)
@@ -33,20 +58,7 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
end
def network(request)
- if request.key =~ /^\w+:\/\// # it looks like a URI
- begin
- uri = URI.parse(URI.escape(request.key))
- rescue => detail
- raise ArgumentError, "Could not understand URL %s: %s" % [source, detail.to_s]
- end
- server = uri.host || Puppet[:server]
- port = uri.port.to_i == 0 ? Puppet[:masterport].to_i : uri.port.to_i
- else
- server = Puppet[:server]
- port = Puppet[:masterport].to_i
- end
-
- Puppet::Network::HttpPool.http_instance(server, port)
+ Puppet::Network::HttpPool.http_instance(request.server || self.class.server, request.port || self.class.port)
end
def find(request)
diff --git a/spec/unit/indirector/request.rb b/spec/unit/indirector/request.rb
index f7702f821..2476a3d7f 100755
--- a/spec/unit/indirector/request.rb
+++ b/spec/unit/indirector/request.rb
@@ -75,6 +75,37 @@ describe Puppet::Indirector::Request do
it "should keep its options as a hash even if another option is specified" do
Puppet::Indirector::Request.new(:ind, :method, :key, :foo => "bar").options.should be_instance_of(Hash)
end
+
+ describe "and the request key is a URI" do
+ it "should set the protocol to the URI scheme" do
+ Puppet::Indirector::Request.new(:ind, :method, "http://host/stuff").protocol.should == "http"
+ end
+
+ it "should set the server if a server is provided" do
+ Puppet::Indirector::Request.new(:ind, :method, "http://host/stuff").server.should == "host"
+ end
+
+ it "should set the server and port if both are provided" do
+ Puppet::Indirector::Request.new(:ind, :method, "http://host:543/stuff").port.should == 543
+ end
+
+ it "should default to the masterport if the URI scheme is 'puppet'" do
+ Puppet.settings.expects(:value).with(:masterport).returns "321"
+ Puppet::Indirector::Request.new(:ind, :method, "puppet://host/stuff").port.should == 321
+ end
+
+ it "should use the provided port if the URI scheme is not 'puppet'" do
+ Puppet::Indirector::Request.new(:ind, :method, "http://host/stuff").port.should == 80
+ end
+
+ it "should set the request key to the path from the URI" do
+ Puppet::Indirector::Request.new(:ind, :method, "http:///stuff").key.should == "stuff"
+ end
+
+ it "should set the :uri attribute to the full URI" do
+ Puppet::Indirector::Request.new(:ind, :method, "http:///stuff").uri.should == "http:///stuff"
+ end
+ end
end
it "should look use the Indirection class to return the appropriate indirection" do
diff --git a/spec/unit/indirector/rest.rb b/spec/unit/indirector/rest.rb
index 0c88ea4df..e7afbb5b2 100755
--- a/spec/unit/indirector/rest.rb
+++ b/spec/unit/indirector/rest.rb
@@ -45,6 +45,38 @@ describe Puppet::Indirector::REST do
@searcher = @rest_class.new
end
+ it "should have a method for specifying what setting a subclass should use to retrieve its server" do
+ @rest_class.should respond_to(:use_server_setting)
+ end
+
+ it "should use any specified setting to pick the server" do
+ @rest_class.expects(:server_setting).returns :servset
+ Puppet.settings.expects(:value).with(:servset).returns "myserver"
+ @rest_class.server.should == "myserver"
+ end
+
+ it "should default to :server for the server setting" do
+ @rest_class.expects(:server_setting).returns nil
+ Puppet.settings.expects(:value).with(:server).returns "myserver"
+ @rest_class.server.should == "myserver"
+ end
+
+ it "should have a method for specifying what setting a subclass should use to retrieve its port" do
+ @rest_class.should respond_to(:use_port_setting)
+ end
+
+ it "should use any specified setting to pick the port" do
+ @rest_class.expects(:port_setting).returns :servset
+ Puppet.settings.expects(:value).with(:servset).returns "321"
+ @rest_class.port.should == 321
+ end
+
+ it "should default to :port for the port setting" do
+ @rest_class.expects(:port_setting).returns nil
+ Puppet.settings.expects(:value).with(:masterport).returns "543"
+ @rest_class.port.should == 543
+ end
+
describe "when deserializing responses" do
it "should return nil if the response code is 404" do
response = mock 'response'
@@ -91,40 +123,26 @@ describe Puppet::Indirector::REST do
Puppet.settings.stubs(:value).returns("rest_testing")
end
- describe "and the request key is not a URL" do
- it "should use the :server setting as the host and the :masterport setting (as an Integer) as the port" do
- @request = stub 'request', :key => "foo"
- Puppet.settings.expects(:value).with(:server).returns "myserver"
- Puppet.settings.expects(:value).with(:masterport).returns "1234"
- Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 1234).returns "myconn"
- @searcher.network(@request).should == "myconn"
- end
+ it "should use the class's server and port if the indirection request provides neither" do
+ @request = stub 'request', :key => "foo", :server => nil, :port => nil
+ @searcher.class.expects(:port).returns 321
+ @searcher.class.expects(:server).returns "myserver"
+ Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn"
+ @searcher.network(@request).should == "myconn"
end
- describe "and the request key is a URL" do
- it "should use the :server setting and masterport setting, as an Integer, as the host if no values are provided" do
- @request = stub 'request', :key => "puppet:///key"
-
- Puppet.settings.expects(:value).with(:server).returns "myserver"
- Puppet.settings.expects(:value).with(:masterport).returns "1234"
- Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 1234).returns "myconn"
- @searcher.network(@request).should == "myconn"
- end
-
- it "should use the server if one is provided" do
- @request.stubs(:key).returns "puppet://host/key"
-
- Puppet.settings.expects(:value).with(:masterport).returns "1234"
- Puppet::Network::HttpPool.expects(:http_instance).with("host", 1234).returns "myconn"
- @searcher.network(@request).should == "myconn"
- end
-
- it "should use the server and port if they are provided" do
- @request.stubs(:key).returns "puppet://host:123/key"
+ it "should use the server from the indirection request if one is present" do
+ @request = stub 'request', :key => "foo", :server => "myserver", :port => nil
+ @searcher.class.stubs(:port).returns 321
+ Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn"
+ @searcher.network(@request).should == "myconn"
+ end
- Puppet::Network::HttpPool.expects(:http_instance).with("host", 123).returns "myconn"
- @searcher.network(@request).should == "myconn"
- end
+ it "should use the port from the indirection request if one is present" do
+ @request = stub 'request', :key => "foo", :server => nil, :port => 321
+ @searcher.class.stubs(:server).returns "myserver"
+ Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn"
+ @searcher.network(@request).should == "myconn"
end
end