summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Kerry <jk185160@ncr.com>2016-03-23 21:34:46 -0400
committerJohn Kerry <jk185160@ncr.com>2016-03-23 21:36:47 -0400
commit360d506c9cdf0e94071f0a656eafbc7d2f302d9a (patch)
tree6a8dd80bf6ba0c456245805fb338e524f72fa584
parent8c8060ed20a6dd0a085a7484ce95a7d4967f407b (diff)
downloadchef-360d506c9cdf0e94071f0a656eafbc7d2f302d9a.tar.gz
Adding base implementation and the start of unit test coverage
-rw-r--r--lib/chef/provider/remote_file/fetcher.rb2
-rw-r--r--lib/chef/provider/remote_file/sftp.rb75
-rw-r--r--lib/chef/providers.rb1
-rw-r--r--spec/unit/provider/remote_file/sftp_spec.rb19
4 files changed, 96 insertions, 1 deletions
diff --git a/lib/chef/provider/remote_file/fetcher.rb b/lib/chef/provider/remote_file/fetcher.rb
index dad73cf17f..c138ee5d6b 100644
--- a/lib/chef/provider/remote_file/fetcher.rb
+++ b/lib/chef/provider/remote_file/fetcher.rb
@@ -31,6 +31,8 @@ class Chef
Chef::Provider::RemoteFile::HTTP.new(uri, new_resource, current_resource)
when "ftp"
Chef::Provider::RemoteFile::FTP.new(uri, new_resource, current_resource)
+ when "sftp"
+ Chef::Provider::RemoteFile::SFTP.net(uri, new_resource, current_resource)
when "file"
Chef::Provider::RemoteFile::LocalFile.new(uri, new_resource, current_resource)
else
diff --git a/lib/chef/provider/remote_file/sftp.rb b/lib/chef/provider/remote_file/sftp.rb
index 868ccb982c..4e2c0d2c9a 100644
--- a/lib/chef/provider/remote_file/sftp.rb
+++ b/lib/chef/provider/remote_file/sftp.rb
@@ -26,6 +26,81 @@ class Chef
class Provider
class RemoteFile
class SFTP
+
+ attr_reader :uri
+ attr_reader :new_resource
+ attr_reader :current_resource
+
+ def initialize(uri, new_resource, current_resource)
+ @uri = uri
+ @new_resource = new_resource
+ @current_resource = current_resource
+ validate_path!
+ end
+
+ def hostname
+ @uri.host
+ end
+
+ def user
+ if uri.userinfo
+ URI.unescape(uri.user)
+ else
+ 'anonymous'
+ end
+ end
+
+ def pass
+ if uri.userinfo
+ URI.unescape(uri.password)
+ else
+ nil
+ end
+ end
+
+ def filename
+ parse_path if @filename.nil?
+ @filename
+ end
+
+ def fetch
+ get
+ end
+
+ def sftp
+ @sftp ||= Net::SFTP.start(hostname, user, :password => pass)
+ end
+
+ private
+
+ def validate_path!
+ parse_path
+ end
+
+ # Fetches using Net::FTP, returns a Tempfile with the content
+ def get
+ tempfile = Chef::FileContentManagement::Tempfile.new(@new_resource).tempfile
+ sftp.download!(uri.path, tempfile.path)
+ tempfile.close if tempfile
+ tempfile
+ end
+
+ def parse_path
+ path = uri.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
+
+ @directories, @filename = directories, filename
+ end
+
end
end
end
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index 6fd67e0068..e5635daed3 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -124,6 +124,7 @@ require "chef/provider/deploy/revision"
require "chef/provider/deploy/timestamped"
require "chef/provider/remote_file/ftp"
+require "chef/provider/remote_file/sftp"
require "chef/provider/remote_file/http"
require "chef/provider/remote_file/local_file"
require "chef/provider/remote_file/network_file"
diff --git a/spec/unit/provider/remote_file/sftp_spec.rb b/spec/unit/provider/remote_file/sftp_spec.rb
index 1e42b72af5..2cc473ae6b 100644
--- a/spec/unit/provider/remote_file/sftp_spec.rb
+++ b/spec/unit/provider/remote_file/sftp_spec.rb
@@ -20,7 +20,24 @@ require "spec_helper"
describe Chef::Provider::RemoteFile::SFTP do
#built out dependencies
- let(:uri) { URI.Parse("sftp://opscode.com/seattle.txt") }
+ let(:enclosing_directory) {
+ canonicalize_path(File.expand_path(File.join(CHEF_SPEC_DATA, "templates")))
+ }
+ let(:resource_path) {
+ canonicalize_path(File.expand_path(File.join(enclosing_directory, "seattle.txt")))
+ }
+
+ let(:new_resource) do
+ r = Chef::Resource::RemoteFile.new("remote file ftp backend test (new resource)")
+ r.path(resource_path)
+ r
+ end
+
+ let(:current_resource) do
+ Chef::Resource::RemoteFile.new("remote file ftp backend test (current resource)'")
+ end
+
+ let(:uri) { URI.parse("sftp://opscode.com/seattle.txt") }
describe "on initialization" do