aws-s3 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/COPYING +19 -0
  2. data/INSTALL +35 -0
  3. data/README +529 -0
  4. data/Rakefile +284 -0
  5. data/bin/s3sh +4 -0
  6. data/bin/setup.rb +10 -0
  7. data/lib/aws/s3.rb +64 -0
  8. data/lib/aws/s3/acl.rb +631 -0
  9. data/lib/aws/s3/authentication.rb +218 -0
  10. data/lib/aws/s3/base.rb +232 -0
  11. data/lib/aws/s3/bittorrent.rb +58 -0
  12. data/lib/aws/s3/bucket.rb +323 -0
  13. data/lib/aws/s3/connection.rb +212 -0
  14. data/lib/aws/s3/error.rb +69 -0
  15. data/lib/aws/s3/exceptions.rb +130 -0
  16. data/lib/aws/s3/extensions.rb +186 -0
  17. data/lib/aws/s3/logging.rb +163 -0
  18. data/lib/aws/s3/object.rb +565 -0
  19. data/lib/aws/s3/owner.rb +44 -0
  20. data/lib/aws/s3/parsing.rb +138 -0
  21. data/lib/aws/s3/response.rb +180 -0
  22. data/lib/aws/s3/service.rb +43 -0
  23. data/lib/aws/s3/version.rb +12 -0
  24. data/support/faster-xml-simple/lib/faster_xml_simple.rb +115 -0
  25. data/support/faster-xml-simple/test/regression_test.rb +16 -0
  26. data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +22 -0
  27. data/support/rdoc/code_info.rb +211 -0
  28. data/test/acl_test.rb +243 -0
  29. data/test/authentication_test.rb +96 -0
  30. data/test/base_test.rb +143 -0
  31. data/test/bucket_test.rb +48 -0
  32. data/test/connection_test.rb +120 -0
  33. data/test/error_test.rb +75 -0
  34. data/test/extensions_test.rb +282 -0
  35. data/test/fixtures.rb +89 -0
  36. data/test/fixtures/buckets.yml +102 -0
  37. data/test/fixtures/errors.yml +34 -0
  38. data/test/fixtures/headers.yml +3 -0
  39. data/test/fixtures/logging.yml +15 -0
  40. data/test/fixtures/policies.yml +16 -0
  41. data/test/logging_test.rb +36 -0
  42. data/test/mocks/base.rb +89 -0
  43. data/test/object_test.rb +177 -0
  44. data/test/parsing_test.rb +82 -0
  45. data/test/remote/acl_test.rb +117 -0
  46. data/test/remote/bittorrent_test.rb +45 -0
  47. data/test/remote/bucket_test.rb +127 -0
  48. data/test/remote/logging_test.rb +82 -0
  49. data/test/remote/object_test.rb +267 -0
  50. data/test/remote/test_file.data +0 -0
  51. data/test/remote/test_helper.rb +30 -0
  52. data/test/response_test.rb +70 -0
  53. data/test/service_test.rb +26 -0
  54. data/test/test_helper.rb +82 -0
  55. metadata +125 -0
