aws-s3 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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