-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.rb
124 lines (100 loc) · 2.81 KB
/
client.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
require 'aws-sdk'
require 'thor'
require 'digest/md5'
require 'mime/types'
require 'singleton'
class DearS3::Client
include Singleton
def set_bucket name
self.bucket = s3.buckets[name]
if new_bucket? name
s3.buckets.create(bucket.name, acl: :bucket_owner_full_control)
end
bucket.name
end
def validate_bucket_name name
return :Invalid if invalid_bucket_name? name
return :Unavailable if unavailable_bucket_name? name
nil
end
def new_bucket? name
!s3.buckets[name].exists?
end
def bucket_name
bucket.name
end
def with s3_connection
@bucket = nil
@s3 = s3_connection
self
end
def walk_and_upload path, status_proc = nil
entries = Dir.entries path
entries.each do |entry|
next if entry == File.basename(__FILE__) || entry[0] == '.'
nested_entry = (path == "." ? entry : "#{ path }/#{ entry }")
if File.directory? nested_entry
walk_and_upload nested_entry, status_proc
next
else
upload nested_entry, status_proc
end
end
end
def configure_website index_doc, error_doc
bucket.configure_website do |cfg|
cfg.index_document_suffix = index_doc
cfg.error_document_key = error_doc
end
bucket.policy = generate_policy
# TODO: find more general pattern
"http://#{ bucket_name }.s3-website-us-east-1.amazonaws.com/"
end
def generate_policy
policy = AWS::S3::Policy.new
resources = "arn:aws:s3:::#{ bucket_name }/*"
policy.allow(actions: [:get_object], resources: resources, principals: :any)
policy
end
def files_in_bucket
@files_in_bucket ||= bucket.objects.map &:key
end
def remove_website
bucket.remove_website_configuration
bucket.url
end
private
attr_accessor :bucket
attr_reader :s3
def upload entry, status_proc = nil
object = bucket.objects[entry]
if object.exists? && entry_is_unchanged?(entry, object)
status_proc.call entry, :unchanged
elsif object.exists?
status_proc.call entry, :update
else
status_proc.call entry, :upload
end
content_type = ::MIME::Types.type_for(entry).to_s
object.write File.open entry, content_type: content_type
end
def entry_is_unchanged? entry, object
# Is object etag equal to the MD5 digest of the entry?
# Strip opening and closing "\" chars from AWS-formatted etag
object.etag[1..-2] == ::Digest::MD5.hexdigest(File.read entry)
end
def invalid_bucket_name? name
name.length < 3 or
name.length > 62 or
name[-1] == '-' or
name.include?('_') or
name.include?(".") or
name.include?(";") or
name.include?("-.") or
name.include?(".-")
end
def unavailable_bucket_name? name
my_buckets = s3.buckets.map &:name
s3.buckets[name].exists? && !my_buckets.include?(name)
end
end