Skip to content

Commit

Permalink
switch back to chef::rest
Browse files Browse the repository at this point in the history
  • Loading branch information
jcam committed Mar 2, 2013
1 parent a2faf73 commit 7d9c7ac
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 61 deletions.
14 changes: 3 additions & 11 deletions lib/chef/provider/remote_file.rb
Expand Up @@ -18,7 +18,6 @@
# #


require 'chef/provider/file' require 'chef/provider/file'
require 'rest_client'
require 'uri' require 'uri'
require 'tempfile' require 'tempfile'


Expand Down Expand Up @@ -110,15 +109,8 @@ def try_multiple_sources(sources)
begin begin
uri = URI.parse(source) uri = URI.parse(source)
raw_file = grab_file_from_uri(uri) raw_file = grab_file_from_uri(uri)
rescue ArgumentError => e rescue SocketError, Errno::ECONNREFUSED, Errno::ENOENT, Errno::EACCES, Timeout::Error, Net::HTTPFatalError, Net::FTPError => e
raise e Chef::Log.warn("#{@new_resource} cannot be downloaded from #{source}: #{e.to_s}")
rescue => e
if e.is_a?(RestClient::Exception)
error = "Request returned #{e.message}"
else
error = e.to_s
end
Chef::Log.info("#{@new_resource} cannot be downloaded from #{source}: #{error}")
if source = sources.shift if source = sources.shift
Chef::Log.info("#{@new_resource} trying to download from another mirror") Chef::Log.info("#{@new_resource} trying to download from another mirror")
retry retry
Expand Down Expand Up @@ -146,7 +138,7 @@ def grab_file_from_uri(uri)
end end
if URI::HTTP === uri if URI::HTTP === uri
#HTTP or HTTPS #HTTP or HTTPS
raw_file, mtime, etag = HTTP::fetch(uri, proxy_uri(uri), if_modified_since, if_none_match) raw_file, mtime, etag = HTTP::fetch(uri, if_modified_since, if_none_match)

This comment has been minimized.

Copy link
@danielsdeleo

danielsdeleo Mar 11, 2013

Using :: to call a class method should be considered deprecated in ruby even if not officially so.

elsif URI::FTP === uri elsif URI::FTP === uri
#FTP #FTP
raw_file, mtime = FTP::fetch(uri, proxy_uri(uri), @new_resource.ftp_active_mode, if_modified_since) raw_file, mtime = FTP::fetch(uri, proxy_uri(uri), @new_resource.ftp_active_mode, if_modified_since)
Expand Down
60 changes: 39 additions & 21 deletions lib/chef/provider/remote_file/http.rb
Expand Up @@ -18,6 +18,7 @@


require 'uri' require 'uri'
require 'tempfile' require 'tempfile'
require 'chef/rest'
require 'chef/provider/remote_file' require 'chef/provider/remote_file'


class Chef class Chef
Expand All @@ -26,41 +27,40 @@ class RemoteFile
class HTTP class HTTP


# Fetches the file at uri, returning a Tempfile-like File handle # Fetches the file at uri, returning a Tempfile-like File handle
def self.fetch(uri, proxy_uri, if_modified_since, if_none_match) def self.fetch(uri, if_modified_since, if_none_match)
request = HTTP.new(uri, proxy_uri, if_modified_since, if_none_match) request = HTTP.new(uri, if_modified_since, if_none_match)
request.execute request.execute
end end


# Parse the uri into instance variables # Parse the uri into instance variables
def initialize(uri, proxy_uri, if_modified_since, if_none_match) def initialize(uri, if_modified_since, if_none_match)
RestClient.proxy = proxy_uri.to_s
@headers = Hash.new @headers = Hash.new
if if_none_match if if_none_match
@headers[:if_none_match] = "\"#{if_none_match}\"" @headers['if-none-match'] = "\"#{if_none_match}\""
elsif if_modified_since elsif if_modified_since
@headers[:if_modified_since] = if_modified_since.strftime("%a, %d %b %Y %H:%M:%S %Z") @headers['if-modified-since'] = if_modified_since.strftime("%a, %d %b %Y %H:%M:%S %Z")
end end
@uri = uri @uri = uri
end end


