mss-sdk 1.0.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 (131) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +9 -0
  3. data/LICENSE.txt +0 -0
  4. data/README.md +192 -0
  5. data/bin/mss-rb +178 -0
  6. data/ca-bundle.crt +3554 -0
  7. data/lib/mss/core/async_handle.rb +89 -0
  8. data/lib/mss/core/cacheable.rb +76 -0
  9. data/lib/mss/core/client.rb +786 -0
  10. data/lib/mss/core/collection/simple.rb +81 -0
  11. data/lib/mss/core/collection/with_limit_and_next_token.rb +70 -0
  12. data/lib/mss/core/collection/with_next_token.rb +96 -0
  13. data/lib/mss/core/collection.rb +262 -0
  14. data/lib/mss/core/configuration.rb +527 -0
  15. data/lib/mss/core/credential_providers.rb +653 -0
  16. data/lib/mss/core/data.rb +251 -0
  17. data/lib/mss/core/deprecations.rb +83 -0
  18. data/lib/mss/core/endpoints.rb +36 -0
  19. data/lib/mss/core/http/connection_pool.rb +374 -0
  20. data/lib/mss/core/http/curb_handler.rb +150 -0
  21. data/lib/mss/core/http/handler.rb +88 -0
  22. data/lib/mss/core/http/net_http_handler.rb +144 -0
  23. data/lib/mss/core/http/patch.rb +98 -0
  24. data/lib/mss/core/http/request.rb +258 -0
  25. data/lib/mss/core/http/response.rb +80 -0
  26. data/lib/mss/core/indifferent_hash.rb +87 -0
  27. data/lib/mss/core/inflection.rb +55 -0
  28. data/lib/mss/core/ini_parser.rb +41 -0
  29. data/lib/mss/core/json_client.rb +46 -0
  30. data/lib/mss/core/json_parser.rb +75 -0
  31. data/lib/mss/core/json_request_builder.rb +34 -0
  32. data/lib/mss/core/json_response_parser.rb +78 -0
  33. data/lib/mss/core/lazy_error_classes.rb +107 -0
  34. data/lib/mss/core/log_formatter.rb +426 -0
  35. data/lib/mss/core/managed_file.rb +31 -0
  36. data/lib/mss/core/meta_utils.rb +44 -0
  37. data/lib/mss/core/model.rb +61 -0
  38. data/lib/mss/core/naming.rb +29 -0
  39. data/lib/mss/core/option_grammar.rb +737 -0
  40. data/lib/mss/core/options/json_serializer.rb +81 -0
  41. data/lib/mss/core/options/validator.rb +154 -0
  42. data/lib/mss/core/options/xml_serializer.rb +117 -0
  43. data/lib/mss/core/page_result.rb +74 -0
  44. data/lib/mss/core/policy.rb +938 -0
  45. data/lib/mss/core/query_client.rb +40 -0
  46. data/lib/mss/core/query_error_parser.rb +23 -0
  47. data/lib/mss/core/query_request_builder.rb +46 -0
  48. data/lib/mss/core/query_response_parser.rb +34 -0
  49. data/lib/mss/core/region.rb +84 -0
  50. data/lib/mss/core/region_collection.rb +79 -0
  51. data/lib/mss/core/resource.rb +412 -0
  52. data/lib/mss/core/resource_cache.rb +39 -0
  53. data/lib/mss/core/response.rb +214 -0
  54. data/lib/mss/core/response_cache.rb +49 -0
  55. data/lib/mss/core/rest_error_parser.rb +23 -0
  56. data/lib/mss/core/rest_json_client.rb +39 -0
  57. data/lib/mss/core/rest_request_builder.rb +153 -0
  58. data/lib/mss/core/rest_response_parser.rb +65 -0
  59. data/lib/mss/core/rest_xml_client.rb +46 -0
  60. data/lib/mss/core/service_interface.rb +82 -0
  61. data/lib/mss/core/signers/base.rb +45 -0
  62. data/lib/mss/core/signers/cloud_front.rb +55 -0
  63. data/lib/mss/core/signers/s3.rb +158 -0
  64. data/lib/mss/core/signers/version_2.rb +71 -0
  65. data/lib/mss/core/signers/version_3.rb +85 -0
  66. data/lib/mss/core/signers/version_3_https.rb +60 -0
  67. data/lib/mss/core/signers/version_4/chunk_signed_stream.rb +190 -0
  68. data/lib/mss/core/signers/version_4.rb +227 -0
  69. data/lib/mss/core/uri_escape.rb +43 -0
  70. data/lib/mss/core/xml/frame.rb +245 -0
  71. data/lib/mss/core/xml/frame_stack.rb +84 -0
  72. data/lib/mss/core/xml/grammar.rb +306 -0
  73. data/lib/mss/core/xml/parser.rb +69 -0
  74. data/lib/mss/core/xml/root_frame.rb +64 -0
  75. data/lib/mss/core/xml/sax_handlers/libxml.rb +46 -0
  76. data/lib/mss/core/xml/sax_handlers/nokogiri.rb +55 -0
  77. data/lib/mss/core/xml/sax_handlers/ox.rb +40 -0
  78. data/lib/mss/core/xml/sax_handlers/rexml.rb +46 -0
  79. data/lib/mss/core/xml/stub.rb +122 -0
  80. data/lib/mss/core.rb +602 -0
  81. data/lib/mss/errors.rb +161 -0
  82. data/lib/mss/rails.rb +194 -0
  83. data/lib/mss/s3/access_control_list.rb +262 -0
  84. data/lib/mss/s3/acl_object.rb +263 -0
  85. data/lib/mss/s3/acl_options.rb +200 -0
  86. data/lib/mss/s3/bucket.rb +757 -0
  87. data/lib/mss/s3/bucket_collection.rb +161 -0
  88. data/lib/mss/s3/bucket_lifecycle_configuration.rb +472 -0
  89. data/lib/mss/s3/bucket_region_cache.rb +51 -0
  90. data/lib/mss/s3/bucket_tag_collection.rb +110 -0
  91. data/lib/mss/s3/bucket_version_collection.rb +78 -0
  92. data/lib/mss/s3/cipher_io.rb +119 -0
  93. data/lib/mss/s3/client/xml.rb +265 -0
  94. data/lib/mss/s3/client.rb +2076 -0
  95. data/lib/mss/s3/config.rb +60 -0
  96. data/lib/mss/s3/cors_rule.rb +107 -0
  97. data/lib/mss/s3/cors_rule_collection.rb +193 -0
  98. data/lib/mss/s3/data_options.rb +190 -0
  99. data/lib/mss/s3/encryption_utils.rb +145 -0
  100. data/lib/mss/s3/errors.rb +93 -0
  101. data/lib/mss/s3/multipart_upload.rb +353 -0
  102. data/lib/mss/s3/multipart_upload_collection.rb +75 -0
  103. data/lib/mss/s3/object_collection.rb +355 -0
  104. data/lib/mss/s3/object_metadata.rb +102 -0
  105. data/lib/mss/s3/object_upload_collection.rb +76 -0
  106. data/lib/mss/s3/object_version.rb +153 -0
  107. data/lib/mss/s3/object_version_collection.rb +88 -0
  108. data/lib/mss/s3/paginated_collection.rb +74 -0
  109. data/lib/mss/s3/policy.rb +73 -0
  110. data/lib/mss/s3/prefix_and_delimiter_collection.rb +46 -0
  111. data/lib/mss/s3/prefixed_collection.rb +84 -0
  112. data/lib/mss/s3/presign_v4.rb +135 -0
  113. data/lib/mss/s3/presigned_post.rb +574 -0
  114. data/lib/mss/s3/region_detection.rb +75 -0
  115. data/lib/mss/s3/request.rb +61 -0
  116. data/lib/mss/s3/s3_object.rb +1795 -0
  117. data/lib/mss/s3/tree/branch_node.rb +67 -0
  118. data/lib/mss/s3/tree/child_collection.rb +103 -0
  119. data/lib/mss/s3/tree/leaf_node.rb +93 -0
  120. data/lib/mss/s3/tree/node.rb +21 -0
  121. data/lib/mss/s3/tree/parent.rb +86 -0
  122. data/lib/mss/s3/tree.rb +115 -0
  123. data/lib/mss/s3/uploaded_part.rb +81 -0
  124. data/lib/mss/s3/uploaded_part_collection.rb +83 -0
  125. data/lib/mss/s3/website_configuration.rb +101 -0
  126. data/lib/mss/s3.rb +161 -0
  127. data/lib/mss/version.rb +16 -0
  128. data/lib/mss-sdk.rb +2 -0
  129. data/lib/mss.rb +14 -0
  130. data/rails/init.rb +14 -0
  131. metadata +201 -0
