diff options
-rw-r--r-- | lib/chef/provider/remote_file.rb | 93 | ||||
-rw-r--r-- | lib/chef/provider/remote_file/ftp.rb | 95 | ||||
-rw-r--r-- | lib/chef/providers.rb | 2 | ||||
-rw-r--r-- | lib/chef/resource/remote_file.rb | 11 | ||||
-rw-r--r-- | spec/data/remote_file/nyan_cat.png.gz | bin | 14944 -> 0 bytes | |||
-rw-r--r-- | spec/functional/resource/remote_file_spec.rb | 43 | ||||
-rw-r--r-- | spec/tiny_server.rb | 21 | ||||
-rw-r--r-- | spec/unit/provider/remote_file/ftp_spec.rb | 117 | ||||
-rw-r--r-- | spec/unit/provider/remote_file_spec.rb | 65 | ||||
-rw-r--r-- | spec/unit/resource/remote_file_spec.rb | 18 |
10 files changed, 90 insertions, 375 deletions
diff --git a/lib/chef/provider/remote_file.rb b/lib/chef/provider/remote_file.rb index 4d1e696d0e..f985682441 100644 --- a/lib/chef/provider/remote_file.rb +++ b/lib/chef/provider/remote_file.rb @@ -1,5 +1,4 @@ # -# Author:: Jesse Campbell (<hikeit@gmail.com>) # Author:: Adam Jacob (<adam@opscode.com>) # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 @@ -18,9 +17,10 @@ # require 'chef/provider/file' -require 'rest_client' +require 'chef/rest' require 'uri' require 'tempfile' +require 'net/https' class Chef class Provider @@ -40,12 +40,24 @@ class Chef Chef::Log.debug("#{@new_resource} checksum matches target checksum (#{@new_resource.checksum}) - not updating") else sources = @new_resource.source - raw_file, raw_file_source = try_multiple_sources(sources) + source = sources.shift + begin + rest = Chef::REST.new(source, nil, nil, http_client_opts(source)) + raw_file = rest.streaming_request(rest.create_url(source), {}) + rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Net::HTTPFatalError => e + Chef::Log.debug("#{@new_resource} cannot be downloaded from #{source}") + if source = sources.shift + Chef::Log.debug("#{@new_resource} trying to download from another mirror") + retry + else + raise e + end + end if matches_current_checksum?(raw_file) Chef::Log.debug "#{@new_resource} target and source checksums are the same - not updating" else description = [] - description << "copy file downloaded from #{raw_file_source} into #{@new_resource.path}" + description << "copy file downloaded from #{@new_resource.source} into #{@new_resource.path}" description << diff_current(raw_file.path) converge_by(description) do backup_new_resource @@ -90,55 +102,38 @@ class Chef end end - private - - # Given an array of source uris, iterate through them until one does not fail - def try_multiple_sources(sources) - sources = sources.dup - source = sources.shift - begin - uri = URI.parse(source) - raw_file = grab_file_from_uri(uri) - rescue ArgumentError => e - raise e - rescue => e - if e.is_a?(RestClient::Exception) - error = "Request returned #{e.message}" - else - error = e.to_s - end - Chef::Log.debug("#{@new_resource} cannot be downloaded from #{source}: #{error}") - if source = sources.shift - Chef::Log.debug("#{@new_resource} trying to download from another mirror") - retry - else - raise e - end - end - if uri.userinfo - uri.password = "********" + def source_file(source, current_checksum, &block) + if absolute_uri?(source) + fetch_from_uri(source, &block) + elsif !Chef::Config[:solo] + fetch_from_chef_server(source, current_checksum, &block) + else + fetch_from_local_cookbook(source, &block) end - return raw_file, uri.to_s end - # Given a source uri, return a Tempfile, or a File that acts like a Tempfile (close! method) - def grab_file_from_uri(uri) - if URI::HTTP === uri - #HTTP or HTTPS - raw_file = RestClient::Request.execute(:method => :get, :url => uri.to_s, :raw_response => true).file - elsif URI::FTP === uri - #FTP - raw_file = FTP::fetch(uri, @new_resource.ftp_active_mode) - elsif uri.scheme == "file" - #local/network file - raw_file = ::File.new(uri.path, "r") - def raw_file.close! - self.close - end - else - raise ArgumentError, "Invalid uri. Only http(s), ftp, and file are currently supported" + def http_client_opts(source) + 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 @new_resource.path =~ /gz$/ or source =~ /gz$/ + opts[:disable_gzip] = true end - raw_file + opts + end + + private + + def absolute_uri?(source) + URI.parse(source).absolute? + rescue URI::InvalidURIError + false end end diff --git a/lib/chef/provider/remote_file/ftp.rb b/lib/chef/provider/remote_file/ftp.rb deleted file mode 100644 index 9efc4ca08e..0000000000 --- a/lib/chef/provider/remote_file/ftp.rb +++ /dev/null @@ -1,95 +0,0 @@ -# -# Author:: Jesse Campbell (<hikeit@gmail.com>) -# Copyright:: Copyright (c) 2013 Jesse Campbell -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'uri' -require 'tempfile' -require 'net/ftp' -require 'chef/provider/remote_file' - -class Chef - class Provider - class RemoteFile - class FTP - - # Fetches the file at uri using Net::FTP, returning a Tempfile - def self.fetch(uri, ftp_active_mode) - self.new(uri, ftp_active_mode).fetch() - end - - # Parse the uri into instance variables - def initialize(uri, ftp_active_mode) - @directories, @filename = parse_path(uri.path) - @typecode = uri.typecode - # Only support ascii and binary types - if @typecode && /\A[ai]\z/ !~ @typecode - raise ArgumentError, "invalid typecode: #{@typecode.inspect}" - end - @ftp_active_mode = ftp_active_mode - @hostname = uri.host - @port = uri.port - if uri.userinfo - @user = URI.unescape(uri.user) - @pass = URI.unescape(uri.password) - else - @user = 'anonymous' - @pass = nil - end - end - - # Fetches using Net::FTP, returns a Tempfile with the content - def fetch() - tempfile = Tempfile.new(@filename) - - # The access sequence is defined by RFC 1738 - ftp = Net::FTP.new - ftp.connect(@hostname, @port) - ftp.passive = !@ftp_active_mode - ftp.login(@user, @pass) - @directories.each do |cwd| - ftp.voidcmd("CWD #{cwd}") - end - if @typecode - ftp.voidcmd("TYPE #{@typecode.upcase}") - end - ftp.getbinaryfile(@filename, tempfile.path) - ftp.close - - tempfile - end - - private - - def parse_path(path) - path = path.sub(%r{\A/}, '%2F') # re-encode the beginning slash because uri library decodes it. - directories = path.split(%r{/}, -1) - directories.each {|d| - d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") } - } - unless filename = directories.pop - raise ArgumentError, "no filename: #{path.inspect}" - end - if filename.length == 0 || filename.end_with?( "/" ) - raise ArgumentError, "no filename: #{path.inspect}" - end - return directories, filename - end - - end - end - end -end diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index 3a40c542ec..ae95632eaa 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -101,7 +101,5 @@ require 'chef/provider/mount/windows' require 'chef/provider/deploy/revision' require 'chef/provider/deploy/timestamped' -require 'chef/provider/remote_file/ftp' - require "chef/provider/lwrp_base" require 'chef/provider/registry_key' diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb index 524e00186b..2798cba3f2 100644 --- a/lib/chef/resource/remote_file.rb +++ b/lib/chef/resource/remote_file.rb @@ -32,8 +32,7 @@ class Chef super @resource_name = :remote_file @action = "create" - @source = [] - @ftp_active_mode = false + @source = nil @provider = Chef::Provider::RemoteFile end @@ -55,14 +54,6 @@ class Chef ) end - def ftp_active_mode(args=nil) - set_or_return( - :ftp_active_mode, - args, - :kind_of => [ TrueClass, FalseClass ] - ) - end - def after_created validate_source(@source) end diff --git a/spec/data/remote_file/nyan_cat.png.gz b/spec/data/remote_file/nyan_cat.png.gz Binary files differdeleted file mode 100644 index efa9d4427a..0000000000 --- a/spec/data/remote_file/nyan_cat.png.gz +++ /dev/null diff --git a/spec/functional/resource/remote_file_spec.rb b/spec/functional/resource/remote_file_spec.rb index fbb921d48c..57a5321ea2 100644 --- a/spec/functional/resource/remote_file_spec.rb +++ b/spec/functional/resource/remote_file_spec.rb @@ -23,6 +23,14 @@ describe Chef::Resource::RemoteFile do include_context Chef::Resource::File let(:file_base) { "remote_file_spec" } + let(:source) { 'http://localhost:9000/nyan_cat.png' } + let(:expected_content) do + content = File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'), "rb") do |f| + f.read + end + content.force_encoding(Encoding::BINARY) if content.respond_to?(:force_encoding) + content + end def create_resource node = Chef::Node.new @@ -63,44 +71,13 @@ describe Chef::Resource::RemoteFile do f.read end } - @api.get("/nyan_cat.png.gz", 200, nil, { 'Content-Type' => 'application/gzip', 'Content-Encoding' => 'gzip' } ) { - File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png.gz'), "rb") do |f| - f.read - end - } end after(:all) do @server.stop end - context "when using normal encoding" do - let(:source) { 'http://localhost:9000/nyan_cat.png' } - let(:expected_content) do - content = File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'), "rb") do |f| - f.read - end - content.force_encoding(Encoding::BINARY) if content.respond_to?(:force_encoding) - content - end - - it_behaves_like "a file resource" + it_behaves_like "a file resource" - it_behaves_like "a securable resource with reporting" - end - - context "when using gzip encoding" do - let(:source) { 'http://localhost:9000/nyan_cat.png.gz' } - let(:expected_content) do - content = File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png.gz'), "rb") do |f| - f.read - end - content.force_encoding(Encoding::BINARY) if content.respond_to?(:force_encoding) - content - end - - it_behaves_like "a file resource" - - it_behaves_like "a securable resource with reporting" - end + it_behaves_like "a securable resource with reporting" end diff --git a/spec/tiny_server.rb b/spec/tiny_server.rb index eb5f5c0fc0..9eecf13cec 100644 --- a/spec/tiny_server.rb +++ b/spec/tiny_server.rb @@ -127,20 +127,20 @@ module TinyServer @routes = {GET => [], PUT => [], POST => [], DELETE => []} end - def get(path, response_code, data=nil, headers=nil, &block) - @routes[GET] << Route.new(path, Response.new(response_code, data, headers, &block)) + def get(path, response_code, data=nil, &block) + @routes[GET] << Route.new(path, Response.new(response_code,data, &block)) end - def put(path, response_code, data=nil, headers=nil, &block) - @routes[PUT] << Route.new(path, Response.new(response_code, data, headers, &block)) + def put(path, response_code, data=nil, &block) + @routes[PUT] << Route.new(path, Response.new(response_code,data, &block)) end - def post(path, response_code, data=nil, headers=nil, &block) - @routes[POST] << Route.new(path, Response.new(response_code, data, headers, &block)) + def post(path, response_code, data=nil, &block) + @routes[POST] << Route.new(path, Response.new(response_code,data, &block)) end - def delete(path, response_code, data=nil, headers=nil, &block) - @routes[DELETE] << Route.new(path, Response.new(response_code, data, headers, &block)) + def delete(path, response_code, data=nil, &block) + @routes[DELETE] << Route.new(path, Response.new(response_code,data, &block)) end def call(env) @@ -183,15 +183,14 @@ module TinyServer class Response HEADERS = {'Content-Type' => 'application/json'} - def initialize(response_code=200, data=nil, headers=nil, &block) + def initialize(response_code=200,data=nil, &block) @response_code, @data = response_code, data - @response_headers = headers ? HEADERS.merge(headers) : HEADERS @block = block_given? ? block : nil end def call data = @data || @block.call - [@response_code, @response_headers, Array(data)] + [@response_code, HEADERS, Array(data)] end def to_s diff --git a/spec/unit/provider/remote_file/ftp_spec.rb b/spec/unit/provider/remote_file/ftp_spec.rb deleted file mode 100644 index 03ef9424dd..0000000000 --- a/spec/unit/provider/remote_file/ftp_spec.rb +++ /dev/null @@ -1,117 +0,0 @@ -# -# Author:: Jesse Campbell (<hikeit@gmail.com>) -# Copyright:: Copyright (c) 2013 Jesse Campbell -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'spec_helper' - -describe Chef::Provider::RemoteFile::FTP, "fetch" do - before(:each) do - @ftp = mock(Net::FTP, { }) - Net::FTP.stub!(:new).and_return(@ftp) - @ftp.stub!(:connect) - @ftp.stub!(:login) - @ftp.stub!(:voidcmd) - @ftp.stub!(:getbinaryfile) - @ftp.stub!(:close) - @ftp.stub!(:passive=) - @tempfile = Tempfile.new("chef-rspec-ftp_spec-line#{__LINE__}--") - Tempfile.stub!(:new).and_return(@tempfile) - @uri = URI.parse("ftp://opscode.com/seattle.txt") - end - - describe "when parsing the uri" do - it "throws an argument exception when no path is given" do - @uri.path = "" - lambda { Chef::Provider::RemoteFile::FTP.new(@uri, false) }.should raise_error(ArgumentError) - end - - it "throws an argument exception when only a / is given" do - @uri.path = "/" - lambda { Chef::Provider::RemoteFile::FTP.new(@uri, false) }.should raise_error(ArgumentError) - end - - it "throws an argument exception when no filename is given" do - @uri.path = "/the/whole/path/" - lambda { Chef::Provider::RemoteFile::FTP.new(@uri, false) }.should raise_error(ArgumentError) - end - - it "throws an argument exception when the typecode is invalid" do - @uri.typecode = "d" - lambda { Chef::Provider::RemoteFile::FTP.new(@uri, false) }.should raise_error(ArgumentError) - end - end - - describe "when connecting to the remote" do - it "should connect to the host from the uri on the default port 21" do - @ftp.should_receive(:connect).with("opscode.com", 21) - Chef::Provider::RemoteFile::FTP.fetch(@uri, false).close! - end - - it "should connect on an alternate port when one is provided" do - @ftp.should_receive(:connect).with("opscode.com", 8021) - Chef::Provider::RemoteFile::FTP.fetch(URI.parse("ftp://opscode.com:8021/seattle.txt"), false).close! - end - - it "should set passive true when ftp_active_mode is false" do - @ftp.should_receive(:passive=).with(true) - Chef::Provider::RemoteFile::FTP.fetch(@uri, false).close! - end - - it "should set passive false when ftp_active_mode is false" do - @ftp.should_receive(:passive=).with(false) - Chef::Provider::RemoteFile::FTP.fetch(@uri, true).close! - end - - it "should use anonymous ftp when no userinfo is provided" do - @ftp.should_receive(:login).with("anonymous", nil) - Chef::Provider::RemoteFile::FTP.fetch(@uri, false).close! - end - - it "should use authenticated ftp when userinfo is provided" do - @ftp.should_receive(:login).with("the_user", "the_password") - Chef::Provider::RemoteFile::FTP.fetch(URI.parse("ftp://the_user:the_password@opscode.com/seattle.txt"), false).close! - end - - it "should accept ascii for the typecode" do - @uri.typecode = "a" - @ftp.should_receive(:voidcmd).with("TYPE A").once - Chef::Provider::RemoteFile::FTP.fetch(@uri, false).close! - end - - it "should accept image for the typecode" do - @uri.typecode = "i" - @ftp.should_receive(:voidcmd).with("TYPE I").once - Chef::Provider::RemoteFile::FTP.fetch(@uri, false).close! - end - - it "should fetch the file from the correct path" do - @ftp.should_receive(:voidcmd).with("CWD the").once - @ftp.should_receive(:voidcmd).with("CWD whole").once - @ftp.should_receive(:voidcmd).with("CWD path").once - @ftp.should_receive(:getbinaryfile).with("seattle.txt", @tempfile.path) - Chef::Provider::RemoteFile::FTP.fetch(URI.parse("ftp://opscode.com/the/whole/path/seattle.txt"), false).close! - end - end - - describe "when it finishes downloading" do - it "should return a tempfile" do - ftpfile = Chef::Provider::RemoteFile::FTP.fetch(@uri, false) - ftpfile.should equal @tempfile - ftpfile.close! - end - end -end diff --git a/spec/unit/provider/remote_file_spec.rb b/spec/unit/provider/remote_file_spec.rb index 149f0462c3..78d7e77121 100644 --- a/spec/unit/provider/remote_file_spec.rb +++ b/spec/unit/provider/remote_file_spec.rb @@ -46,9 +46,11 @@ describe Chef::Provider::RemoteFile, "action_create" do describe "when fetching the file from the remote" do before(:each) do @tempfile = Tempfile.new("chef-rspec-remote_file_spec-line#{__LINE__}--") - @rawresp = RestClient::RawResponse.new(@tempfile, nil, 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!(:create_url) { |url| url } @resource.cookbook_name = "monkey" @provider.stub!(:checksum).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") @@ -79,19 +81,19 @@ describe Chef::Provider::RemoteFile, "action_create" do shared_examples_for "source specified with multiple URIs" 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", :raw_response => true).once.and_raise(SocketError) - RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://bar", :raw_response => true).once.and_return(@rawresp) + @rest.should_receive(:streaming_request).with("http://foo", {}).once.and_raise(SocketError) + @rest.should_receive(:streaming_request).with("http://bar", {}).once.and_return(@tempfile) @provider.run_action(:create) end it "should raise an exception when all the URIs fail" do - RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://foo", :raw_response => true).once.and_raise(SocketError) - RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://bar", :raw_response => true).once.and_raise(SocketError) + @rest.should_receive(:streaming_request).with("http://foo", {}).once.and_raise(SocketError) + @rest.should_receive(:streaming_request).with("http://bar", {}).once.and_raise(SocketError) lambda { @provider.run_action(:create) }.should raise_error(SocketError) end 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) end @@ -121,7 +123,7 @@ describe Chef::Provider::RemoteFile, "action_create" do end it "does not download the file" do - RestClient::Request.should_not_receive(:execute).with("http://opscode.com/seattle.txt").and_return(@tempfile) + @rest.should_not_receive(:fetch).with("http://opscode.com/seattle.txt").and_return(@tempfile) @provider.run_action(:create) end @@ -138,7 +140,7 @@ describe Chef::Provider::RemoteFile, "action_create" do end it "should not download the file if the checksum is a partial match from the beginning" do - @rawresp.should_not_receive(:fetch).with("http://opscode.com/seattle.txt").and_return(@tempfile) + @rest.should_not_receive(:fetch).with("http://opscode.com/seattle.txt").and_return(@tempfile) @provider.run_action(:create) end @@ -152,7 +154,7 @@ describe Chef::Provider::RemoteFile, "action_create" do describe "and the existing file doesn't match the given checksum" do it "downloads the file" do @resource.checksum("this hash doesn't match") - RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://opscode.com/seattle.txt", :raw_response => true).and_return(@rawresp) + @rest.should_receive(:streaming_request).with("http://opscode.com/seattle.txt", {}).and_return(@tempfile) @provider.stub!(:update_new_file_state) @provider.run_action(:create) end @@ -160,7 +162,7 @@ describe Chef::Provider::RemoteFile, "action_create" do it "does not consider the checksum a match if the matching string is offset" do # i.e., the existing file is "0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa" @resource.checksum("fd012fd") - RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://opscode.com/seattle.txt", :raw_response => true).and_return(@rawresp) + @rest.should_receive(:streaming_request).with("http://opscode.com/seattle.txt", {}).and_return(@tempfile) @provider.stub!(:update_new_file_state) @provider.run_action(:create) end @@ -171,7 +173,7 @@ describe Chef::Provider::RemoteFile, "action_create" do describe "and the resource doesn't specify a checksum" do it "should download the file from the remote URL" do @resource.checksum(nil) - RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://opscode.com/seattle.txt", :raw_response => true).and_return(@rawresp) + @rest.should_receive(:streaming_request).with("http://opscode.com/seattle.txt", {}).and_return(@tempfile) @provider.run_action(:create) end end @@ -188,7 +190,7 @@ describe Chef::Provider::RemoteFile, "action_create" do 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", :raw_response => true).and_return(@rawresp) + Chef::REST.should_receive(:new).with("http://opscode.com/seattle.txt", nil, nil, :disable_gzip => true).and_return(@rest) end it "disables gzip in the http client" do @@ -200,7 +202,7 @@ describe Chef::Provider::RemoteFile, "action_create" do context "and the source appears to be a tarball" do before do @resource.source("http://example.com/tarball.tgz") - RestClient::Request.should_receive(:execute).with(:method => :get, :url => "http://example.com/tarball.tgz", :raw_response => true).and_return(@rawresp) + Chef::REST.should_receive(:new).with("http://example.com/tarball.tgz", nil, nil, :disable_gzip => true).and_return(@rest) end it "disables gzip in the http client" do @@ -208,45 +210,17 @@ describe Chef::Provider::RemoteFile, "action_create" do end end - context "and the uri scheme is ftp" do - before do - @resource.source("ftp://opscode.com/seattle.txt") - end - - it "should fetch with ftp in passive mode" do - Chef::Provider::RemoteFile::FTP.should_receive(:fetch).with(URI.parse("ftp://opscode.com/seattle.txt"), false).and_return(@tempfile) - @provider.run_action(:create) - end - - it "should fetch with ftp in active mode" do - @resource.ftp_active_mode true - Chef::Provider::RemoteFile::FTP.should_receive(:fetch).with(URI.parse("ftp://opscode.com/seattle.txt"), true).and_return(@tempfile) - @provider.run_action(:create) - end - end - - context "and the uri scheme is file" do - before do - @resource.source("file:///nyan_cat.png") - end - - it "should load the local file" do - File.should_receive(:new).with("/nyan_cat.png", "r").and_return(File.open(File.join(CHEF_SPEC_DATA, "remote_file", "nyan_cat.png"), "r")) - @provider.run_action(:create) - end - end - it "should raise an exception if it's any other kind of retriable response than 304" do r = Net::HTTPMovedPermanently.new("one", "two", "three") 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) end it "should raise an exception if anything else happens" do r = Net::HTTPBadRequest.new("one", "two", "three") 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) end @@ -342,6 +316,9 @@ describe Chef::Provider::RemoteFile, "action_create" do @provider.should_receive(:set_all_access_controls).and_return(true) @provider.run_action(:create) end + + end + end end diff --git a/spec/unit/resource/remote_file_spec.rb b/spec/unit/resource/remote_file_spec.rb index 064c97fc27..d91f80d1a7 100644 --- a/spec/unit/resource/remote_file_spec.rb +++ b/spec/unit/resource/remote_file_spec.rb @@ -42,7 +42,7 @@ describe Chef::Resource::RemoteFile do describe "source" do it "does not have a default value for 'source'" do - @resource.source.should eql([]) + @resource.source.should be_nil end it "should accept a URI for the remote file source" do @@ -64,7 +64,7 @@ describe Chef::Resource::RemoteFile do lambda { @resource.source("not-a-uri") }.should raise_error(Chef::Exceptions::InvalidRemoteFileURI) end - it "should raise an exception when source is an empty array" do + it "should raise and exception when source is an empty array" do lambda { @resource.source([]) }.should raise_error(ArgumentError) end @@ -80,18 +80,7 @@ describe Chef::Resource::RemoteFile do @resource.checksum.should == nil end end - - describe "ftp_active_mode" do - it "should accept a boolean for the ftp_active_mode object" do - @resource.ftp_active_mode true - @resource.ftp_active_mode.should be_true - end - - it "should default to false" do - @resource.ftp_active_mode.should be_false - end - end - + describe "when it has group, mode, owner, source, and checksum" do before do if Chef::Platform.windows? @@ -130,4 +119,5 @@ describe Chef::Resource::RemoteFile do end end end + end |