@@ -0,0 +1,117 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RemoteACLTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ establish_real_connection
7
+ end
8
+
9
+ def teardown
10
+ disconnect!
11
+ end
12
+
13
+ def test_acl
14
+ Bucket.create(TEST_BUCKET) # Wipe out the existing bucket's ACL
15
+
16
+ bucket_policy = Bucket.acl(TEST_BUCKET)
17
+ assert_equal 1, bucket_policy.grants.size
18
+ assert !bucket_policy.grants.include?(:public_read_acp)
19
+
20
+ bucket_policy.grants << ACL::Grant.grant(:public_read_acp)
21
+
22
+ assert_nothing_raised do
23
+ Bucket.acl(TEST_BUCKET, bucket_policy)
24
+ end
25
+
26
+ bucket = Bucket.find(TEST_BUCKET)
27
+ assert bucket.acl.grants.include?(:public_read_acp)
28
+
29
+ bucket.acl.grants.pop # Get rid of the newly added grant
30
+
31
+ assert !bucket.acl.grants.include?(:public_read_acp)
32
+ bucket.acl(bucket.acl) # Update its acl
33
+ assert Service.response.success?
34
+
35
+ bucket_policy = Bucket.acl(TEST_BUCKET)
36
+ assert_equal 1, bucket_policy.grants.size
37
+ assert !bucket_policy.grants.include?(:public_read_acp)
38
+
39
+ S3Object.store('testing-acls', 'the test data', TEST_BUCKET, :content_type => 'text/plain')
40
+ acl = S3Object.acl('testing-acls', TEST_BUCKET)
41
+
42
+ # Confirm object has the default policy
43
+
44
+ assert !acl.grants.empty?
45
+ assert_equal 1, acl.grants.size
46
+ grant = acl.grants.first
47
+
48
+ assert_equal 'FULL_CONTROL', grant.permission
49
+
50
+ grantee = grant.grantee
51
+
52
+ assert acl.owner.id
53
+ assert acl.owner.display_name
54
+ assert grantee.id
55
+ assert grantee.display_name
56
+
57
+ assert_equal acl.owner.id, grantee.id
58
+ assert_equal acl.owner.display_name, grantee.display_name
59
+
60
+ assert_equal Owner.current, acl.owner
61
+
62
+
63
+ # Manually add read access to an Amazon customer by email address
64
+
65
+ new_grant = ACL::Grant.new
66
+ new_grant.permission = 'READ'
67
+ new_grant_grantee = ACL::Grantee.new
68
+ new_grant_grantee.email_address = 'marcel@vernix.org'
69
+ new_grant.grantee = new_grant_grantee
70
+ acl.grants << new_grant
71
+
72
+ assert_nothing_raised do
73
+ S3Object.acl('testing-acls', TEST_BUCKET, acl)
74
+ end
75
+
76
+ # Confirm the acl was updated successfully
77
+
78
+ assert Service.response.success?
79
+
80
+ acl = S3Object.acl('testing-acls', TEST_BUCKET)
81
+ assert !acl.grants.empty?
82
+ assert_equal 2, acl.grants.size
83
+ new_grant = acl.grants.last
84
+ assert_equal 'READ', new_grant.permission
85
+
86
+ # Confirm instance method has same result
87
+
88
+ assert_equal acl.grants, S3Object.find('testing-acls', TEST_BUCKET).acl.grants
89
+
90
+ # Get rid of the grant we just added
91
+
92
+ acl.grants.pop
93
+
94
+ # Confirm acl class method sees that the bucket option is being used to put a new acl
95
+
96
+ assert_nothing_raised do
97
+ TestS3Object.acl('testing-acls', acl)
98
+ end
99
+
100
+ assert Service.response.success?
101
+
102
+ acl = TestS3Object.acl('testing-acls')
103
+
104
+ # Confirm added grant was removed from the policy
105
+
106
+ assert !acl.grants.empty?
107
+ assert_equal 1, acl.grants.size
108
+ grant = acl.grants.first
109
+ assert_equal 'FULL_CONTROL', grant.permission
110
+
111
+ assert_nothing_raised do
112
+ S3Object.delete('testing-acls', TEST_BUCKET)
113
+ end
114
+
115
+ assert Service.response.success?
116
+ end
117
+ end
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RemoteBittorrentTest < Test::Unit::TestCase
4
+ def setup
5
+ establish_real_connection
6
+ end
7
+
8
+ def teardown
9
+ disconnect!
10
+ end
11
+
12
+ def test_bittorrent
13
+ bt_test_key = 'testing-bittorrent'
14
+ S3Object.create(bt_test_key, 'foo', TEST_BUCKET)
15
+
16
+ # Confirm we can fetch a bittorrent file for this object
17
+
18
+ torrent_file = nil
19
+ assert_nothing_raised do
20
+ torrent_file = S3Object.torrent_for(bt_test_key, TEST_BUCKET)
21
+ end
22
+ assert torrent_file
23
+ assert torrent_file['tracker']
24
+
25
+ # Make object accessible to the public via a torrent
26
+
27
+ policy = S3Object.acl(bt_test_key, TEST_BUCKET)
28
+
29
+ assert !policy.grants.include?(:public_read)
30
+
31
+ assert_nothing_raised do
32
+ S3Object.grant_torrent_access_to(bt_test_key, TEST_BUCKET)
33
+ end
34
+
35
+ policy = S3Object.acl(bt_test_key, TEST_BUCKET)
36
+
37
+ assert policy.grants.include?(:public_read)
38
+
39
+ # Confirm instance method wraps class method
40
+
41
+ assert_equal torrent_file, S3Object.find(bt_test_key, TEST_BUCKET).torrent
42
+
43
+ S3Object.delete(bt_test_key, TEST_BUCKET)
44
+ end
45
+ end
@@ -0,0 +1,127 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RemoteBucketTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ establish_real_connection
7
+ assert Bucket.find(TEST_BUCKET).delete_all
8
+ end
9
+
10
+ def teardown
11
+ disconnect!
12
+ end
13
+
14
+ def test_bucket
15
+ # Fetch the testing bucket
16
+
17
+ bucket = nil
18
+ assert_nothing_raised do
19
+ bucket = Bucket.find(TEST_BUCKET)
20
+ end
21
+
22
+ assert bucket
23
+
24
+ # Confirm we can fetch the bucket implicitly
25
+
26
+ bucket = nil
27
+ assert_nothing_raised do
28
+ bucket = TestBucket.find
29
+ end
30
+
31
+ assert bucket
32
+
33
+ # Confirm the bucket has the right name
34
+
35
+ assert_equal TEST_BUCKET, bucket.name
36
+
37
+ assert bucket.empty?
38
+ assert_equal 0, bucket.size
39
+
40
+ # Add some files to the bucket
41
+
42
+ assert_nothing_raised do
43
+ %w(a m z).each do |file_name|
44
+ S3Object.create(file_name, file_name, bucket.name, :content_type => 'text/plain')
45
+ end
46
+ end
47
+
48
+ # Confirm that we can reload the objects
49
+
50
+ assert_nothing_raised do
51
+ bucket.objects(:reload)
52
+ end
53
+
54
+ assert !bucket.empty?
55
+ assert_equal 3, bucket.size
56
+
57
+ assert_nothing_raised do
58
+ bucket.objects(:marker => 'm')
59
+ end
60
+
61
+ assert_equal 1, bucket.size
62
+ assert bucket['z']
63
+
64
+ assert_equal 1, Bucket.find(TEST_BUCKET, :max_keys => 1).size
65
+
66
+ assert_nothing_raised do
67
+ bucket.objects(:reload)
68
+ end
69
+
70
+ assert_equal 3, bucket.size
71
+
72
+ # Ensure the reloaded buckets have been repatriated
73
+
74
+ assert_equal bucket, bucket.objects.first.bucket
75
+
76
+ # Confirm that we can delete one of the objects and it will be removed
77
+
78
+ object_to_be_deleted = bucket.objects.last
79
+ assert_nothing_raised do
80
+ object_to_be_deleted.delete
81
+ end
82
+
83
+ assert !bucket.objects.include?(object_to_be_deleted)
84
+
85
+ # Confirm that we can add an object
86
+
87
+ object = bucket.new_object(:value => 'hello')
88
+
89
+ assert_raises(NoKeySpecified) do
90
+ object.store
91
+ end
92
+
93
+ object.key = 'abc'
94
+ assert_nothing_raised do
95
+ object.store
96
+ end
97
+
98
+ assert bucket.objects.include?(object)
99
+
100
+ # Confirm that the object is still there after reloading its objects
101
+
102
+ assert_nothing_raised do
103
+ bucket.objects(:reload)
104
+ end
105
+ assert bucket.objects.include?(object)
106
+
107
+ # Check that TestBucket has the same objects fetched implicitly
108
+
109
+ assert_equal bucket.objects, TestBucket.objects
110
+
111
+ # Empty out bucket
112
+
113
+ assert_nothing_raised do
114
+ bucket.delete_all
115
+ end
116
+
117
+ assert bucket.empty?
118
+
119
+ bucket = nil
120
+ assert_nothing_raised do
121
+ bucket = Bucket.find(TEST_BUCKET)
122
+ end
123
+
124
+ assert bucket.empty?
125
+ end
126
+
127
+ end
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RemoteLoggingTest < Test::Unit::TestCase
4
+ def setup
5
+ establish_real_connection
6
+ end
7
+
8
+ def teardown
9
+ disconnect!
10
+ end
11
+
12
+ def test_logging
13
+ Bucket.create(TEST_BUCKET) # Clear out any custom grants
14
+
15
+ # Confirm that logging is not enabled on the test bucket
16
+
17
+ assert !Bucket.logging_enabled_for?(TEST_BUCKET)
18
+ assert !Bucket.find(TEST_BUCKET).logging_enabled?
19
+
20
+ assert_equal [], Bucket.logs_for(TEST_BUCKET)
21
+
22
+ # Confirm the current bucket doesn't have logging grants
23
+
24
+ policy = Bucket.acl(TEST_BUCKET)
25
+ assert !policy.grants.include?(:logging_read_acp)
26
+ assert !policy.grants.include?(:logging_write)
27
+
28
+ # Confirm that we can enable logging
29
+
30
+ assert_nothing_raised do
31
+ Bucket.enable_logging_for TEST_BUCKET
32
+ end
33
+
34
+ # Confirm enabling logging worked
35
+
36
+ assert Service.response.success?
37
+
38
+ assert Bucket.logging_enabled_for?(TEST_BUCKET)
39
+ assert Bucket.find(TEST_BUCKET).logging_enabled?
40
+
41
+ # Confirm the appropriate grants were added
42
+
43
+ policy = Bucket.acl(TEST_BUCKET)
44
+ assert policy.grants.include?(:logging_read_acp)
45
+ assert policy.grants.include?(:logging_write)
46
+
47
+ # Confirm logging status used defaults
48
+
49
+ logging_status = Bucket.logging_status_for TEST_BUCKET
50
+ assert_equal TEST_BUCKET, logging_status.target_bucket
51
+ assert_equal 'log-', logging_status.target_prefix
52
+
53
+ # Confirm we can update the logging status
54
+
55
+ logging_status.target_prefix = 'access-log-'
56
+
57
+ assert_nothing_raised do
58
+ Bucket.logging_status_for TEST_BUCKET, logging_status
59
+ end
60
+
61
+ assert Service.response.success?
62
+
63
+ logging_status = Bucket.logging_status_for TEST_BUCKET
64
+ assert_equal 'access-log-', logging_status.target_prefix
65
+
66
+ # Confirm we can make a request for the bucket's logs
67
+
68
+ assert_nothing_raised do
69
+ Bucket.logs_for TEST_BUCKET
70
+ end
71
+
72
+ # Confirm we can disable logging
73
+
74
+ assert_nothing_raised do
75
+ Bucket.disable_logging_for(TEST_BUCKET)
76
+ end
77
+
78
+ assert Service.response.success?
79
+
80
+ assert !Bucket.logging_enabled_for?(TEST_BUCKET)
81
+ end
82
+ end
@@ -0,0 +1,267 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RemoteS3ObjectTest < Test::Unit::TestCase
4
+ def setup
5
+ establish_real_connection
6
+ end
7
+
8
+ def teardown
9
+ disconnect!
10
+ end
11
+
12
+ def test_object
13
+ key = 'testing_s3objects'
14
+ value = 'testing'
15
+ content_type = 'text/plain'
16
+ fetch_object_at = Proc.new {|url| Net::HTTP.get_response(URI.parse(url))}
17
+ unauthenticated_url = ['http:/', Base.connection.http.address, TEST_BUCKET, key].join('/')
18
+
19
+ # Create an object
20
+
21
+ response = nil
22
+ assert_nothing_raised do
23
+ response = S3Object.create(key, value, TEST_BUCKET, :access => :public_read, :content_type => content_type)
24
+ end
25
+
26
+ # Check response
27
+
28
+ assert response.success?
29
+
30
+ # Extract the object's etag
31
+
32
+ etag = nil
33
+ assert_nothing_raised do
34
+ etag = response.etag
35
+ end
36
+
37
+ assert etag
38
+
39
+ # Confirm we can't create an object unless the bucket is set
40
+
41
+ assert_raises(NoBucketSpecified) do
42
+ object = S3Object.new
43
+ object.key = 'hello'
44
+ object.store
45
+ end
46
+
47
+ # Fetch newly created object to show it was actually created
48
+
49
+ object = nil
50
+ assert_nothing_raised do
51
+ object = S3Object.find(key, TEST_BUCKET)
52
+ end
53
+
54
+ assert object
55
+
56
+ # Confirm it has the right etag
57
+
58
+ assert_equal etag, object.etag
59
+
60
+ # Check if its owner is properly set
61
+
62
+ assert_nothing_raised do
63
+ object.owner.display_name
64
+ end
65
+
66
+ # Confirm we can get the object's key
67
+
68
+ assert_equal key, object.key
69
+
70
+ # Confirm its value was properly set
71
+
72
+ assert_equal value, object.value
73
+ assert_equal value, S3Object.value(key, TEST_BUCKET)
74
+ streamed_value = ''
75
+ assert_nothing_raised do
76
+ S3Object.stream(key, TEST_BUCKET) do |segment|
77
+ streamed_value << segment
78
+ end
79
+ end
80
+
81
+ assert_equal value, streamed_value
82
+
83
+ # Change its value
84
+
85
+ new_value = "<script>alert('foo');</script>"
86
+ assert_nothing_raised do
87
+ object.value = new_value
88
+ end
89
+ assert_equal new_value, object.value
90
+
91
+ # Confirm content type was properly set
92
+
93
+ assert_equal content_type, object.content_type
94
+
95
+ # Change its content type
96
+
97
+ new_content_type = 'text/javascript'
98
+ assert_nothing_raised do
99
+ object.content_type = new_content_type
100
+ end
101
+
102
+ assert_equal new_content_type, object.content_type
103
+
104
+ # Test that it is publicly readable
105
+
106
+ response = fetch_object_at[unauthenticated_url]
107
+ assert (200..299).include?(response.code.to_i)
108
+
109
+ # Confirm that it has no meta data
110
+
111
+ assert object.metadata.empty?
112
+
113
+ # Set some meta data
114
+
115
+ metadata_key = :secret_sauce
116
+ metadata_value = "it's a secret"
117
+ object.metadata[metadata_key] = metadata_value
118
+
119
+ # Persist all changes
120
+
121
+ assert_nothing_raised do
122
+ object.store
123
+ end
124
+
125
+ # Refetch the object
126
+
127
+ key = object.key
128
+ object = nil
129
+ assert_nothing_raised do
130
+ object = S3Object.find(key, TEST_BUCKET)
131
+ end
132
+
133
+ # Confirm all changes were persisted
134
+
135
+ assert object
136
+ assert_equal key, object.key
137
+
138
+ assert_equal new_content_type, object.content_type
139
+
140
+ assert_equal new_value, object.value
141
+ assert_equal new_value, object.value(:reload)
142
+
143
+ assert !object.metadata.empty?
144
+ assert_equal metadata_value, object.metadata[metadata_key]
145
+
146
+ # Change acl
147
+
148
+ assert_nothing_raised do
149
+ S3Object.create(object.key, object.value, TEST_BUCKET, :access => :private, :content_type => object.content_type)
150
+ end
151
+
152
+ # Confirm object is no longer publicly readable
153
+
154
+ response = fetch_object_at[unauthenticated_url]
155
+ assert (400..499).include?(response.code.to_i)
156
+
157
+ # Confirm object is accessible from its authenticated url
158
+
159
+ response = fetch_object_at[object.url]
160
+ assert (200..299).include?(response.code.to_i)
161
+
162
+ # Copy the object
163
+
164
+ assert_nothing_raised do
165
+ object.copy('testing_s3objects-copy')
166
+ end
167
+
168
+ # Confirm the object is identical
169
+
170
+ copy = nil
171
+ assert_nothing_raised do
172
+ copy = S3Object.find('testing_s3objects-copy', TEST_BUCKET)
173
+ end
174
+
175
+ assert copy
176
+
177
+ assert_equal object.value, copy.value
178
+ assert_equal object.content_type, copy.content_type
179
+
180
+ # Delete object
181
+
182
+ assert_nothing_raised do
183
+ object.delete
184
+ end
185
+
186
+ # Confirm we can rename objects
187
+
188
+ renamed_to = copy.key + '-renamed'
189
+ renamed_value = copy.value
190
+ assert_nothing_raised do
191
+ S3Object.rename(copy.key, renamed_to, TEST_BUCKET)
192
+ end
193
+
194
+ # Confirm renamed copy exists
195
+
196
+ renamed = nil
197
+ assert_nothing_raised do
198
+ renamed = S3Object.find(renamed_to, TEST_BUCKET)
199
+ end
200
+
201
+ assert renamed
202
+ assert_equal renamed_value, renamed.value
203
+
204
+ # Confirm copy is deleted
205
+
206
+ assert_raises(NoSuchKey) do
207
+ S3Object.find(copy.key, TEST_BUCKET)
208
+ end
209
+
210
+ # Confirm that you can not store an object once it is deleted
211
+
212
+ assert_raises(DeletedObject) do
213
+ object.store
214
+ end
215
+
216
+ assert_raises(NoSuchKey) do
217
+ S3Object.find(key, TEST_BUCKET)
218
+ end
219
+
220
+ # Confirm we can pass in an IO stream and have the uploading sent in chunks
221
+
222
+ response = nil
223
+ test_file_key = File.basename(TEST_FILE)
224
+ assert_nothing_raised do
225
+ response = S3Object.store(test_file_key, File.open(TEST_FILE), TEST_BUCKET)
226
+ end
227
+ assert response.success?
228
+
229
+ assert_equal File.size(TEST_FILE), Integer(S3Object.about(test_file_key, TEST_BUCKET)['content-length'])
230
+
231
+ result = nil
232
+ assert_nothing_raised do
233
+ result = S3Object.delete(test_file_key, TEST_BUCKET)
234
+ end
235
+
236
+ assert result
237
+
238
+ # Confirm we can create an object with spaces in its key
239
+
240
+ object = S3Object.new(:value => 'just some text')
241
+ object.key = 'name with spaces'
242
+ object.bucket = Bucket.find(TEST_BUCKET)
243
+
244
+ assert_nothing_raised do
245
+ object.store
246
+ end
247
+
248
+ object = nil
249
+ assert_nothing_raised do
250
+ object = S3Object.find('name with spaces', TEST_BUCKET)
251
+ end
252
+
253
+ assert object
254
+ assert_equal 'name with spaces', object.key
255
+
256
+ # Confirm authenticated url is generated correctly despite space in file name
257
+
258
+ response = fetch_object_at[object.url]
259
+ assert (200..299).include?(response.code.to_i)
260
+
261
+ # Confirm we can delete objects with spaces in their key
262
+
263
+ assert_nothing_raised do
264
+ object.delete
265
+ end
266
+ end
267
+ end