def execute def execute
begin begin
rest = RestClient::Request.execute(:method => :get, :url => @uri.to_s, :headers => @headers, :raw_response => true) rest = Chef::REST.new(@uri, nil, nil, http_client_opts)
tempfile = rest.file tempfile = rest.streaming_request(@uri, @headers)
if rest.headers.include?(:last_modified) if rest.last_response['last_modified']
mtime = Time.parse(rest.headers[:last_modified]) mtime = Time.parse(rest.last_response['last_modified'])
elsif rest.headers.include?(:date) elsif rest.last_response['date']
mtime = Time.parse(rest.headers[:date]) mtime = Time.parse(rest.last_response['date'])
else else
mtime = Time.now mtime = Time.now
end end
if rest.headers.include?(:etag) if rest.last_response['etag']
etag = rest.headers[:etag] etag = rest.last_response['etag']
else else
etag = nil etag = nil
end end
rescue RestClient::Exception => e rescue Net::HTTPRetriableError => e
if e.http_code == 304 if e.response.is_a? Net::HTTPNotModified
tempfile = nil tempfile = nil
else else
raise e raise e
Expand All @@ -69,6 +69,24 @@ def execute
return tempfile, mtime, etag return tempfile, mtime, etag
end end


private

def http_client_opts
opts={}
# CHEF-3140
# 1. If it's already compressed, trying to compress it more will
# probably be counter-productive.
# 2. Some servers are misconfigured so that you GET $URL/file.tgz but
# they respond with content type of tar and content encoding of gzip,
# which tricks Chef::REST into decompressing the response body. In this
# case you'd end up with a tar archive (no gzip) named, e.g., foo.tgz,
# which is not what you wanted.
if @uri.to_s =~ /gz$/
opts[:disable_gzip] = true
end
opts
end

end end
end end
end end
Expand Down
2 changes: 1 addition & 1 deletion lib/chef/provider/remote_file/local_file.rb
Expand Up @@ -31,7 +31,7 @@ def self.fetch(uri, if_modified_since)
if mtime && if_modified_since && mtime.to_i <= if_modified_since.to_i if mtime && if_modified_since && mtime.to_i <= if_modified_since.to_i
tempfile = nil tempfile = nil
else else
tempfile = Tempfile.new(File.basename(uri.path)) tempfile = Tempfile.new(::File.basename(uri.path))
Chef::Log.debug("#{@new_resource} staging #{uri.path} to #{tempfile.path}") Chef::Log.debug("#{@new_resource} staging #{uri.path} to #{tempfile.path}")
FileUtils.cp(uri.path, tempfile.path) FileUtils.cp(uri.path, tempfile.path)
tempfile tempfile
Expand Down
6 changes: 6 additions & 0 deletions lib/chef/rest.rb
Expand Up @@ -84,6 +84,10 @@ def signing_key
@raw_key @raw_key
end end


def last_response
@last_response
end

# Send an HTTP GET request to the path # Send an HTTP GET request to the path
# #
# Using this method to +fetch+ a file is considered deprecated. # Using this method to +fetch+ a file is considered deprecated.
Expand Down Expand Up @@ -164,6 +168,7 @@ def raw_http_request(method, url, headers, body)
retriable_rest_request(method, url, body, headers) do |rest_request| retriable_rest_request(method, url, body, headers) do |rest_request|
begin begin
response = rest_request.call {|r| r.read_body} response = rest_request.call {|r| r.read_body}
@last_response = response


Chef::Log.debug("---- HTTP Status and Header Data: ----") Chef::Log.debug("---- HTTP Status and Header Data: ----")
Chef::Log.debug("HTTP #{response.http_version} #{response.code} #{response.msg}") Chef::Log.debug("HTTP #{response.http_version} #{response.code} #{response.msg}")
Expand Down Expand Up @@ -248,6 +253,7 @@ def streaming_request(url, headers, &block)
tempfile = stream_to_tempfile(url, r) tempfile = stream_to_tempfile(url, r)
end end
end end
@last_response = response
if response.kind_of?(Net::HTTPSuccess) if response.kind_of?(Net::HTTPSuccess)
tempfile tempfile
elsif redirect_location = redirected_to(response) elsif redirect_location = redirected_to(response)
Expand Down
7 changes: 6 additions & 1 deletion lib/chef/rest/rest_request.rb
Expand Up @@ -21,6 +21,7 @@
# limitations under the License. # limitations under the License.
# #
require 'uri' require 'uri'
require 'cgi'
require 'net/http' require 'net/http'
require 'chef/rest/cookie_jar' require 'chef/rest/cookie_jar'


