summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2013-11-05 14:53:17 -0800
committerdanielsdeleo <dan@opscode.com>2013-11-05 14:53:17 -0800
commit8ba0f29ab5b3f96f3320f241987813823756ea50 (patch)
tree8183958fe15ccf0b18b0f50efca6eecbe0798753
parentb23cafc337dcbf2053b43e60a0e9783ab33c0876 (diff)
parent82cbc9afc737eb8421db24f04f21ba50edc9ff3e (diff)
downloadchef-8ba0f29ab5b3f96f3320f241987813823756ea50.tar.gz
Merge branch 'CHEF-1848-10-stable' into 10-stable
-rw-r--r--chef/chef.gemspec2
-rw-r--r--chef/lib/chef/rest.rb2
-rw-r--r--chef/spec/unit/rest_spec.rb72
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")