@@ -0,0 +1,757 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ #
8
+ # or in the "license" file accompanying this file. This file is
9
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10
+ # ANY KIND, either express or implied. See the License for the specific
11
+ # language governing permissions and limitations under the License.
12
+
13
+ module MSS
14
+ class S3
15
+
16
+ # Represents a bucket in S3.
17
+ #
18
+ # # Creating Buckets
19
+ #
20
+ # You create a bucket by name. Bucket names must be globally unique
21
+ # and must be DNS compatible.
22
+ #
23
+ # s3 = MSS::S3.new
24
+ # bucket = s3.buckets.create('dns-compat-bucket-name')
25
+ #
26
+ # # Getting a Bucket
27
+ #
28
+ # You can create a reference to a bucket, given its name.
29
+ #
30
+ # bucket = s3.buckets['bucket-name'] # makes no request
31
+ # bucket.exists? #=> returns true/false
32
+ #
33
+ # # Enumerating Buckets
34
+ #
35
+ # The {BucketCollection} class is enumerable.
36
+ #
37
+ # s3.buckets.each do |bucket|
38
+ # puts bucket.name
39
+ # end
40
+ #
41
+ # # Deleting a Bucket
42
+ #
43
+ # You can delete an empty bucket you own.
44
+ #
45
+ # bucket = s3.buckets.create('my-temp-bucket')
46
+ # bucket.objects['abc'].write('xyz')
47
+ #
48
+ # bucket.clear! # deletes all object versions in batches
49
+ # bucket.delete
50
+ #
51
+ # You can alternatively call {#delete!} which will clear
52
+ # the bucket for your first.
53
+ #
54
+ # bucket.delete!
55
+ #
56
+ # # Objects
57
+ #
58
+ # Given a bucket you can access its objects, either by key or by
59
+ # enumeration.
60
+ #
61
+ # bucket.objects['key'] #=> makes no request, returns an S3Object
62
+ #
63
+ # bucket.objects.each do |obj|
64
+ # puts obj.key
65
+ # end
66
+ #
67
+ # See {ObjectCollection} and {S3Object} for more information on working
68
+ # with objects.
69
+ #
70
+ # # Website Configuration
71
+ #
72
+ # It is easy to enable website hosting for a bucket.
73
+ #
74
+ # bucket.configure_website
75
+ #
76
+ # You can specify the index and error documents by passing a block.
77
+ # If your bucket is already configured as a website, the current
78
+ # configuration will be yielded. If you bucket it not currently
79
+ # configured as a website, a new configuration will be yielded
80
+ # with default values.
81
+ #
82
+ # bucket.configure_website do |cfg|
83
+ # cfg.index_document_suffix = 'index.html'
84
+ # cfg.error_document_key = 'error.html'
85
+ # end
86
+ #
87
+ # You can disable website hosting two ways:
88
+ #
89
+ # bucket.remove_website_configuration
90
+ # bucket.website_configuration = nil
91
+ #
92
+ # You can use {#website_configuration=} to copy a website configuration
93
+ # from one bucket to another.
94
+ #
95
+ # bucket.website_configuration = other_bucket.website_configuration
96
+ #
97
+ # # Bucket Policies and ACLs
98
+ #
99
+ # You can control access to your bucket and its contents a number
100
+ # of ways. You can specify a bucket ACL (access control list)
101
+ # or a bucket policy.
102
+ #
103
+ # ## ACLs
104
+ #
105
+ # ACLs control access to your bucket and its contents via a list of
106
+ # grants and grantees.
107
+ #
108
+ # ### Canned ACLs
109
+ #
110
+ # The simplest way to specify an ACL is to use one of Amazon's "canned"
111
+ # ACLs. Amazon accepts the following canned ACLs:
112
+ #
113
+ # * `:private`
114
+ # * `:public_read`
115
+ # * `:public_read_write`
116
+ # * `:authenticated_read`
117
+ # * `:bucket_owner_read`
118
+ # * `:bucket_owner_full_control`
119
+ #
120
+ # You can specify a the ACL at bucket creation or later update a bucket.
121
+ #
122
+ # # at create time, defaults to :private when not specified
123
+ # bucket = s3.buckets.create('name', :acl => :public_read)
124
+ #
125
+ # # replacing an existing bucket ACL
126
+ # bucket.acl = :private
127
+ #
128
+ # ### Grants
129
+ #
130
+ # Alternatively you can specify a hash of grants. Each entry in the
131
+ # `:grant` hash has a grant (key) and a list of grantees (values).
132
+ # Valid grant keys are:
133
+ #
134
+ # * `:grant_read`
135
+ # * `:grant_write`
136
+ # * `:grant_read_acp`
137
+ # * `:grant_write_acp`
138
+ # * `:grant_full_control`
139
+ #
140
+ # Each grantee can be a String, Hash or array of strings or hashes.
141
+ # The following example uses grants to provide public read
142
+ # to everyone while providing full control to a user by email address
143
+ # and to another by their account id (cannonical user id).
144
+ #
145
+ # bucket = s3.buckets.create('name', :grants => {
146
+ # :grant_read => [
147
+ # { :uri => "http://acs.amazonmss.com/groups/global/AllUsers" },
148
+ # ],
149
+ # :grant_full_control => [
150
+ # { :id => 'abc...mno' } # cannonical user id
151
+ # { :email_address => 'foo@bar.com' }, # email address
152
+ # ]
153
+ # })
154
+ #
155
+ # ### ACL Object
156
+ #
157
+ # Lastly, you can build an ACL object and use a Ruby DSL to specify grants
158
+ # and grantees. See {ACLObject} for more information.
159
+ #
160
+ # # updating an existing bucket acl using ACLObject
161
+ # bucket.acl.change do |acl|
162
+ # acl.grants.reject! do |g|
163
+ # g.grantee.canonical_user_id != bucket.owner.id
164
+ # end
165
+ # end
166
+ #
167
+ # ## Policies
168
+ #
169
+ # You can also work with bucket policies.
170
+ #
171
+ # policy = MSS::S3::Policy.new
172
+ # policy.allow(
173
+ # :actions => [:put_object, :get_object]
174
+ # :resources => [bucket]
175
+ # :principals => :any)
176
+ #
177
+ # bucket.policy = policy
178
+ #
179
+ # See {Core::Policy} and {S3::Policy} for more information on build
180
+ # policy objects.
181
+ #
182
+ # # Versioned Buckets
183
+ #
184
+ # You can enable versioning on a bucket you control. When versioning
185
+ # is enabled, S3 will keep track of each version of each object you
186
+ # write to the bucket (even deletions).
187
+ #
188
+ # bucket.versioning_enabled? #=> false
189
+ # bucket.enable_versioning
190
+ # # there is also a #suspend_versioning method
191
+ #
192
+ # obj = bucket.objects['my-obj']
193
+ # obj.write('a')
194
+ # obj.write('b')
195
+ # obj.delete
196
+ # obj.write('c')
197
+ #
198
+ # obj.versions.each do |obj_version|
199
+ # if obj_version.delete_marker?
200
+ # puts obj_version.read
201
+ # else
202
+ # puts "- DELETE MARKER"
203
+ # end
204
+ # end
205
+ #
206
+ # Alternatively you can enumerate all versions of all objects in your
207
+ # bucket.
208
+ #
209
+ # bucket.versions.each do |obj_version|
210
+ # puts obj_version.key ` " : " ` obj_version.version_id
211
+ # end
212
+ #
213
+ # See {BucketVersionCollection}, {ObjectVersionCollection} and
214
+ # {ObjectVersion} for more information on working with objects in
215
+ # a versioned bucket. Also see the S3 documentation for information
216
+ # on object versioning.
217
+ #
218
+ class Bucket
219
+
220
+ include Core::Model
221
+ include ACLOptions
222
+
223
+ # @param [String] name
224
+ # @param [Hash] options
225
+ # @option options [String] :owner (nil) The owner id of this bucket.
226
+ def initialize(name, options = {})
227
+ # the S3 docs disagree with what the service allows,
228
+ # so it's not safe to toss out invalid bucket names
229
+ # S3::Client.validate_bucket_name!(name)
230
+ @name = name
231
+ @owner = options[:owner]
232
+ super
233
+ end
234
+
235
+ # @return [String] The bucket name
236
+ attr_reader :name
237
+
238
+ # Returns the url for this bucket.
239
+ # @return [String] url to the bucket
240
+ def url(options = {})
241
+ protocol = options.fetch(:secure, false) ? "https://" : "http://"
242
+ if client.dns_compatible_bucket_name?(name)
243
+ # "#{protocol}#{name}.s3.amazonmss.com/"
244
+ "#{protocol}#{name}.mtmos.com/"
245
+ else
246
+ # "#{protocol}s3.amazonmss.com/#{name}/"
247
+ "#{protocol}mtmos.com/#{name}/"
248
+ end
249
+ end
250
+
251
+ # @return [Boolean] Returns true if the bucket has no objects
252
+ # (this includes versioned objects that are delete markers).
253
+ def empty?
254
+ # versions.first ? false : true
255
+ objects.first ? false : true
256
+ end
257
+
258
+ # @return [String,nil] Returns the location constraint for a bucket
259
+ # (if it has one), nil otherwise.
260
+ # def location_constraint
261
+ # client.get_bucket_location(:bucket_name => name).location_constraint
262
+ # end
263
+
264
+ # Configure the current bucket as a website.
265
+ #
266
+ # bucket.configure_website
267
+ #
268
+ # If you pass a block, the website configuration object
269
+ # will be yielded. You can modify it before it is saved.
270
+ #
271
+ # bucket.configure_website do |cfg|
272
+ # cfg.index_document_suffix = 'index.html'
273
+ # cfg.error_document_key = 'error.html'
274
+ # end
275
+ #
276
+ # If the bucket already has a website configuration, it will be loaded
277
+ # and yielded. This makes it possible to modify an existing
278
+ # configuration.
279
+ #
280
+ # # only rename the error document
281
+ # bucket.configure_website do |cfg|
282
+ # cfg.error_document_key = 'oops.html'
283
+ # end
284
+ #
285
+ # @yieldparam [WebsiteConfiguration] website_config
286
+ # @return [WebsiteConfiguration]
287
+ # @see #website_configuration
288
+ # @see #website_configuration=
289
+ # @see #remove_website_configuration
290
+ # @see #website?
291
+ # def configure_website &block
292
+ # website_config = self.website_configuration
293
+ # website_config ||= WebsiteConfiguration.new
294
+ # yield(website_config) if block_given?
295
+ # self.website_configuration = website_config
296
+ # end
297
+
298
+ # Returns the bucket website configuration. Returns `nil` if the bucket
299
+ # is not configured as a website.
300
+ # @return [WebsiteConfiguration,nil]
301
+ # @see #configure_website
302
+ # @see #website_configuration=
303
+ # @see #remove_website_configuration
304
+ # @see #website?
305
+ # def website_configuration
306
+ # resp = client.get_bucket_website(:bucket_name => name)
307
+ # WebsiteConfiguration.new(resp.data)
308
+ # rescue Errors::NoSuchWebsiteConfiguration
309
+ # nil
310
+ # end
311
+
312
+ # Sets the website configuration. Deletes the configuration if
313
+ # `nil` is passed.
314
+ # @param [WebsiteConfiguration,nil] website_configuration
315
+ # @see #configure_website
316
+ # @see #website_configuration
317
+ # @see #remove_website_configuration
318
+ # @see #website?
319
+ # def website_configuration= website_configuration
320
+ # if website_configuration
321
+ # client_opts = website_configuration.to_hash
322
+ # client_opts[:bucket_name] = name
323
+ # client.put_bucket_website(client_opts)
324
+ # else
325
+ # remove_website_configuration
326
+ # end
327
+ # end
328
+
329
+ # @return [nil] Deletes the bucket website configuration.
330
+ # @see #configure_website
331
+ # @see #website_configuration
332
+ # @see #website_configuration=
333
+ # @see #website?
334
+ # def remove_website_configuration
335
+ # client.delete_bucket_website(:bucket_name => name)
336
+ # @website_configuration = false
337
+ # nil
338
+ # end
339
+
340
+ # @return [Boolean] Returns `true` if this bucket is configured as
341
+ # a website.
342
+ # @see #configure_website
343
+ # @see #website_configuration
344
+ # @see #website_configuration=
345
+ # @see #remove_website_configuration
346
+ # def website?
347
+ # !!website_configuration
348
+ # end
349
+
350
+ # Returns the tags for this bucket.
351
+ #
352
+ # tags = bucket.tags
353
+ # #=> <MSS::S3::BucketTagCollection>
354
+ #
355
+ # # adds a tag to the bucket
356
+ # tags['foo'] = 'abc'
357
+ #
358
+ # # replaces all tags
359
+ # tags.set('new' => 'tags')
360
+ #
361
+ # # removes all tags from the bucket
362
+ # tags.clear
363
+ #
364
+ # # returns tags as a hash
365
+ # tags.to_h
366
+ #
367
+ # @return [BucketTagCollection] Returns a collection that represents
368
+ # the tags for this bucket.
369
+ #
370
+ # def tags
371
+ # BucketTagCollection.new(self)
372
+ # end
373
+
374
+ # Sets the tags for this bucket.
375
+ #
376
+ # bucket.tags = { 'contents' => 'photots' }
377
+ #
378
+ # You can remove all tags for the bucket by passing an empty
379
+ # hash or `nil`.
380
+ #
381
+ # bucket.tags = nil # {} also deletes all tags
382
+ # bucket.tags
383
+ # #=> {}
384
+ #
385
+ # @param [Hash,nil] tags The tags to set on this bucket.
386
+ #
387
+ # def tags= tags
388
+ # self.tags.set(tags)
389
+ # end
390
+
391
+ # @return [CORSRuleCollection] Returns a collection that can be
392
+ # used to manage (add, edit and delete) CORS rules for this bucket.
393
+ # def cors
394
+ # CORSRuleCollection.new(self)
395
+ # end
396
+
397
+ # Sets the bucket CORS rules.
398
+ # @param (see CORSRuleCollection#set)
399
+ # @see CORSRuleCollection#set
400
+ # def cors= *rules
401
+ # self.cors.set(*rules)
402
+ # end
403
+
404
+ # Enables versioning on this bucket.
405
+ #
406
+ # @option opts [String] :mfa_delete Set to 'Enabled' or 'Disabled'
407
+ # to control the state of MFA delete on the bucket versioning.
408
+ # Setting this option requires the :mfa option to also be set.
409
+ #
410
+ # @option opts [String] :mfa The serial number and current token code of
411
+ # the Multi-Factor Authentication (MFA) device for the user. Format
412
+ # is "SERIAL TOKEN" - with a space between the serial and token.
413
+ #
414
+ # @return [nil]
415
+ # def enable_versioning(opts = {})
416
+ # client.set_bucket_versioning(
417
+ # :bucket_name => @name,
418
+ # :state => :enabled,
419
+ # :mfa_delete => opts[:mfa_delete],
420
+ # :mfa => opts[:mfa])
421
+ # nil
422
+ # end
423
+
424
+ # Suspends versioning on this bucket.
425
+ #
426
+ # @option opts [String] :mfa_delete Set to 'Enabled' or 'Disabled'
427
+ # to control the state of MFA delete on the bucket versioning.
428
+ # Setting this option requires the :mfa option to also be set.
429
+ #
430
+ # @option opts [String] :mfa The serial number and current token code of
431
+ # the Multi-Factor Authentication (MFA) device for the user. Format
432
+ # is "SERIAL TOKEN" - with a space between the serial and token.
433
+ #
434
+ # @return [nil]
435
+ # def suspend_versioning(opts = {})
436
+ # client.set_bucket_versioning(
437
+ # :bucket_name => @name,
438
+ # :state => :suspended,
439
+ # :mfa_delete => opts[:mfa_delete],
440
+ # :mfa => opts[:mfa])
441
+ # nil
442
+ # end
443
+
444
+ # @return [Boolean] returns `true` if version is enabled on this bucket.
445
+ def versioning_enabled?
446
+ versioning_state == :enabled
447
+ end
448
+ alias_method :versioned?, :versioning_enabled?
449
+
450
+ # Returns the versioning status for this bucket. States include:
451
+ #
452
+ # * `:enabled` - currently enabled
453
+ # * `:suspended` - currently suspended
454
+ # * `:unversioned` - versioning has never been enabled
455
+ #
456
+ # @return [Symbol] the versioning state
457
+ def versioning_state
458
+ client.get_bucket_versioning(:bucket_name => @name).status
459
+ end
460
+
461
+ # Deletes all objects from this bucket.
462
+ # @return [nil]
463
+ def clear!
464
+ # versions.each_batch do |versions|
465
+ # objects.delete(versions)
466
+ # end
467
+ objects.each do |object|
468
+ object.delete
469
+ end
470
+ end
471
+
472
+ # Deletes the current bucket. An error will be raised if the
473
+ # bucket is not empty.
474
+ # @return [nil]
475
+ def delete
476
+ client.delete_bucket(:bucket_name => @name)
477
+ nil
478
+ end
479
+
480
+ # Deletes all objects in a bucket and then deletes the bucket.
481
+ # @return [nil]
482
+ def delete!
483
+ clear!
484
+ delete
485
+ end
486
+
487
+ # @return [String] bucket owner id
488
+ def owner
489
+ @owner || client.list_buckets.owner
490
+ end
491
+
492
+ # @api private
493
+ def inspect
494
+ "#<MSS::S3::Bucket:#{name}>"
495
+ end
496
+
497
+ # @return [Boolean] Returns true if the two buckets have the same name.
498
+ def ==(other)
499
+ other.kind_of?(Bucket) && other.name == name
500
+ end
501
+
502
+ # @return [Boolean] Returns true if the two buckets have the same name
503
+ def eql?(other_bucket)
504
+ self == other_bucket
505
+ end
506
+
507
+ # @note This method only indicates if there is a bucket in S3, not
508
+ # if you have permissions to work with the bucket or not.
509
+ # @return [Boolean] Returns true if the bucket exists in S3.
510
+ def exists?
511
+ begin
512
+ versioned? # makes a get bucket request without listing contents
513
+ # raises a client error if the bucket doesn't exist or
514
+ # if you don't have permission to get the bucket
515
+ # versioning status.
516
+ true
517
+ rescue Errors::NoSuchBucket => e
518
+ false # bucket does not exist
519
+ rescue Errors::AccessDenied => e
520
+ true # bucket exists
521
+ end
522
+ end
523
+
524
+ # @return [ObjectCollection] Represents all objects(keys) in
525
+ # this bucket.
526
+ def objects
527
+ ObjectCollection.new(self)
528
+ end
529
+
530
+ # @return [BucketVersionCollection] Represents all of the versioned
531
+ # objects stored in this bucket.
532
+ # def versions
533
+ # BucketVersionCollection.new(self)
534
+ # end
535
+
536
+ # @return [MultipartUploadCollection] Represents all of the
537
+ # multipart uploads that are in progress for this bucket.
538
+ def multipart_uploads
539
+ MultipartUploadCollection.new(self)
540
+ end
541
+
542
+ # @api private
543
+ module ACLProxy
544
+
545
+ attr_accessor :bucket
546
+
547
+ def change
548
+ yield(self)
549
+ bucket.acl = self
550
+ end
551
+
552
+ end
553
+
554
+ # Returns the bucket's access control list. This will be an
555
+ # instance of AccessControlList, plus an additional `change`
556
+ # method:
557
+ #
558
+ # bucket.acl.change do |acl|
559
+ # acl.grants.reject! do |g|
560
+ # g.grantee.canonical_user_id != bucket.owner.id
561
+ # end
562
+ # end
563
+ #
564
+ # @return [AccessControlList]
565
+ def acl
566
+
567
+ resp = client.get_bucket_acl(:bucket_name => name)
568
+
569
+ acl = AccessControlList.new(resp.data)
570
+ acl.extend ACLProxy
571
+ acl.bucket = self
572
+ acl
573
+
574
+ end
575
+
576
+ # Sets the bucket's ACL (access control list). You can provide an ACL
577
+ # in a number of different formats.
578
+ # @param (see ACLOptions#acl_options)
579
+ # @return [nil]
580
+ # def acl= acl
581
+ # client.set_bucket_acl(acl_options(acl).merge(:bucket_name => name))
582
+ # nil
583
+ # end
584
+ def set_acl_public_read
585
+ client.set_bucket_acl(acl_options(:public_read).merge(:bucket_name => name))
586
+ nil
587
+ end
588
+
589
+ def set_acl_private
590
+ client.set_bucket_acl(acl_options(:private).merge(:bucket_name => name))
591
+ nil
592
+ end
593
+
594
+ # @api private
595
+ # module PolicyProxy
596
+ #
597
+ # attr_accessor :bucket
598
+ #
599
+ # def change
600
+ # yield(self)
601
+ # bucket.policy = self
602
+ # end
603
+ #
604
+ # def delete
605
+ # bucket.client.delete_bucket_policy(:bucket_name => bucket.name)
606
+ # end
607
+ #
608
+ # end
609
+
610
+ # Returns the bucket policy. This will be an instance of
611
+ # Policy. The returned policy will also have the methods of
612
+ # PolicyProxy mixed in, so you can use it to change the
613
+ # current policy or delete it, for example:
614
+ #
615
+ # if policy = bucket.policy
616
+ # # add a statement
617
+ # policy.change do |p|
618
+ # p.allow(...)
619
+ # end
620
+ #
621
+ # # delete the policy
622
+ # policy.delete
623
+ # end
624
+ #
625
+ # Note that changing the policy is not an atomic operation; it
626
+ # fetches the current policy, yields it to the block, and then
627
+ # sets it again. Therefore, it's possible that you may
628
+ # overwrite a concurrent update to the policy using this
629
+ # method.
630
+ #
631
+ # @return [Policy,nil] Returns the bucket policy (if it has one),
632
+ # or it returns `nil` otherwise.
633
+ # def policy
634
+ # resp = client.get_bucket_policy(:bucket_name => name)
635
+ # policy = Policy.from_json(resp.data[:policy])
636
+ # policy.extend(PolicyProxy)
637
+ # policy.bucket = self
638
+ # policy
639
+ # rescue Errors::NoSuchBucketPolicy => e
640
+ # nil
641
+ # end
642
+
643
+ # Sets the bucket's policy.
644
+ #
645
+ # @param policy The new policy. This can be a string (which
646
+ # is assumed to contain a valid policy expressed in JSON), a
647
+ # Policy object or any object that responds to `to_json`.
648
+ # @see Policy
649
+ # @return [nil]
650
+ # def policy=(policy)
651
+ # client.set_bucket_policy(:bucket_name => name, :policy => policy)
652
+ # nil
653
+ # end
654
+
655
+ # The primary interface for editing the lifecycle configuration.
656
+ # See {BucketLifecycleConfiguration} for more information.
657
+ #
658
+ # @example Adding rules to a bucket's lifecycle configuration
659
+ #
660
+ # bucket.lifecycle_configuration.update do
661
+ # add_rule 'cache-1/', 30
662
+ # add_rule 'cache-2/', 30
663
+ # end
664
+ #
665
+ # @example Deleting the lifecycle configuration
666
+ #
667
+ # bucket.lifecycle_configuration.clear
668
+ #
669
+ # @return [BucketLifecycleConfiguration]
670
+ #
671
+ # def lifecycle_configuration
672
+ # @lifecycle_cfg ||= BucketLifecycleConfiguration.new(self)
673
+ # end
674
+
675
+ # You can call this method if you prefer to build your own
676
+ # lifecycle configuration.
677
+ #
678
+ # bucket.lifecycle_configuration = <<-XML
679
+ # <LifecycleConfiguration>
680
+ # ...
681
+ # </LifecycleConfiguration>
682
+ # XML
683
+ #
684
+ # You can also use this method to copy a lifecycle configuration
685
+ # from another bucket.
686
+ #
687
+ # bucket.lifecycle_configuration = other_bucket.lifecycle_configuration
688
+ #
689
+ # If you call this method, passing nil, the lifecycle configuration
690
+ # for this bucket will be deleted.
691
+ #
692
+ # @param [String,Object] config You can pass an xml string or any
693
+ # other object that responds to #to_xml (e.g.
694
+ # BucketLifecycleConfiguration).
695
+ #
696
+ # @return [nil]
697
+ #
698
+ # def lifecycle_configuration= config
699
+ #
700
+ # if config.nil?
701
+ #
702
+ # client_opts = {}
703
+ # client_opts[:bucket_name] = name
704
+ # client.delete_bucket_lifecycle_configuration(client_opts)
705
+ #
706
+ # @lifecycle_cfg = BucketLifecycleConfiguration.new(self, :empty => true)
707
+ #
708
+ # else
709
+ #
710
+ # xml = config.is_a?(String) ? config : config.to_xml
711
+ #
712
+ # client_opts = {}
713
+ # client_opts[:bucket_name] = name
714
+ # client_opts[:lifecycle_configuration] = xml
715
+ # client.set_bucket_lifecycle_configuration(client_opts)
716
+ #
717
+ # @lifecycle_cfg = BucketLifecycleConfiguration.new(self, :xml => xml)
718
+ #
719
+ # end
720
+ #
721
+ # nil
722
+ #
723
+ # end
724
+
725
+ # Returns a tree that allows you to expose the bucket contents
726
+ # like a directory structure.
727
+ #
728
+ # @see Tree
729
+ # @param [Hash] options
730
+ # @option options [String] :prefix (nil) Set prefix to choose where
731
+ # the top of the tree will be. A value of `nil` means
732
+ # that the tree will include all objects in the collection.
733
+ #
734
+ # @option options [String] :delimiter ('/') The string that separates
735
+ # each level of the tree. This is usually a directory separator.
736
+ #
737
+ # @option options [Boolean] :append (true) If true, the delimiter is
738
+ # appended to the prefix when the prefix does not already end
739
+ # with the delimiter.
740
+ #
741
+ # @return [Tree]
742
+ def as_tree options = {}
743
+ objects.as_tree(options)
744
+ end
745
+
746
+ # Generates fields for a presigned POST to this object. All
747
+ # options are sent to the PresignedPost constructor.
748
+ #
749
+ # @see PresignedPost
750
+ def presigned_post(options = {})
751
+ PresignedPost.new(self, options)
752
+ end
753
+
754
+ end
755
+
756
+ end
757
+ end