diff options
author | Jesse Campbell <hikeit@gmail.com> | 2013-02-05 11:07:58 -0500 |
---|---|---|
committer | Bryan McLellan <btm@opscode.com> | 2013-02-26 11:11:43 -0800 |
commit | 7a2975342ea3e51d0875c125f0061d52bd559d6a (patch) | |
tree | 48873938865cb29581ab82bc403c3e2ab6cf230a | |
parent | ef9b1a83df9055ecf4c1e93632669f817f52e689 (diff) | |
download | chef-7a2975342ea3e51d0875c125f0061d52bd559d6a.tar.gz |
pull ftp functionality out of remote_file.rb, move to remote_file/ftp.rb
add file://
-rw-r--r-- | lib/chef/provider/remote_file.rb | 77 | ||||
-rw-r--r-- | lib/chef/provider/remote_file/ftp.rb | 82 |
2 files changed, 101 insertions, 58 deletions
diff --git a/lib/chef/provider/remote_file.rb b/lib/chef/provider/remote_file.rb index cf4d129bea..27ee95acd3 100644 --- a/lib/chef/provider/remote_file.rb +++ b/lib/chef/provider/remote_file.rb @@ -19,10 +19,9 @@ require 'chef/provider/file' require 'rest_client' +require 'chef/provider/remote_file/ftp' require 'uri' require 'tempfile' -require 'net/https' -require 'net/ftp' class Chef class Provider @@ -48,11 +47,16 @@ class Chef if URI::HTTP === uri #HTTP or HTTPS raw_file = RestClient::Request.execute(:method => :get, :url => source, :raw_response => true).file - else + elsif URI::FTP === uri #FTP - raw_file = ftp_fetch(uri) + raw_file = FTP::fetch(uri, @new_resource.ftp_active_mode) + elsif uri.scheme == "file" + #local/network file + raw_file = ::File.new(uri.path, "r") + else + raise ArgumentError, "Invalid uri. Only http(s), ftp, and file are currently supported" end - rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Net::HTTPFatalError => e + rescue => 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") @@ -71,12 +75,20 @@ class Chef backup_new_resource FileUtils.cp raw_file.path, @new_resource.path Chef::Log.info "#{@new_resource} updated" - raw_file.close! + if raw_file.is_a? Tempfile + raw_file.close! + else + raw_file.close + end end # whyrun mode cleanup - the temp file will never be used, # so close/unlink it here. if whyrun_mode? - raw_file.close! + if raw_file.is_a? Tempfile + raw_file.close! + else + raw_file.close + end end end end @@ -109,57 +121,6 @@ class Chef backup @new_resource.path end end - - private - - def ftp_fetch(uri) - # Shamelessly stolen from open-uri - # Fetches the file using Net::FTP, returning a Tempfile - path = uri.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: #{uri.inspect}" - end - directories.each {|d| - if /[\r\n]/ =~ d - raise ArgumentError, "invalid directory: #{d.inspect}" - end - } - if /[\r\n]/ =~ filename - raise ArgumentError, "invalid filename: #{filename.inspect}" - end - typecode = uri.typecode - if typecode && /\A[aid]\z/ !~ typecode - raise ArgumentError, "invalid typecode: #{typecode.inspect}" - end - - tempfile = Tempfile.new(filename) - - # The access sequence is defined by RFC 1738 - ftp = Net::FTP.new - ftp.connect(uri.hostname, uri.port) - ftp.passive = true if !@new_resource.ftp_active_mode - # todo: extract user/passwd from .netrc. - user = 'anonymous' - passwd = nil - user, passwd = uri.userinfo.split(/:/) if uri.userinfo - ftp.login(user, passwd) - directories.each {|cwd| - ftp.voidcmd("CWD #{cwd}") - } - if typecode - # xxx: typecode D is not handled. - ftp.voidcmd("TYPE #{typecode.upcase}") - end - ftp.getbinaryfile(filename, tempfile.path) - ftp.close - - tempfile - end end end end diff --git a/lib/chef/provider/remote_file/ftp.rb b/lib/chef/provider/remote_file/ftp.rb new file mode 100644 index 0000000000..9973822223 --- /dev/null +++ b/lib/chef/provider/remote_file/ftp.rb @@ -0,0 +1,82 @@ +# +# Author:: Jesse Campbell (<hikeit@gmail.com>) +# Copyright:: Copyright (c) 2008 Opscode, Inc. +# 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' + +class Chef + class Provider + class RemoteFile < Chef::Provider::File + class FTP + + # Fetches the file at uri using Net::FTP, returning a Tempfile + # Parts shamelessly stolen from open-uri + def self.fetch(uri, ftp_active_mode) + path = uri.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: #{uri.inspect}" + end + directories.each {|d| + if /[\r\n]/ =~ d + raise ArgumentError, "invalid directory: #{d.inspect}" + end + } + if /[\r\n]/ =~ filename + raise ArgumentError, "invalid filename: #{filename.inspect}" + end + typecode = uri.typecode + if typecode && /\A[aid]\z/ !~ typecode + raise ArgumentError, "invalid typecode: #{typecode.inspect}" + end + + tempfile = Tempfile.new(filename) + + # The access sequence is defined by RFC 1738 + ftp = Net::FTP.new + ftp.connect(uri.hostname, uri.port) + ftp.passive = true if !ftp_active_mode + # todo: extract user/passwd from .netrc. + user = 'anonymous' + passwd = nil + if uri.userinfo + user = URI.unescape(uri.user) + passwd = URI.unescape(uri.password) + end + ftp.login(user, passwd) + directories.each {|cwd| + ftp.voidcmd("CWD #{cwd}") + } + if typecode + # xxx: typecode D is not handled. + ftp.voidcmd("TYPE #{typecode.upcase}") + end + ftp.getbinaryfile(filename, tempfile.path) + ftp.close + + tempfile + end + end + end + end +end |