Expand Down Expand Up @@ -220,7 +221,11 @@ def configure_http_request(request_body=nil)


@http_request.body = request_body if (request_body && @http_request.request_body_permitted?) @http_request.body = request_body if (request_body && @http_request.request_body_permitted?)
# Optionally handle HTTP Basic Authentication # Optionally handle HTTP Basic Authentication
@http_request.basic_auth(url.user, url.password) if url.user if url.user
user = CGI.unescape(url.user)
password = CGI.unescape(url.password) if url.password
@http_request.basic_auth(user, password)
end
@http_request[USER_AGENT] = self.class.user_agent @http_request[USER_AGENT] = self.class.user_agent
end end


Expand Down
45 changes: 18 additions & 27 deletions spec/unit/provider/remote_file_spec.rb
Expand Up @@ -46,9 +46,11 @@
describe "when fetching the file from the remote" do describe "when fetching the file from the remote" do
before(:each) do before(:each) do
@tempfile = Tempfile.new("chef-rspec-remote_file_spec-line#{__LINE__}--") @tempfile = Tempfile.new("chef-rspec-remote_file_spec-line#{__LINE__}--")
@rawresp = RestClient::RawResponse.new(@tempfile, Hash.new, nil)


RestClient::Request.stub!(:execute).and_return(@rawresp) @rest = mock(Chef::REST, { })
Chef::REST.stub!(:new).and_return(@rest)
@rest.stub!(:streaming_request).and_return(@tempfile)
@rest.stub!(:last_response).and_return({})
@resource.cookbook_name = "monkey" @resource.cookbook_name = "monkey"


@provider.stub!(:checksum).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") @provider.stub!(:checksum).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa")
Expand Down Expand Up @@ -79,19 +81,19 @@


shared_examples_for "source specified with multiple URIs" do shared_examples_for "source specified with multiple URIs" do
it "should try to download the next URI when the first one fails" do it "should try to download the next URI when the first one fails" do
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://foo", :headers => {}, :raw_response => true).once.and_raise(SocketError) @rest.should_receive(:streaming_request).with(URI.parse("http://foo"), {}).once.and_raise(SocketError)
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://bar", :headers => {}, :raw_response => true).once.and_return(@rawresp) @rest.should_receive(:streaming_request).with(URI.parse("http://bar"), {}).once.and_return(@tempfile)
@provider.run_action(:create) @provider.run_action(:create)
end end


it "should raise an exception when all the URIs fail" do it "should raise an exception when all the URIs fail" do
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://foo", :headers => {}, :raw_response => true).once.and_raise(SocketError) @rest.should_receive(:streaming_request).with(URI.parse("http://foo"), {}).once.and_raise(SocketError)
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://bar", :headers => {}, :raw_response => true).once.and_raise(SocketError) @rest.should_receive(:streaming_request).with(URI.parse("http://bar"), {}).once.and_raise(SocketError)
lambda { @provider.run_action(:create) }.should raise_error(SocketError) lambda { @provider.run_action(:create) }.should raise_error(SocketError)
end end


it "should download from only one URI when the first one works" do it "should download from only one URI when the first one works" do
RestClient::Request.should_receive(:execute).once.and_return(@rawresp) @rest.should_receive(:streaming_request).once.and_return(@tempfile)
@provider.run_action(:create) @provider.run_action(:create)
end end


Expand Down Expand Up @@ -121,7 +123,7 @@
end end


it "does not download the file" do it "does not download the file" do
RestClient::Request.should_not_receive(:execute) @rest.should_not_receive(:fetch)
@provider.run_action(:create) @provider.run_action(:create)
end end


Expand All @@ -138,7 +140,7 @@
end end


it "should not download the file if the checksum is a partial match from the beginning" do it "should not download the file if the checksum is a partial match from the beginning" do
RestClient::Request.should_not_receive(:execute) @rest.should_not_receive(:fetch)
@provider.run_action(:create) @provider.run_action(:create)
end end


Expand All @@ -152,15 +154,15 @@
describe "and the existing file doesn't match the given checksum" do describe "and the existing file doesn't match the given checksum" do
it "downloads the file" do it "downloads the file" do
@resource.checksum("this hash doesn't match") @resource.checksum("this hash doesn't match")
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://opscode.com/seattle.txt", :headers => {}, :raw_response => true).and_return(@rawresp) @rest.should_receive(:streaming_request).with(URI.parse("http://opscode.com/seattle.txt"), {}).and_return(@tempfile)
@provider.stub!(:update_new_file_state) @provider.stub!(:update_new_file_state)
@provider.run_action(:create) @provider.run_action(:create)
end end


