summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJesse Campbell <hikeit@gmail.com>2013-02-28 11:54:31 -0500
committerJesse Campbell <hikeit@gmail.com>2013-02-28 11:54:31 -0500
commit6a8476ef8edb618e6a0fc7169e81aa900dd8260f (patch)
treef88fdca145afaadc27a05ce081cdd6da42fa2c61 /lib
parent4f01be11f89c1a340cb97c227148795c870298cd (diff)
downloadchef-6a8476ef8edb618e6a0fc7169e81aa900dd8260f.tar.gz
break up into separate classes for each supported scheme
Diffstat (limited to 'lib')
-rw-r--r--lib/chef/provider/remote_file.rb74
-rw-r--r--lib/chef/provider/remote_file/ftp.rb20
-rw-r--r--lib/chef/provider/remote_file/http.rb76
-rw-r--r--lib/chef/provider/remote_file/local_file.rb52
-rw-r--r--lib/chef/providers.rb2
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'