diff options
author | danielsdeleo <dan@opscode.com> | 2013-11-05 14:53:17 -0800 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2013-11-05 14:53:17 -0800 |
commit | 8ba0f29ab5b3f96f3320f241987813823756ea50 (patch) | |
tree | 8183958fe15ccf0b18b0f50efca6eecbe0798753 | |
parent | b23cafc337dcbf2053b43e60a0e9783ab33c0876 (diff) | |
parent | 82cbc9afc737eb8421db24f04f21ba50edc9ff3e (diff) | |
download | chef-8ba0f29ab5b3f96f3320f241987813823756ea50.tar.gz |
Merge branch 'CHEF-1848-10-stable' into 10-stable
-rw-r--r-- | chef/chef.gemspec | 2 | ||||
-rw-r--r-- | chef/lib/chef/rest.rb | 2 | ||||
-rw-r--r-- | chef/spec/unit/rest_spec.rb | 72 |
3 files changed, 51 insertions, 25 deletions
diff --git a/chef/chef.gemspec b/chef/chef.gemspec index 6a87ae27d2..435c33ffa5 100644 --- a/chef/chef.gemspec +++ b/chef/chef.gemspec @@ -40,7 +40,7 @@ Gem::Specification.new do |s| # development_dependency thin: eventmachine 0.12.10 doesn't support Ruby 1.9 on Windows %w(rdoc sdoc rake rack rspec_junit_formatter).each { |gem| s.add_development_dependency gem } - %w(rspec-core rspec-expectations rspec-mocks).each { |gem| s.add_development_dependency gem, "~> 2.8.0" } + %w(rspec-core rspec-expectations rspec-mocks).each { |gem| s.add_development_dependency gem, "~> 2.12.0" } s.bindir = "bin" s.executables = %w( chef-client chef-solo knife shef ) diff --git a/chef/lib/chef/rest.rb b/chef/lib/chef/rest.rb index 5556800fcd..a3f36b8c4f 100644 --- a/chef/lib/chef/rest.rb +++ b/chef/lib/chef/rest.rb @@ -276,7 +276,7 @@ class Chef end elsif redirect_location = redirected_to(response) if [:GET, :HEAD].include?(method) - follow_redirect {api_request(method, create_url(redirect_location))} + follow_redirect {api_request(method, create_url(redirect_location), headers)} else raise Exceptions::InvalidRedirect, "#{method} request was redirected from #{url} to #{redirect_location}. Only GET and HEAD support redirects." end diff --git a/chef/spec/unit/rest_spec.rb b/chef/spec/unit/rest_spec.rb index b1c3f54a9b..bc7ad084e6 100644 --- a/chef/spec/unit/rest_spec.rb +++ b/chef/spec/unit/rest_spec.rb @@ -278,9 +278,11 @@ describe Chef::REST do describe "streaming downloads to a tempfile" do before do - @tempfile = Tempfile.open("chef-rspec-rest_spec-line-#{__LINE__}--") - Tempfile.stub!(:new).with("chef-rest").and_return(@tempfile) - Tempfile.stub!(:open).and_return(@tempfile) + @tempfile = StringIO.new + @tempfile.stub(:close!) + @tempfile.stub(:path).and_return("/tmp/this-is-a-stringio-not-a-real-file") + Tempfile.stub(:new).with("chef-rest").and_return(@tempfile) + Tempfile.stub(:open).and_return(@tempfile) @request_mock = {} Net::HTTP::Get.stub!(:new).and_return(@request_mock) @@ -288,11 +290,6 @@ describe Chef::REST do @http_response_mock = mock("Net::HTTP Response mock") end - after do - @tempfile.rspec_reset - @tempfile.close! - end - it "should build a new HTTP GET request without the application/json accept header" do expected_headers = {'X-Chef-Version' => Chef::VERSION, 'Accept-Encoding' => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE} Net::HTTP::Get.should_receive(:new).with("/?foo=bar", expected_headers).and_return(@request_mock) @@ -309,9 +306,9 @@ describe Chef::REST do end it "should populate the tempfile with the value of the raw request" do - @http_response_mock.stub!(:read_body).and_yield("ninja") - @tempfile.should_receive(:write).with("ninja").once.and_return(true) + @http_response.should_receive(:read_body).and_yield("ninja") @rest.run_request(:GET, @url, {}, false, nil, true) + @tempfile.string.should include("ninja") end it "should close the tempfile if we're doing a raw request" do @@ -426,22 +423,54 @@ describe Chef::REST do @rest.api_request(:GET, @url, {}).should == {"ohai2u"=>"json_api"} end - %w[ HTTPFound HTTPMovedPermanently HTTPSeeOther HTTPUseProxy HTTPTemporaryRedirect HTTPMultipleChoice ].each do |resp_name| - it "should call api_request again on a #{resp_name} response" do - resp_cls = Net.const_get(resp_name) + describe "when the server returns a redirect response" do + let(:redirected_url) { "https://chef.example.com:8443/foo" } + let(:redirected_uri) { URI.parse(redirected_url) } + + def redirect_with(response_name) + resp_cls = Net.const_get(response_name) resp_code = Net::HTTPResponse::CODE_TO_OBJ.keys.detect { |k| Net::HTTPResponse::CODE_TO_OBJ[k] == resp_cls } - http_response = Net::HTTPFound.new("1.1", resp_code, "bob is somewhere else again") - http_response.add_field("location", @url.path) - http_response.stub!(:read_body) + redirect = Net::HTTPFound.new("1.1", resp_code, "bob is somewhere else again") + redirect.add_field("location", redirected_url) + redirect.stub!(:read_body).and_return('') + redirect + end - @http_client.stub!(:request).and_yield(http_response).and_return(http_response) + %w[ HTTPFound HTTPMovedPermanently HTTPSeeOther HTTPUseProxy HTTPTemporaryRedirect HTTPMultipleChoice ].each do |response_name| + + it "should call api_request again on a #{response_name} response" do + redirect = redirect_with(response_name) + + headers = { "X-Auth-Header" => "foo" } + auto_headers = {"Accept"=>"application/json", "Accept-Encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3"} + expected_headers = auto_headers.merge(headers) + + success = Net::HTTPSuccess.new("1.1",200, "it-works") + success.stub!(:read_body).and_return('{"foo": "bar"}') + success['content-type'] = "application/json" + + @http_client.should_receive(:request).and_yield(redirect).and_return(redirect) + @http_client.should_receive(:request).and_yield(success).and_return(success) - lambda { @rest.api_request(:GET, @url) }.should raise_error(Chef::Exceptions::RedirectLimitExceeded) + # CHEF-1848: verify that headers get passed to redirects + @rest.should_receive(:retriable_rest_request).with(:GET, @url, nil, expected_headers).and_call_original + @rest.should_receive(:retriable_rest_request).with(:GET, redirected_uri, nil, expected_headers).and_call_original - [:PUT, :POST, :DELETE].each do |method| - lambda { @rest.api_request(method, @url) }.should raise_error(Chef::Exceptions::InvalidRedirect) + @rest.api_request(:GET, @url, headers).should == {"foo" => "bar"} + end + + context "when making a request for a method other than GET" do + + [:PUT, :POST, :DELETE].each do |method| + it "raises an error" do + redirect = redirect_with(response_name) + @http_client.should_receive(:request).and_yield(redirect).and_return(redirect) + lambda { @rest.api_request(method, @url) }.should raise_error(Chef::Exceptions::InvalidRedirect) + end + end end end + end it "should show the JSON error message on an unsuccessful request" do @@ -494,7 +523,6 @@ describe Chef::REST do end after do - @tempfile.rspec_reset @tempfile.close! end @@ -561,7 +589,6 @@ describe Chef::REST do end it "closes and unlinks the tempfile when the response is a redirect" do - Tempfile.rspec_reset tempfile = mock("die", :path => "/tmp/ragefist", :close => true, :binmode => nil) tempfile.should_receive(:close!).at_least(2).times Tempfile.stub!(:new).with("chef-rest").and_return(tempfile) @@ -575,7 +602,6 @@ describe Chef::REST do end it "passes the original block to the redirected request" do - Tempfile.rspec_reset http_response = Net::HTTPFound.new("1.1", "302", "bob is taking care of that one for me today") http_response.add_field("location","/that-thing-is-here-now") |