it "does not consider the checksum a match if the matching string is offset" do it "does not consider the checksum a match if the matching string is offset" do
# i.e., the existing file is "0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa" # i.e., the existing file is "0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa"
@resource.checksum("fd012fd") @resource.checksum("fd012fd")
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://opscode.com/seattle.txt", :headers => {}, :raw_response => true).and_return(@rawresp) @rest.should_receive(:streaming_request).with(URI.parse("http://opscode.com/seattle.txt"), {}).and_return(@tempfile)
@provider.stub!(:update_new_file_state) @provider.stub!(:update_new_file_state)
@provider.run_action(:create) @provider.run_action(:create)
end end
Expand All @@ -171,7 +173,7 @@
describe "and the resource doesn't specify a checksum" do describe "and the resource doesn't specify a checksum" do
it "should download the file from the remote URL" do it "should download the file from the remote URL" do
@resource.checksum(nil) @resource.checksum(nil)
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://opscode.com/seattle.txt", :headers => {}, :raw_response => true).and_return(@rawresp) @rest.should_receive(:streaming_request).with(URI.parse("http://opscode.com/seattle.txt"), {}).and_return(@tempfile)
@provider.run_action(:create) @provider.run_action(:create)
end end
end end
Expand All @@ -185,22 +187,10 @@
# detect when users are fetching gzipped files and turn off gzip in # detect when users are fetching gzipped files and turn off gzip in
# Chef::REST. # Chef::REST.


context "and the target file is a tarball" do
before do
@resource.path(File.expand_path(File.join(CHEF_SPEC_DATA, "seattle.tar.gz")))
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://opscode.com/seattle.txt", :headers => {}, :raw_response => true).and_return(@rawresp)
end

it "disables gzip in the http client" do
@provider.action_create
end

end

context "and the source appears to be a tarball" do context "and the source appears to be a tarball" do
before do before do
@resource.source("http://example.com/tarball.tgz") @resource.source("http://example.com/tarball.tgz")
RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://example.com/tarball.tgz", :headers => {}, :raw_response => true).and_return(@rawresp) Chef::REST.should_receive(:new).with(URI.parse("http://example.com/tarball.tgz"), nil, nil, :disable_gzip => true).and_return(@rest)
end end


it "disables gzip in the http client" do it "disables gzip in the http client" do
Expand Down Expand Up @@ -239,14 +229,14 @@
it "should raise an exception if it's any other kind of retriable response than 304" do it "should raise an exception if it's any other kind of retriable response than 304" do
r = Net::HTTPMovedPermanently.new("one", "two", "three") r = Net::HTTPMovedPermanently.new("one", "two", "three")
e = Net::HTTPRetriableError.new("301", r) e = Net::HTTPRetriableError.new("301", r)
RestClient::Request.stub!(:execute).and_raise(e) @rest.stub!(:streaming_request).and_raise(e)
lambda { @provider.run_action(:create) }.should raise_error(Net::HTTPRetriableError) lambda { @provider.run_action(:create) }.should raise_error(Net::HTTPRetriableError)
end end


it "should raise an exception if anything else happens" do it "should raise an exception if anything else happens" do
r = Net::HTTPBadRequest.new("one", "two", "three") r = Net::HTTPBadRequest.new("one", "two", "three")
e = Net::HTTPServerException.new("fake exception", r) e = Net::HTTPServerException.new("fake exception", r)
RestClient::Request.stub!(:execute).and_raise(e) @rest.stub!(:streaming_request).and_raise(e)
lambda { @provider.run_action(:create) }.should raise_error(Net::HTTPServerException) lambda { @provider.run_action(:create) }.should raise_error(Net::HTTPServerException)
end end


Expand Down Expand Up @@ -342,6 +332,7 @@
@provider.should_receive(:set_all_access_controls).and_return(true) @provider.should_receive(:set_all_access_controls).and_return(true)
@provider.run_action(:create) @provider.run_action(:create)
end end

end end
end end
end end

0 comments on commit 7d9c7ac

Please sign in to comment.