gotime_aws 2.5.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/s3/s3.rb ADDED
@@ -0,0 +1,347 @@
1
+ #
2
+ # Copyright (c) 2007-2008 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ module Aws
24
+
25
+ # = Aws::S3 -- RightScale's Amazon S3 interface
26
+ # The Aws::S3 class provides a complete interface to Amazon's Simple
27
+ # Storage Service.
28
+ # For explanations of the semantics
29
+ # of each call, please refer to Amazon's documentation at
30
+ # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=48
31
+ #
32
+ # See examples below for the bucket and buckets methods.
33
+ #
34
+ # Error handling: all operations raise an Aws::AwsError in case
35
+ # of problems. Note that transient errors are automatically retried.
36
+ #
37
+ # It is a good way to use domain naming style getting a name for the buckets.
38
+ # See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingBucket.html
39
+ # about the naming convention for the buckets. This case they can be accessed using a virtual domains.
40
+ #
41
+ # Let assume you have 3 buckets: 'awesome-bucket', 'awesome_bucket' and 'AWEsomE-bucket'.
42
+ # The first ones objects can be accessed as: http:// awesome-bucket.s3.amazonaws.com/key/object
43
+ #
44
+ # But the rest have to be accessed as:
45
+ # http:// s3.amazonaws.com/awesome_bucket/key/object and http:// s3.amazonaws.com/AWEsomE-bucket/key/object
46
+ #
47
+ # See: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html for better explanation.
48
+ #
49
+ class S3
50
+
51
+
52
+ class Owner
53
+ attr_reader :id, :name
54
+
55
+ def initialize(id, name)
56
+ @id = id
57
+ @name = name
58
+ end
59
+
60
+ # Return Owner name as a +String+.
61
+ def to_s
62
+ @name
63
+ end
64
+ end
65
+
66
+ require_relative 'bucket'
67
+ require_relative 'key'
68
+ require_relative 'grantee'
69
+
70
+
71
+ attr_reader :interface
72
+
73
+
74
+ # Create a new handle to an S3 account. All handles share the same per process or per thread
75
+ # HTTP connection to Amazon S3. Each handle is for a specific account.
76
+ # The +params+ are passed through as-is to Aws::S3Interface.new
77
+ #
78
+ # Params is a hash:
79
+ #
80
+ # {:server => 's3.amazonaws.com' # Amazon service host: 's3.amazonaws.com'(default)
81
+ # :port => 443 # Amazon service port: 80 or 443(default)
82
+ # :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default)
83
+ # :virtual_hosting => false # Force using bucket virtual hosting: https://s3.amazonaws.com/my-bucket vs. https://my-bucket.s3.amazonaws.com
84
+ # :connection_mode => :default # options are
85
+ # :default (will use best known safe (as in won't need explicit close) option, may change in the future)
86
+ # :per_request (opens and closes a connection on every request)
87
+ # :single (one thread across entire app)
88
+ # :per_thread (one connection per thread)
89
+ # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
90
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
91
+ @interface = S3Interface.new(aws_access_key_id, aws_secret_access_key, params)
92
+ end
93
+
94
+ def close_connection
95
+ @interface.close_connection
96
+ end
97
+
98
+ # Retrieve a list of buckets.
99
+ # Returns an array of Aws::S3::Bucket instances.
100
+ # # Create handle to S3 account
101
+ # s3 = Aws::S3.new(aws_access_key_id, aws_secret_access_key)
102
+ # my_buckets_names = s3.buckets.map{|b| b.name}
103
+ # puts "Buckets on S3: #{my_bucket_names.join(', ')}"
104
+ def buckets
105
+ @interface.list_all_my_buckets.map! do |entry|
106
+ owner = Owner.new(entry[:owner_id], entry[:owner_display_name])
107
+ Bucket.new(self, entry[:name], entry[:creation_date], owner)
108
+ end
109
+ end
110
+
111
+ # Retrieve an individual bucket.
112
+ # If the bucket does not exist and +create+ is set, a new bucket
113
+ # is created on S3. Launching this method with +create+=+true+ may
114
+ # affect on the bucket's ACL if the bucket already exists.
115
+ # Returns a Aws::S3::Bucket instance or +nil+ if the bucket does not exist
116
+ # and +create+ is not set.
117
+ #
118
+ # s3 = Aws::S3.new(aws_access_key_id, aws_secret_access_key)
119
+ # bucket1 = s3.bucket('my_awesome_bucket_1')
120
+ # bucket1.keys #=> exception here if the bucket does not exists
121
+ # ...
122
+ # bucket2 = s3.bucket('my_awesome_bucket_2', true)
123
+ # bucket2.keys #=> list of keys
124
+ # # create a bucket at the European location with public read access
125
+ # bucket3 = s3.bucket('my-awesome-bucket-3', true, 'public-read', :location => :eu)
126
+ #
127
+ # see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html
128
+ # (section: Canned Access Policies)
129
+ #
130
+ def bucket(name, create=false, perms=nil, headers={})
131
+ headers['x-amz-acl'] = perms if perms
132
+ @interface.create_bucket(name, headers) if create
133
+ return Bucket.new(self, name)
134
+ # The old way below was too slow and unnecessary because it retreived all the buckets every time.
135
+ # owner = Owner.new(entry[:owner_id], entry[:owner_display_name])
136
+ # buckets.each { |bucket| return bucket if bucket.name == name }
137
+ # nil
138
+ end
139
+
140
+
141
+ end
142
+
143
+ # Aws::S3Generator and Aws::S3Generator::Bucket methods:
144
+ #
145
+ # s3g = Aws::S3Generator.new('1...2', 'nx...Y6') #=> #<Aws::S3Generator:0xb7b5cc94>
146
+ #
147
+ # # List all buckets(method 'GET'):
148
+ # buckets_list = s3g.buckets #=> 'https://s3.amazonaws.com:443/?Signature=Y...D&Expires=1180941864&AWSAccessKeyId=1...2'
149
+ # # Create bucket link (method 'PUT'):
150
+ # bucket = s3g.bucket('my_awesome_bucket') #=> #<Aws::S3Generator::Bucket:0xb7bcbda8>
151
+ # link_to_create = bucket.create_link(1.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket?Signature=4...D&Expires=1180942132&AWSAccessKeyId=1...2
152
+ # # ... or:
153
+ # bucket = Aws::S3Generator::Bucket.create(s3g, 'my_awesome_bucket') #=> #<Aws::S3Generator::Bucket:0xb7bcbda8>
154
+ # link_to_create = bucket.create_link(1.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket?Signature=4...D&Expires=1180942132&AWSAccessKeyId=1...2
155
+ # # ... or:
156
+ # bucket = Aws::S3Generator::Bucket.new(s3g, 'my_awesome_bucket') #=> #<Aws::S3Generator::Bucket:0xb7bcbda8>
157
+ # link_to_create = bucket.create_link(1.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket?Signature=4...D&Expires=1180942132&AWSAccessKeyId=1...2
158
+ # # List bucket(method 'GET'):
159
+ # bucket.keys(1.day) #=> https://s3.amazonaws.com:443/my_awesome_bucket?Signature=i...D&Expires=1180942620&AWSAccessKeyId=1...2
160
+ # # Create/put key (method 'PUT'):
161
+ # bucket.put('my_cool_key') #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=q...D&Expires=1180943094&AWSAccessKeyId=1...2
162
+ # # Get key data (method 'GET'):
163
+ # bucket.get('logs/today/1.log', 1.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=h...M%3D&Expires=1180820032&AWSAccessKeyId=1...2
164
+ # # Delete bucket (method 'DELETE'):
165
+ # bucket.delete(2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=4...D&Expires=1180820032&AWSAccessKeyId=1...2
166
+ #
167
+ # Aws::S3Generator::Key methods:
168
+ #
169
+ # # Create Key instance:
170
+ # key = Aws::S3Generator::Key.new(bicket, 'my_cool_key') #=> #<Aws::S3Generator::Key:0xb7b7394c>
171
+ # # Put key data (method 'PUT'):
172
+ # key.put #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=2...D&Expires=1180943302&AWSAccessKeyId=1...2
173
+ # # Get key data (method 'GET'):
174
+ # key.get #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=a...D&Expires=1180820032&AWSAccessKeyId=1...2
175
+ # # Head key (method 'HEAD'):
176
+ # key.head #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=b...D&Expires=1180820032&AWSAccessKeyId=1...2
177
+ # # Delete key (method 'DELETE'):
178
+ # key.delete #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=x...D&Expires=1180820032&AWSAccessKeyId=1...2
179
+ #
180
+ class S3Generator
181
+ attr_reader :interface
182
+
183
+ def initialize(aws_access_key_id, aws_secret_access_key, params={})
184
+ @interface = S3Interface.new(aws_access_key_id, aws_secret_access_key, params)
185
+ end
186
+
187
+ # Generate link to list all buckets
188
+ #
189
+ # s3.buckets(1.hour)
190
+ #
191
+ def buckets(expires=nil, headers={})
192
+ @interface.list_all_my_buckets_link(expires, headers)
193
+ end
194
+
195
+ # Create new S3LinkBucket instance and generate link to create it at S3.
196
+ #
197
+ # bucket= s3.bucket('my_owesome_bucket')
198
+ #
199
+ def bucket(name, expires=nil, headers={})
200
+ Bucket.create(self, name.to_s)
201
+ end
202
+
203
+ class Bucket
204
+ attr_reader :s3, :name
205
+
206
+ def to_s
207
+ @name
208
+ end
209
+
210
+ alias_method :full_name, :to_s
211
+
212
+ # Return a public link to bucket.
213
+ #
214
+ # bucket.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket'
215
+ #
216
+ def public_link
217
+ params = @s3.interface.params
218
+ "#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name}"
219
+ end
220
+
221
+ # Create new S3LinkBucket instance and generate creation link for it.
222
+ def self.create(s3, name, expires=nil, headers={})
223
+ new(s3, name.to_s)
224
+ end
225
+
226
+ # Create new S3LinkBucket instance.
227
+ def initialize(s3, name)
228
+ @s3, @name = s3, name.to_s
229
+ end
230
+
231
+ # Return a link to create this bucket.
232
+ #
233
+ def create_link(expires=nil, headers={})
234
+ @s3.interface.create_bucket_link(@name, expires, headers)
235
+ end
236
+
237
+ # Generate link to list keys.
238
+ #
239
+ # bucket.keys
240
+ # bucket.keys('prefix'=>'logs')
241
+ #
242
+ def keys(options=nil, expires=nil, headers={})
243
+ @s3.interface.list_bucket_link(@name, options, expires, headers)
244
+ end
245
+
246
+ # Return a S3Generator::Key instance.
247
+ #
248
+ # bucket.key('my_cool_key').get #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=B...D&Expires=1180820032&AWSAccessKeyId=1...2
249
+ # bucket.key('my_cool_key').delete #=> https://s3.amazonaws.com:443/my_awesome_bucket/my_cool_key?Signature=B...D&Expires=1180820098&AWSAccessKeyId=1...2
250
+ #
251
+ def key(name)
252
+ Key.new(self, name)
253
+ end
254
+
255
+ # Generates link to PUT key data.
256
+ #
257
+ # puts bucket.put('logs/today/1.log', 2.hour)
258
+ #
259
+ def put(key, meta_headers={}, expires=nil, headers={})
260
+ meta = Aws::S3::Key.add_meta_prefix(meta_headers)
261
+ @s3.interface.put_link(@name, key.to_s, nil, expires, meta.merge(headers))
262
+ end
263
+
264
+ # Generate link to GET key data.
265
+ #
266
+ # bucket.get('logs/today/1.log', 1.hour)
267
+ #
268
+ def get(key, expires=nil, headers={})
269
+ @s3.interface.get_link(@name, key.to_s, expires, headers)
270
+ end
271
+
272
+ # Generate link to delete bucket.
273
+ #
274
+ # bucket.delete(2.hour)
275
+ #
276
+ def delete(expires=nil, headers={})
277
+ @s3.interface.delete_bucket_link(@name, expires, headers)
278
+ end
279
+ end
280
+
281
+
282
+ class Key
283
+ attr_reader :bucket, :name
284
+
285
+ def to_s
286
+ @name
287
+ end
288
+
289
+ # Return a full S# name (bucket/key).
290
+ #
291
+ # key.full_name #=> 'my_awesome_bucket/cool_key'
292
+ #
293
+ def full_name(separator='/')
294
+ "#{@bucket.to_s}#{separator}#{@name}"
295
+ end
296
+
297
+ # Return a public link to key.
298
+ #
299
+ # key.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket/cool_key'
300
+ #
301
+ def public_link
302
+ params = @bucket.s3.interface.params
303
+ "#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name('/')}"
304
+ end
305
+
306
+ def initialize(bucket, name, meta_headers={})
307
+ @bucket = bucket
308
+ @name = name.to_s
309
+ @meta_headers = meta_headers
310
+ raise 'Key name can not be empty.' if Aws::Utils.blank?(@name)
311
+ end
312
+
313
+ # Generate link to PUT key data.
314
+ #
315
+ # puts bucket.put('logs/today/1.log', '123', 2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=B...D&Expires=1180820032&AWSAccessKeyId=1...2
316
+ #
317
+ def put(expires=nil, headers={})
318
+ @bucket.put(@name.to_s, @meta_headers, expires, headers)
319
+ end
320
+
321
+ # Generate link to GET key data.
322
+ #
323
+ # bucket.get('logs/today/1.log', 1.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=h...M%3D&Expires=1180820032&AWSAccessKeyId=1...2
324
+ #
325
+ def get(expires=nil, headers={})
326
+ @bucket.s3.interface.get_link(@bucket.to_s, @name, expires, headers)
327
+ end
328
+
329
+ # Generate link to delete key.
330
+ #
331
+ # bucket.delete(2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=4...D&Expires=1180820032&AWSAccessKeyId=1...2
332
+ #
333
+ def delete(expires=nil, headers={})
334
+ @bucket.s3.interface.delete_link(@bucket.to_s, @name, expires, headers)
335
+ end
336
+
337
+ # Generate link to head key.
338
+ #
339
+ # bucket.head(2.hour) #=> https://s3.amazonaws.com:443/my_awesome_bucket/logs%2Ftoday%2F1.log?Signature=4...D&Expires=1180820032&AWSAccessKeyId=1...2
340
+ #
341
+ def head(expires=nil, headers={})
342
+ @bucket.s3.interface.head_link(@bucket.to_s, @name, expires, headers)
343
+ end
344
+ end
345
+ end
346
+
347
+ end