diff options
author | Lamont Granquist <lamont@opscode.com> | 2013-03-20 15:13:05 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@opscode.com> | 2013-03-20 15:13:05 -0700 |
commit | 7655abea85be5731aa872489ee9561c69f7be0be (patch) | |
tree | a30da1e7a2c3a5d940d9fc3934d96f4d3b557971 /lib/chef/provider/remote_file/content.rb | |
parent | de0452180a1464d4a74992e0f9a83733ff4d8da2 (diff) | |
download | chef-7655abea85be5731aa872489ee9561c69f7be0be.tar.gz |
locate objects closer to their primary concerns
Diffstat (limited to 'lib/chef/provider/remote_file/content.rb')
-rw-r--r-- | lib/chef/provider/remote_file/content.rb | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/chef/provider/remote_file/content.rb b/lib/chef/provider/remote_file/content.rb new file mode 100644 index 0000000000..fbd7a6bb24 --- /dev/null +++ b/lib/chef/provider/remote_file/content.rb @@ -0,0 +1,110 @@ +# +# Author:: Jesse Campbell (<hikeit@gmail.com>) +# Author:: Lamont Granquist (<lamont@opscode.com>) +# Copyright:: Copyright (c) 2013 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 'rest_client' +require 'uri' +require 'tempfile' +require 'chef/provider/file_content_base' + +class Chef + class Provider + class RemoteFile + class Content < Chef::Provider::FileContentBase + + attr_reader :raw_file_source + + private + + def file_for_provider + Chef::Log.debug("#{@new_resource} checking for changes") + + if current_resource_matches_target_checksum? + 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) + end + raw_file + 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 SocketError, Errno::ECONNREFUSED, Errno::ENOENT, Errno::EACCES, Timeout::Error, Net::HTTPFatalError, Net::FTPError => e + Chef::Log.warn("#{@new_resource} cannot be downloaded from #{source}: #{e.to_s}") + if source = sources.shift + Chef::Log.info("#{@new_resource} trying to download from another mirror") + retry + else + raise e + end + end + if uri.userinfo + uri.password = "********" + 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_modified_since = @new_resource.last_modified + if_none_match = @new_resource.etag + uri_dup = uri.dup + if uri_dup.userinfo + uri_dup.password = "********" + end + if uri_dup.to_s == @current_resource.source[0] + if_modified_since ||= @current_resource.last_modified + if_none_match ||= @current_resource.etag + end + if URI::HTTP === uri + #HTTP or HTTPS + raw_file, mtime, etag = Chef::Provider::RemoteFile::HTTP.fetch(uri, if_modified_since, if_none_match) + elsif URI::FTP === uri + #FTP + raw_file, mtime = Chef::Provider::RemoteFile::FTP.fetch(uri, @new_resource.ftp_active_mode, if_modified_since) + etag = nil + elsif uri.scheme == "file" + #local/network file + raw_file, mtime = Chef::Provider::RemoteFile::LocalFile.fetch(uri, if_modified_since) + etag = nil + else + raise ArgumentError, "Invalid uri. Only http(s), ftp, and file are currently supported" + end + unless raw_file.nil? + @new_resource.etag etag unless @new_resource.etag + @new_resource.last_modified mtime unless @new_resource.last_modified + end + return raw_file + end + + def current_resource_matches_target_checksum? + @new_resource.checksum && @current_resource.checksum && @current_resource.checksum =~ /^#{Regexp.escape(@new_resource.checksum)}/ + end + + end + end + end +end |