summaryrefslogtreecommitdiffstats
path: root/spec/unit
diff options
context:
space:
mode:
authorPaul Berry <paul@puppetlabs.com>2011-01-10 17:05:38 -0800
committerPaul Berry <paul@puppetlabs.com>2011-01-12 16:29:06 -0800
commitc514c641d0c0090be29252dcc773385248d3fe93 (patch)
treeb73294a3764f4dc0743971aee1fcc574d5d85f02 /spec/unit
parent2b9b7a5f7fe4b673f0d1fba9fb523cc0e2e34fa5 (diff)
downloadpuppet-c514c641d0c0090be29252dcc773385248d3fe93.tar.gz
puppet-c514c641d0c0090be29252dcc773385248d3fe93.tar.xz
puppet-c514c641d0c0090be29252dcc773385248d3fe93.zip
(#5838) Added support for HEAD requests to the indirector.
Added the ability for the indirector to handle REST HEAD requests. These are done using a new indirector method, head(), which should return true if find() would return a result and false if find() would return nil. Access control for the head method is the union of that for the find and save methods. That is, if either find or save is allowed, then head is allowed. This is necessary so that users will not have to change their authconfig to take advantage of the new feature. Paired-with: Jesse Wolfe <jesse@puppetlabs.com>
Diffstat (limited to 'spec/unit')
-rwxr-xr-xspec/unit/indirector/file_server_spec.rb13
-rwxr-xr-xspec/unit/indirector/indirection_spec.rb69
-rwxr-xr-xspec/unit/indirector/rest_spec.rb36
-rwxr-xr-xspec/unit/indirector_spec.rb5
-rw-r--r--spec/unit/network/http/api/v1_spec.rb4
-rwxr-xr-xspec/unit/network/http/handler_spec.rb33
-rwxr-xr-xspec/unit/network/rest_authconfig_spec.rb2
-rwxr-xr-xspec/unit/network/rights_spec.rb20
8 files changed, 174 insertions, 8 deletions
diff --git a/spec/unit/indirector/file_server_spec.rb b/spec/unit/indirector/file_server_spec.rb
index 686f79a24..eafcf2bb7 100755
--- a/spec/unit/indirector/file_server_spec.rb
+++ b/spec/unit/indirector/file_server_spec.rb
@@ -229,6 +229,12 @@ describe Puppet::Indirector::FileServer do
describe "when checking authorization" do
before do
@request.method = :find
+
+ @mount = stub 'mount'
+ @configuration.stubs(:split_path).with(@request).returns([@mount, "rel/path"])
+ @request.stubs(:node).returns("mynode")
+ @request.stubs(:ip).returns("myip")
+ @mount.stubs(:allowed?).with("mynode", "myip").returns "something"
end
it "should return false when destroying" do
@@ -254,13 +260,6 @@ describe Puppet::Indirector::FileServer do
end
it "should return the results of asking the mount whether the node and IP are authorized" do
- @mount = stub 'mount'
- @configuration.expects(:split_path).with(@request).returns([@mount, "rel/path"])
-
- @request.stubs(:node).returns("mynode")
- @request.stubs(:ip).returns("myip")
- @mount.expects(:allowed?).with("mynode", "myip").returns "something"
-
@file_server.authorized?(@request).should == "something"
end
end
diff --git a/spec/unit/indirector/indirection_spec.rb b/spec/unit/indirector/indirection_spec.rb
index 1e774fb2e..a910cb6f2 100755
--- a/spec/unit/indirector/indirection_spec.rb
+++ b/spec/unit/indirector/indirection_spec.rb
@@ -383,6 +383,75 @@ describe Puppet::Indirector::Indirection do
end
end
+ describe "and doing a head operation" do
+ before { @method = :head }
+
+ it_should_behave_like "Indirection Delegator"
+ it_should_behave_like "Delegation Authorizer"
+
+ it "should return true if the head method returned true" do
+ @terminus.expects(:head).returns(true)
+ @indirection.head("me").should == true
+ end
+
+ it "should return false if the head method returned false" do
+ @terminus.expects(:head).returns(false)
+ @indirection.head("me").should == false
+ end
+
+ describe "when caching is enabled" do
+ before do
+ @indirection.cache_class = :cache_terminus
+ @cache_class.stubs(:new).returns(@cache)
+
+ @instance.stubs(:expired?).returns false
+ end
+
+ it "should first look in the cache for an instance" do
+ @terminus.stubs(:find).never
+ @terminus.stubs(:head).never
+ @cache.expects(:find).returns @instance
+
+ @indirection.head("/my/key").should == true
+ end
+
+ it "should not save to the cache" do
+ @cache.expects(:find).returns nil
+ @cache.expects(:save).never
+ @terminus.expects(:head).returns true
+ @indirection.head("/my/key").should == true
+ end
+
+ it "should not fail if the cache fails" do
+ @terminus.stubs(:head).returns true
+
+ @cache.expects(:find).raises ArgumentError
+ lambda { @indirection.head("/my/key") }.should_not raise_error
+ end
+
+ it "should look in the main terminus if the cache fails" do
+ @terminus.expects(:head).returns true
+ @cache.expects(:find).raises ArgumentError
+ @indirection.head("/my/key").should == true
+ end
+
+ it "should send a debug log if it is using the cached object" do
+ Puppet.expects(:debug)
+ @cache.stubs(:find).returns @instance
+
+ @indirection.head("/my/key")
+ end
+
+ it "should not accept the cached object if it is expired" do
+ @instance.stubs(:expired?).returns true
+
+ @cache.stubs(:find).returns @instance
+ @terminus.stubs(:head).returns false
+ @indirection.head("/my/key").should == false
+ end
+ end
+ end
+
describe "and storing a model instance" do
before { @method = :save }
diff --git a/spec/unit/indirector/rest_spec.rb b/spec/unit/indirector/rest_spec.rb
index 5f0fe363a..7bc1cc513 100755
--- a/spec/unit/indirector/rest_spec.rb
+++ b/spec/unit/indirector/rest_spec.rb
@@ -282,6 +282,42 @@ describe Puppet::Indirector::REST do
end
end
+ describe "when doing a head" do
+ before :each do
+ @connection = stub('mock http connection', :head => @response)
+ @searcher.stubs(:network).returns(@connection)
+
+ # Use a key with spaces, so we can test escaping
+ @request = Puppet::Indirector::Request.new(:foo, :head, "foo bar")
+ end
+
+ it "should call the HEAD http method on a network connection" do
+ @searcher.expects(:network).returns @connection
+ @connection.expects(:head).returns @response
+ @searcher.head(@request)
+ end
+
+ it "should return true if there was a successful http response" do
+ @connection.expects(:head).returns @response
+ @response.stubs(:code).returns "200"
+
+ @searcher.head(@request).should == true
+ end
+
+ it "should return false if there was a successful http response" do
+ @connection.expects(:head).returns @response
+ @response.stubs(:code).returns "404"
+
+ @searcher.head(@request).should == false
+ end
+
+ it "should use the URI generated by the Handler module" do
+ @searcher.expects(:indirection2uri).with(@request).returns "/my/uri"
+ @connection.expects(:head).with { |path, args| path == "/my/uri" }.returns(@response)
+ @searcher.head(@request)
+ end
+ end
+
describe "when doing a search" do
before :each do
@connection = stub('mock http connection', :get => @response)
diff --git a/spec/unit/indirector_spec.rb b/spec/unit/indirector_spec.rb
index acbfc1726..6f44764da 100755
--- a/spec/unit/indirector_spec.rb
+++ b/spec/unit/indirector_spec.rb
@@ -118,6 +118,11 @@ describe Puppet::Indirector, "when redirecting a model" do
it_should_behave_like "Delegated Indirection Method"
end
+ describe "when performing a head request" do
+ before { @method = :head }
+ it_should_behave_like "Delegated Indirection Method"
+ end
+
# This is an instance method, so it behaves a bit differently.
describe "when saving instances via the model" do
before do
diff --git a/spec/unit/network/http/api/v1_spec.rb b/spec/unit/network/http/api/v1_spec.rb
index c593242c0..23a291cf3 100644
--- a/spec/unit/network/http/api/v1_spec.rb
+++ b/spec/unit/network/http/api/v1_spec.rb
@@ -68,6 +68,10 @@ describe Puppet::Network::HTTP::API::V1 do
@tester.uri2indirection("GET", "/env/foo/bar", {}).method.should == :find
end
+ it "should choose 'head' as the indirection method if the http method is a HEAD and the indirection name is singular" do
+ @tester.uri2indirection("HEAD", "/env/foo/bar", {}).method.should == :head
+ end
+
it "should choose 'search' as the indirection method if the http method is a GET and the indirection name is plural" do
@tester.uri2indirection("GET", "/env/foos/bar", {}).method.should == :search
end
diff --git a/spec/unit/network/http/handler_spec.rb b/spec/unit/network/http/handler_spec.rb
index cdbce41f7..8464ae68e 100755
--- a/spec/unit/network/http/handler_spec.rb
+++ b/spec/unit/network/http/handler_spec.rb
@@ -256,6 +256,39 @@ describe Puppet::Network::HTTP::Handler do
end
end
+ describe "when performing head operation" do
+ before do
+ @irequest = stub 'indirection_request', :method => :head, :indirection_name => "my_handler", :to_hash => {}, :key => "my_result", :model => @model_class
+
+ @model_class.stubs(:head).returns true
+ end
+
+ it "should use the indirection request to find the model class" do
+ @irequest.expects(:model).returns @model_class
+
+ @handler.do_head(@irequest, @request, @response)
+ end
+
+ it "should use the escaped request key" do
+ @model_class.expects(:head).with do |key, args|
+ key == "my_result"
+ end.returns true
+ @handler.do_head(@irequest, @request, @response)
+ end
+
+ it "should not generate a response when a model head call succeeds" do
+ @handler.expects(:set_response).never
+ @handler.do_head(@irequest, @request, @response)
+ end
+
+ it "should return a 404 when the model head call returns false" do
+ @model_class.stubs(:name).returns "my name"
+ @handler.expects(:set_response).with { |response, body, status| status == 404 }
+ @model_class.stubs(:head).returns(false)
+ @handler.do_head(@irequest, @request, @response)
+ end
+ end
+
describe "when searching for model instances" do
before do
@irequest = stub 'indirection_request', :method => :find, :indirection_name => "my_handler", :to_hash => {}, :key => "key", :model => @model_class
diff --git a/spec/unit/network/rest_authconfig_spec.rb b/spec/unit/network/rest_authconfig_spec.rb
index 9892c2b25..d629f8670 100755
--- a/spec/unit/network/rest_authconfig_spec.rb
+++ b/spec/unit/network/rest_authconfig_spec.rb
@@ -47,7 +47,7 @@ describe Puppet::Network::RestAuthConfig do
end
it "should ask for authorization to the ACL subsystem" do
- @acl.expects(:is_forbidden_and_why?).with("/path/to/resource", :node => "me", :ip => "127.0.0.1", :method => :save, :environment => :env, :authenticated => true).returns(nil)
+ @acl.expects(:is_request_forbidden_and_why?).with(@request).returns(nil)
@authconfig.allowed?(@request)
end
diff --git a/spec/unit/network/rights_spec.rb b/spec/unit/network/rights_spec.rb
index ca3f22464..3b9e48374 100755
--- a/spec/unit/network/rights_spec.rb
+++ b/spec/unit/network/rights_spec.rb
@@ -9,6 +9,26 @@ describe Puppet::Network::Rights do
@right = Puppet::Network::Rights.new
end
+ describe "when validating a :head request" do
+ [:find, :save].each do |allowed_method|
+ it "should allow the request if only #{allowed_method} is allowed" do
+ rights = Puppet::Network::Rights.new
+ rights.newright("/")
+ rights.allow("/", "*")
+ rights.restrict_method("/", allowed_method)
+ rights.restrict_authenticated("/", :any)
+ request = Puppet::Indirector::Request.new(:indirection_name, :head, "key")
+ rights.is_request_forbidden_and_why?(request).should == nil
+ end
+ end
+
+ it "should disallow the request if neither :find nor :save is allowed" do
+ rights = Puppet::Network::Rights.new
+ request = Puppet::Indirector::Request.new(:indirection_name, :head, "key")
+ rights.is_request_forbidden_and_why?(request).should be_instance_of(Puppet::Network::AuthorizationError)
+ end
+ end
+
[:allow, :deny, :restrict_method, :restrict_environment, :restrict_authenticated].each do |m|
it "should have a #{m} method" do
@right.should respond_to(m)