Skip to content

Commit

Permalink
add AWS S3 driver
Browse files Browse the repository at this point in the history
  • Loading branch information
al6x committed Aug 25, 2011
1 parent aecb0f4 commit d2ce173
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 29 deletions.
1 change: 0 additions & 1 deletion lib/vos.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
%w(
support

drivers/abstract
drivers/local
drivers/ssh_vfs_storage
drivers/ssh
Expand Down
11 changes: 0 additions & 11 deletions lib/vos/drivers/abstract.rb

This file was deleted.

2 changes: 1 addition & 1 deletion lib/vos/drivers/local.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Vos
module Drivers
class Local < Abstract
class Local
#
# Vfs
#
Expand Down
63 changes: 63 additions & 0 deletions lib/vos/drivers/s3.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'aws'
require 'vos/drivers/s3_vfs_storage'

module Vos
module Drivers
class S3
attr_reader :connection, :bucket

DEFAULT_OPTIONS = {
# public: true
}

def initialize initialization_options, options = {}
@initialization_options, @options = initialization_options, DEFAULT_OPTIONS.merge(options)
end


#
# Establishing SSH channel
#
def open &block
if block
if connection
block.call self
else
begin
open
block.call self
ensure
close
end
end
else
unless connection
@connection = ::AWS::S3.new self.initialization_options.clone
unless bucket = options[:bucket]
raise("S3 bucket not provided (use Vos::Drivers::S3.new({initialization options ...}, {bucket: '<bucket_name>'}))!")
end
@bucket = @connection.buckets[bucket]
end
end
end

def close; end

#
# Vfs
#
include S3VfsStorage
alias_method :open_fs, :open


#
# Miscellaneous
#
def inspect; "<#{self.class.name} #{initialization_options.inspect}, #{options.inspect}>" end
alias_method :to_s, :inspect

protected
attr_reader :initialization_options, :options
end
end
end
155 changes: 155 additions & 0 deletions lib/vos/drivers/s3_vfs_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
module Vos
module Drivers
module S3VfsStorage
class Error < StandardError
end

class Writer
attr_reader :data
def initialize
@data = ""
end

def write data
@data << data
end
end

#
# Attributes
#
def attributes path
path = normalize_path(path)
return {dir: true, file: false} if path.empty?

file = bucket.objects[path]

attrs = {}
file_exists = file.exists?
attrs[:file] = file_exists
if file_exists
attrs[:dir] = false
else
attrs[:dir] = dir_exists? path
end

if file_exists
attrs[:size] = file.content_length
attrs[:last_modified] = file.last_modified
end

attrs
end

def set_attributes path, attrs
raise 'not supported'
end

#
# File
#
def read_file path, &block
path = normalize_path path
file = bucket.objects[path]
block.call file.read
end

def write_file original_path, append, &block
path = normalize_path original_path
# TODO2 Performance lost, extra call to check file existence
file = bucket.objects[path]
file_exist = file.exists?
raise "can't write, file #{original_path} already exist!" if !append and file_exist
raise "can't write, dir #{original_path} already exist!" if dir_exists? path

if append
# there's no support for :append in Fog, so we just mimic it
writer = Writer.new
writer.write file.read if file_exist
block.call writer
file.write writer.data
else
writer = Writer.new
block.call writer
file.write writer.data
end
end

def delete_file path
path = normalize_path path
file = bucket.objects[path]
file.delete
end


#
# Dir
#
def create_dir path
raise Error, ":create_dir not supported!"
end

def delete_dir path
path = normalize_path path

bucket.as_tree(prefix: path).children.each do |obj|
if obj.branch?
delete_dir "/#{obj.prefix}"
elsif obj.leaf?
bucket.objects[obj.key].delete
else
raise "unknow node type!"
end
end
end

def each_entry path, query, &block
path = normalize_path path
raise "S3 not support :each_entry with query!" if query

bucket.as_tree(prefix: path).children.each do |obj|
if obj.branch?
block.call obj.prefix.sub("#{path}/", '').sub(/\/$/, ''), :dir
elsif obj.leaf?
block.call obj.key.sub("#{path}/", ''), :file
else
raise "unknow node type!"
end
end
end

#
# Special
#
def tmp &block
tmp_dir = "/tmp/vfs_#{rand(10**6)}"
if block
begin
block.call tmp_dir
ensure
delete_dir tmp_dir
end
else
tmp_dir
end
end

def local?; false end

protected
def dir_exists? path
path = normalize_path path
catch :break do
bucket.as_tree(prefix: path).children.each do
throw :break, true
end
false
end
end

def normalize_path path
path.sub(/^\//, '')
end
end
end
end
5 changes: 2 additions & 3 deletions lib/vos/drivers/ssh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

module Vos
module Drivers
class Ssh < Abstract
class Ssh
DEFAULT_OPTIONS = {
config: true
}

def initialize options = {}
super
raise ":host not provided!" unless options[:host]
@options = DEFAULT_OPTIONS.merge options

Expand Down Expand Up @@ -90,7 +89,7 @@ def to_s; options[:host] end
def host; options[:host] end

protected
attr_accessor :ssh, :sftp
attr_accessor :ssh, :sftp, :options

def fix_path path
path.sub(/^\~/, home)
Expand Down
12 changes: 5 additions & 7 deletions lib/vos/drivers/ssh_vfs_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def attributes path

attrs
rescue Net::SFTP::StatusException
{}
{file: false, dir: false}
end

def set_attributes path, attrs
Expand All @@ -49,15 +49,13 @@ def write_file path, append, &block
# there's no support for :append in Net::SFTP, so we just mimic it
if append
attrs = attributes(path)
data = if attrs
if attrs[:file]
data = if attrs[:file]
os = ""
read_file(path){|buff| os << buff}
delete_file path
os
else
raise "can't append to dir!"
end
elsif attrs[:dir]
raise "can't append to dir!"
else
''
end
Expand Down Expand Up @@ -127,7 +125,7 @@ def each_entry path, query, &block
# Special
#
def tmp &block
tmp_dir = "/tmp/vfs_#{rand(10**3)}"
tmp_dir = "/tmp/vfs_#{rand(10**6)}"
if block
begin
create_dir tmp_dir
Expand Down
13 changes: 10 additions & 3 deletions spec/config.example.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
:ssh:
:host: some_host.com
:ssh_driver:
:host: xxx.com

# optional, you can omit and use id_rsa key instead
# :user: some_user
# :password: some_password
# :password: some_password

:s3:
:driver:
:access_key_id: 'xxx'
:secret_access_key: 'xxx'

:bucket: :xxx
4 changes: 3 additions & 1 deletion spec/drivers/local_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

describe Vos::Drivers::Local do
it_should_behave_like "vos driver"
it_should_behave_like "vfs storage"
it_should_behave_like 'vfs storage basic'
it_should_behave_like 'vfs storage files'
it_should_behave_like 'vfs storage dirs'

before do
@storage = @driver = Vos::Drivers::Local.new
Expand Down
Loading

0 comments on commit d2ce173

Please sign in to comment.