diff options
author | Jesse Campbell <hikeit@gmail.com> | 2013-02-28 11:54:31 -0500 |
---|---|---|
committer | Jesse Campbell <hikeit@gmail.com> | 2013-02-28 11:54:31 -0500 |
commit | 6a8476ef8edb618e6a0fc7169e81aa900dd8260f (patch) | |
tree | f88fdca145afaadc27a05ce081cdd6da42fa2c61 /lib | |
parent | 4f01be11f89c1a340cb97c227148795c870298cd (diff) | |
download | chef-6a8476ef8edb618e6a0fc7169e81aa900dd8260f.tar.gz |
break up into separate classes for each supported scheme
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/provider/remote_file.rb | 74 | ||||
-rw-r--r-- | lib/chef/provider/remote_file/ftp.rb | 20 | ||||
-rw-r--r-- | lib/chef/provider/remote_file/http.rb | 76 | ||||
-rw-r--r-- | lib/chef/provider/remote_file/local_file.rb | 52 | ||||
-rw-r--r-- | lib/chef/providers.rb | 2 |
5 files changed, 163 insertions, 61 deletions
diff --git a/lib/chef/provider/remote_file.rb b/lib/chef/provider/remote_file.rb index d7a009475d..553e700b16 100644 --- a/lib/chef/provider/remote_file.rb +++ b/lib/chef/provider/remote_file.rb @@ -30,13 +30,13 @@ class Chef def load_current_resource @current_resource = Chef::Resource::RemoteFile.new(@new_resource.name) + super fileinfo = load_fileinfo - if fileinfo["src"] + if fileinfo && fileinfo["checksum"] == @current_resource.checksum @current_resource.etag fileinfo["etag"] @current_resource.last_modified fileinfo["last_modified"] @current_resource.source fileinfo["src"] end - super end def action_create @@ -51,6 +51,7 @@ class Chef Chef::Log.info("#{@new_resource} matched #{raw_file_source}, not updating") elsif matches_current_checksum?(raw_file) Chef::Log.info("#{@new_resource} downloaded from #{raw_file_source}, checksums match, not updating") + raw_file.close! else Chef::Log.info("#{@new_resource} downloaded from #{raw_file_source}") description = [] @@ -61,6 +62,7 @@ class Chef FileUtils.cp raw_file.path, @new_resource.path Chef::Log.info "#{@new_resource} updated" raw_file.close! + save_fileinfo(raw_file_source) end # whyrun mode cleanup - the temp file will never be used, # so close/unlink it here. @@ -79,9 +81,9 @@ class Chef def matches_current_checksum?(candidate_file) Chef::Log.debug "#{@new_resource} checking for file existence of #{@new_resource.path}" + @new_resource.checksum(checksum(candidate_file.path)) if ::File.exists?(@new_resource.path) Chef::Log.debug "#{@new_resource} file exists at #{@new_resource.path}" - @new_resource.checksum(checksum(candidate_file.path)) Chef::Log.debug "#{@new_resource} target checksum: #{@current_resource.checksum}" Chef::Log.debug "#{@new_resource} source checksum: #{@new_resource.checksum}" @@ -134,84 +136,60 @@ class Chef def grab_file_from_uri(uri) if_modified_since = @new_resource.last_modified if_none_match = @new_resource.etag - if uri == @current_resource.source[0] + if uri.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, last_modified, etag, target_matched = http_fetch(uri, if_modified_since, if_none_match) + raw_file, mtime, etag, target_matched = HTTP::fetch(uri, proxy_uri(uri), if_modified_since, if_none_match) elsif URI::FTP === uri #FTP - raw_file, last_modified = FTP::fetch_if_modified(uri, @new_resource.ftp_active_mode, if_modified_since) + raw_file, mtime, target_matched = FTP::fetch(uri, proxy_uri(uri), @new_resource.ftp_active_mode, if_modified_since) etag = nil - target_matched = last_modified && if_modified_since && last_modified.to_i <= if_modified_since.to_i elsif uri.scheme == "file" #local/network file - last_modified = ::File.mtime(uri.path) + raw_file, mtime, target_matched = LocalFile::fetch(uri, if_modified_since) etag = nil - raw_file = ::File.new(uri.path, "r") - def raw_file.close! - self.close - end - target_mathed = last_modified && if_modified_since && last_modified.to_i <= if_modified_since.to_i else raise ArgumentError, "Invalid uri. Only http(s), ftp, and file are currently supported" end unless target_matched @new_resource.etag etag unless @new_resource.etag - @new_resource.last_modified last_modified unless @new_resource.last_modified - save_fileinfo(uri) + @new_resource.last_modified mtime unless @new_resource.last_modified end return raw_file, target_matched end - def http_fetch(uri, if_modified_since, if_none_match) - last_modified = nil - etag = nil - target_matched = false - begin - headers = Hash.new - if if_none_match - headers[:if_none_match] = "\"#{if_none_match}\"" - elsif if_modified_since - headers[:if_modified_since] = if_modified_since.strftime("%a, %d %b %Y %H:%M:%S %Z") - end - rest = RestClient::Request.execute(:method => :get, :url => uri.to_s, :headers => headers, :raw_response => true) - raw_file = rest.file - if rest.headers.include?(:last_modified) - last_modified = Time.parse(rest.headers[:last_modified]) - end - if rest.headers.include?(:etag) - etag = rest.headers[:etag] - end - rescue RestClient::Exception => e - if e.http_code == 304 - target_matched = true - else - raise e - end + #adapted from buildr/lib/buildr/core/transports.rb via chef/rest/rest_client.rb + def proxy_uri(uri) + proxy = Chef::Config["#{uri.scheme}_proxy"] + proxy = URI.parse(proxy) if String === proxy + if Chef::Config["#{uri.scheme}_proxy_user"] + proxy.user = Chef::Config["#{uri.scheme}_proxy_user"] + end + if Chef::Config["#{uri.scheme}_proxy_pass"] + proxy.password = Chef::Config["#{uri.scheme}_proxy_pass"] end - return raw_file, last_modified, etag, target_matched + excludes = Chef::Config[:no_proxy].to_s.split(/\s*,\s*/).compact + excludes = excludes.map { |exclude| exclude =~ /:\d+$/ ? exclude : "#{exclude}:*" } + return proxy unless excludes.any? { |exclude| File.fnmatch(exclude, "#{host}:#{port}") } end def load_fileinfo begin Chef::JSONCompat.from_json(Chef::FileCache.load("remote_file/#{new_resource.name}")) rescue Chef::Exceptions::FileNotFound - cache = Hash.new - cache["etag"] = nil - cache["last_modified"] = nil - cache["src"] = nil - cache + nil end end - def save_fileinfo(uri) + def save_fileinfo(source) cache = Hash.new cache["etag"] = @new_resource.etag cache["last_modified"] = @new_resource.last_modified - cache["src"] = uri + cache["src"] = source + cache["checksum"] = @new_resource.checksum Chef::FileCache.store("remote_file/#{new_resource.name}", cache.to_json) end end diff --git a/lib/chef/provider/remote_file/ftp.rb b/lib/chef/provider/remote_file/ftp.rb index b0e28a4de8..8689d9d788 100644 --- a/lib/chef/provider/remote_file/ftp.rb +++ b/lib/chef/provider/remote_file/ftp.rb @@ -26,30 +26,24 @@ class Chef class RemoteFile class FTP - # Fetches the file at uri using Net::FTP, returning a Tempfile - def self.fetch(uri, ftp_active_mode) - ftp = self.new(uri, ftp_active_mode) - ftp.connect - tempfile = ftp.fetch - ftp.disconnect - tempfile - end - - def self.fetch_if_modified(uri, ftp_active_mode, last_modified) - ftp = self.new(uri, ftp_active_mode) + def self.fetch(uri, proxy_uri, ftp_active_mode, last_modified) + ftp = self.new(uri, proxy_uri, ftp_active_mode) ftp.connect mtime = ftp.mtime if mtime && last_modified && mtime.to_i <= last_modified.to_i tempfile = nil + target_matched = true else tempfile = ftp.fetch + target_matched = false end ftp.disconnect - return tempfile, mtime + return tempfile, mtime, target_matched end # Parse the uri into instance variables - def initialize(uri, ftp_active_mode) + def initialize(uri, proxy_uri, ftp_active_mode) + ENV[SOCKS_SERVER] = proxy_uri.to_s @directories, @filename = parse_path(uri.path) @typecode = uri.typecode # Only support ascii and binary types diff --git a/lib/chef/provider/remote_file/http.rb b/lib/chef/provider/remote_file/http.rb new file mode 100644 index 0000000000..8bf7238baa --- /dev/null +++ b/lib/chef/provider/remote_file/http.rb @@ -0,0 +1,76 @@ +# +# 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 'chef/provider/remote_file' + +class Chef + class Provider + class RemoteFile + class HTTP + + # Fetches the file at uri, returning a Tempfile-like File handle + def self.fetch(uri, proxy_uri, if_modified_since, if_none_match) + request = HTTP.new(uri, proxy_uri, if_modified_since, if_none_match) + request.execute + end + + # Parse the uri into instance variables + def initialize(uri, proxy_uri, if_modified_since, if_none_match) + RestClient.proxy = proxy_uri.to_s + @headers = Hash.new + if if_none_match + @headers[:if_none_match] = "\"#{if_none_match}\"" + elsif if_modified_since + @headers[:if_modified_since] = if_modified_since.strftime("%a, %d %b %Y %H:%M:%S %Z") + end + @uri = uri + end + + def execute + begin + rest = RestClient::Request.execute(:method => :get, :url => @uri.to_s, :headers => @headers, :raw_response => true) + raw_file = rest.file + target_matched = false + if rest.headers.include?(:last_modified) + mtime = Time.parse(rest.headers[:last_modified]) + elsif rest.headers.include?(:date) + mtime = Time.parse(rest.headers[:date]) + else + mtime = Time.now + end + if rest.headers.include?(:etag) + etag = rest.headers[:etag] + else + etag = nil + end + rescue RestClient::Exception => e + if e.http_code == 304 + target_matched = true + else + raise e + end + end + return raw_file, mtime, etag, target_matched + end + + end + end + end +end diff --git a/lib/chef/provider/remote_file/local_file.rb b/lib/chef/provider/remote_file/local_file.rb new file mode 100644 index 0000000000..b760eeea0c --- /dev/null +++ b/lib/chef/provider/remote_file/local_file.rb @@ -0,0 +1,52 @@ +# +# 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 'chef/provider/remote_file' + +class Chef + class Provider + class RemoteFile + class LocalFile < ::File + + # Fetches the file at uri, returning a Tempfile-like File handle + def self.fetch(uri, if_modified_since) + raw_file = LocalFile.new(uri.path) + mtime = raw_file.mtime + target_matched = mtime && if_modified_since && mtime.to_i <= if_modified_since.to_i + if target_matched + raw_file.close + raw_file = nil + end + return raw_file, mtime, target_matched + end + + def close! + close + end + + # Parse the uri into instance variables + def initialize(uri, mode="r") + super(uri.path, mode) + end + + end + end + end +end diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index fa48f79943..0c7aed61b8 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -100,6 +100,8 @@ require 'chef/provider/deploy/revision' require 'chef/provider/deploy/timestamped' require 'chef/provider/remote_file/ftp' +require 'chef/provider/remote_file/http' +require 'chef/provider/remote_file/local_file' require "chef/provider/lwrp_base" require 'chef/provider/registry_key' |