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,161 @@
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 collection of buckets.
17
+ #
18
+ # You can use this to create a bucket:
19
+ #
20
+ # s3.buckets.create("mybucket")
21
+ #
22
+ # You can get a handle for a specific bucket with indifferent
23
+ # access:
24
+ #
25
+ # bucket = s3.buckets[:mybucket]
26
+ # bucket = s3.buckets['mybucket']
27
+ #
28
+ # You can also use it to find out which buckets are in your account:
29
+ #
30
+ # s3.buckets.collect(&:name)
31
+ # #=> ['bucket1', 'bucket2', ...]
32
+ #
33
+ class BucketCollection
34
+
35
+ include Core::Model
36
+ include Enumerable
37
+
38
+ # Creates and returns a new Bucket. For example:
39
+ #
40
+ # @note If your bucket name contains one or more periods and it
41
+ # is hosted in a non-US region, you should make requests
42
+ # against the bucket using the S3 endpoint specific to the
43
+ # region in which your bucket resides. For example:
44
+ #
45
+ # s3 = MSS::S3.new(:region => "eu-west-1")
46
+ # bucket = s3.buckets.create("my.eu.bucket")
47
+ #
48
+ # For a full list of endpoints and regions, see
49
+ # Regions and Endpoints} in the Amazon Web Services General
50
+ # Reference.
51
+ #
52
+ # @example
53
+ #
54
+ # bucket = s3.buckets.create('my-bucket')
55
+ # bucket.name #=> "my-bucket"
56
+ # bucket.exists? #=> true
57
+ #
58
+ # @param [String] bucket_name
59
+ #
60
+ # @param [Hash] options
61
+ #
62
+ # @option options [String] :location_constraint (nil) The
63
+ # location where the bucket should be created. Defaults to
64
+ # the classic US region; however, if you configure a regional
65
+ # endpoint for Amazon S3 this option will default to the
66
+ # appropriate location constraint for the endpoint. For
67
+ # example:
68
+ #
69
+ # s3 = MSS::S3.new(:region => "us-west-1")
70
+ # bucket = s3.buckets.create("my-us-west-bucket")
71
+ # bucket.location_constraint # => "us-west-1"
72
+ #
73
+ # @option options [Symbol,String] :acl (:private) Sets the ACL of the
74
+ # bucket you are creating. Valid Values include:
75
+ # * `:private`
76
+ # * `:public_read`
77
+ # * `:public_read_write`
78
+ # * `:authenticated_read`
79
+ # * `:log_delivery_write`
80
+ #
81
+ # @option options [String] :grant_read
82
+ # @option options [String] :grant_write
83
+ # @option options [String] :grant_read_acp
84
+ # @option options [String] :grant_write_acp
85
+ # @option options [String] :grant_full_control
86
+ #
87
+ # @return [Bucket]
88
+ #
89
+ def create bucket_name, options = {}
90
+
91
+ # convert the symbolized-canned acl into the string version
92
+ if acl = options[:acl]
93
+ # options[:acl] = acl.to_s.tr('_', '-')
94
+ options[:acl] = 'private'
95
+ end
96
+
97
+ # auto set the location constraint for the user if it is not
98
+ # passed in and the endpoint is not the us-standard region. don't
99
+ # override the location constraint though, even it is wrong,
100
+ unless
101
+ config.s3_endpoint == 's3.amazonmss.com' or
102
+ options[:location_constraint]
103
+ then
104
+ constraint = guess_constraint
105
+ options[:location_constraint] = constraint if constraint
106
+ end
107
+
108
+ client.create_bucket(options.merge(:bucket_name => bucket_name))
109
+ bucket_named(bucket_name)
110
+
111
+ end
112
+
113
+ # Returns the Bucket with the given name.
114
+ #
115
+ # Makes no requests. The returned bucket object can
116
+ # be used to make requets for the bucket and its objects.
117
+ #
118
+ # @example
119
+ #
120
+ # bucket = s3.buckets[:mybucket],
121
+ # bucket = s3.buckets['mybucket'],
122
+ #
123
+ # @param [String] bucket_name
124
+ # @return [Bucket]
125
+ def [] bucket_name
126
+ bucket_named(bucket_name)
127
+ end
128
+
129
+ # Iterates the buckets in this collection.
130
+ #
131
+ # @example
132
+ #
133
+ # s3.buckets.each do |bucket|
134
+ # puts bucket.name
135
+ # end
136
+ #
137
+ # @return [nil]
138
+ def each &block
139
+ response = client.list_buckets
140
+ response.buckets.each do |b|
141
+ yield(bucket_named(b.name, response.owner))
142
+ end
143
+ nil
144
+ end
145
+
146
+ private
147
+
148
+ def bucket_named name, owner = nil
149
+ S3::Bucket.new(name.to_s, :owner => owner, :config => config)
150
+ end
151
+
152
+ def guess_constraint
153
+ case config.s3_endpoint
154
+ when 's3-eu-west-1.amazonmss.com' then 'EU'
155
+ when /^s3[.-](.*)\.amazonmss\.com/ then $1
156
+ end
157
+ end
158
+
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,472 @@
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
+ require 'nokogiri'
14
+
15
+ module MSS
16
+ class S3
17
+
18
+ # A lifecycle configuration specify {Rule rules} that manage the way
19
+ # Amazon S3 stores objects. The rules apply to objects whose keys match
20
+ # the rule's prefix.
21
+ #
22
+ # ## Rules
23
+ #
24
+ # A rule is comprised primarily of an id, prefix and set of
25
+ # configuration options. Configuration options on the rules can specify:
26
+ #
27
+ # * When to expire an object
28
+ # * When to transition an object to Glacier
29
+ # * Whether the rule is enabled or disabled
30
+ #
31
+ # See {Rule} for more information on all of the attributes and methods
32
+ # available for rules.
33
+ #
34
+ # ## Expiring Objects
35
+ #
36
+ # You can add a rule to a bucket lifecycle configuration using {#add_rule}
37
+ # inside of an {#update} block that will expire an object after a given
38
+ # number of days:
39
+ #
40
+ # # delete backups after they are 1 year old
41
+ # bucket.lifecycle_configuration.update do
42
+ # add_rule('backups/', :expiration_time => 365)
43
+ # end
44
+ #
45
+ # You can also define the rule to expire objects at a specific date:
46
+ #
47
+ # # delete backups on January 1st of next year
48
+ # bucket.lifecycle_configuration.update do
49
+ # date = Date.new(Time.now.year + 1, 01, 01)
50
+ # add_rule('backups/', :expiration_time => date)
51
+ # end
52
+ #
53
+ # ## Transitioning Objects to Glacier
54
+ #
55
+ # You can add a rule to a bucket lifecycle configuration using {#add_rule}
56
+ # inside of an {#update} block that will transition objects to Glacier
57
+ # after a given number of days:
58
+ #
59
+ # # move backups to Glacier after 3 days
60
+ # bucket.lifecycle_configuration.update do
61
+ # add_rule('backups/', :glacier_transition_time => 3)
62
+ # end
63
+ #
64
+ # You can also define the rule to transition objects at a specific date:
65
+ #
66
+ # # transition all backups on January 1st of next year
67
+ # bucket.lifecycle_configuration.update do
68
+ # date = Date.new(Time.now.year + 1, 01, 01)
69
+ # add_rule('backups/', :glacier_transition_time => date)
70
+ # end
71
+ #
72
+ # ## Replacing Rules
73
+ #
74
+ # If you prefer to completely replace a lifecycle configuration, call
75
+ # {#add_rule} inside a {#replace} block instead of an `#update` block:
76
+ #
77
+ # # replace all existing rules with the following
78
+ # bucket.lifecycle_configuration.replace do
79
+ # add_rule('backups/', :glacier_transition_time => 10)
80
+ # add_rule('temp/', :expiration_time => 30)
81
+ # end
82
+ #
83
+ # ## Removing Rules
84
+ #
85
+ # You can delete specific rules with {#remove_rule}.
86
+ #
87
+ # # delete all disabled rules
88
+ # bucket.lifecycle_configuration.update do
89
+ # rules.each do |rule|
90
+ # remove_rule(rule) if rule.disabled?
91
+ # end
92
+ # end
93
+ #
94
+ # You can also remove all rules in a single call with {#clear}:
95
+ #
96
+ # # remove all rules from this lifecycle configuration
97
+ # bucket.lifecycle_configuration.clear
98
+ #
99
+ # ## Editing Existing Rules
100
+ #
101
+ # You can also make changes to existing rules.
102
+ #
103
+ # # change the expiration days to 10 for EVERY rule
104
+ # bucket.lifecycle_configuration.update do
105
+ # rules.each do |rule|
106
+ # rule.expiration_time = 10
107
+ # end
108
+ # end
109
+ #
110
+ # Please be aware, if you add, remove or edit rules outside of an
111
+ # {#update} or {#replace} block, then you must call `#update` yourself
112
+ # or the changes will not be persisted.
113
+ #
114
+ class BucketLifecycleConfiguration
115
+
116
+ # @api private
117
+ def initialize bucket, options = {}
118
+ @bucket = bucket
119
+ @rules = parse_xml(options[:xml]) if options[:xml]
120
+ @rules = [] if options[:empty] == true
121
+ end
122
+
123
+ # @return [Bucket] Returns the bucket this lifecycle configuration
124
+ # belongs to.
125
+ attr_reader :bucket
126
+
127
+ # @return [Array<Hash>] Returns an array of rules.
128
+ def rules
129
+ @rules ||= begin
130
+ begin
131
+ opts = { :bucket_name => bucket.name }
132
+ response = bucket.client.get_bucket_lifecycle_configuration(opts)
133
+ parse_xml(response.http_response.body)
134
+ rescue Errors::NoSuchLifecycleConfiguration
135
+ []
136
+ end
137
+ end
138
+ end
139
+
140
+ # @overload add_rule(prefix, options = {})
141
+ # @param [String] prefix objects whose keys begin with this prefix
142
+ # will be affected by the rule.
143
+ #
144
+ # @option options [String] :id A unique ID for this rule. If an ID
145
+ # is not provided, one will be generated.
146
+ #
147
+ # @option options [Boolean] :disabled (false) By default, all rules
148
+ # will have the status of enabled. You can override this default
149
+ # by passing `:disabled` => true.
150
+ #
151
+ # @option options [Date, Integer] :expiration_time (nil) Indicates
152
+ # the lifetime for objects matching the given prefix.
153
+ #
154
+ # @option options [Date, Integer] :glacier_transition_time (nil)
155
+ # Indicates the time before objects matching the given prefix will
156
+ # be transitioned into the Amazon Glacier storage tier.
157
+ #
158
+ # @return [Rule] Returns the rule that was added, as a {Rule} object.
159
+ def add_rule prefix, expiration_time = nil, options = {}
160
+ if Hash === expiration_time
161
+ options = expiration_time
162
+ else
163
+ options[:expiration_time] = expiration_time
164
+ end
165
+
166
+ id = options[:id] || SecureRandom.uuid
167
+ opts = {
168
+ :status => options[:disabled] == true ? 'Disabled' : 'Enabled',
169
+ :expiration_time => options[:expiration_time],
170
+ :glacier_transition_time => options[:glacier_transition_time],
171
+ :noncurrent_version_transition_days => options[:noncurrent_version_transition_days],
172
+ :noncurrent_version_expiration_days => options[:noncurrent_version_expiration_days]
173
+ }
174
+ rule = Rule.new(self, id, prefix, opts)
175
+ self.rules << rule
176
+ rule
177
+ end
178
+
179
+ # Removes a single rule. You can pass a rule id or a {Rule}
180
+ # object.
181
+ #
182
+ # # remove a single rule by its ID
183
+ # bucket.lifecycle_configuration.update do
184
+ # remove_rule('rule-id')
185
+ # end
186
+ #
187
+ # # remove all disabled rules
188
+ # bucket.lifecycle_configuration.update do
189
+ # rules.each do |rule|
190
+ # remove_rule(rule) if rule.disabled?
191
+ # end
192
+ # end
193
+ #
194
+ # If you call #remove_rule outside an update block
195
+ # you need to call #update to save the changes.
196
+ #
197
+ # @param [Rule,String] rule_or_rule_id
198
+ #
199
+ # @return [nil]
200
+ #
201
+ def remove_rule rule_or_rule_id
202
+ rule_id = rule_or_rule_id
203
+ if rule_id.nil?
204
+ raise ArgumentError, "expected a rule or rule id, got nil"
205
+ end
206
+ rule_id = rule_id.id unless rule_id.is_a?(String)
207
+ @rules = rules.select{|r| r.id != rule_id }
208
+ nil
209
+ end
210
+
211
+ # Saves changes made to this lifecycle configuration.
212
+ #
213
+ # # set the number of days before expiration for all rules to 10
214
+ # config = bucket.lifecycle_configuration
215
+ # config.rules.each do |rule|
216
+ # rule.expiration_time = 10
217
+ # end
218
+ # config.update
219
+ #
220
+ # You can call #update with a block. Changes are persisted at the
221
+ # end of the block.
222
+ #
223
+ # # shorter version of the example above
224
+ # bucket.lifecycle_configuration.update do
225
+ # rules.each {|rule| rule.expiration_time = 10 }
226
+ # end
227
+ #
228
+ # A block method for updating a BucketLifecycleConfiguration.
229
+ # All modifications made inside the block are persisted at the end of
230
+ # the block.
231
+ #
232
+ # # 1 request
233
+ # bucket.lifecycle_configuration.update do
234
+ # add_rule 'prefix/a', 10
235
+ # add_rule 'prefix/b', 5
236
+ # end
237
+ #
238
+ # # 2 requests
239
+ # bucket.lifecycle_configuration.add_rule 'prefix/a', 10
240
+ # bucket.lifecycle_configuration.add_rule 'prefix/b', 5
241
+ #
242
+ # @return [nil]
243
+ #
244
+ def update arg = {}, &block
245
+ begin
246
+ @batching = true
247
+ instance_exec(arg, &block) if block_given?
248
+ persist(true)
249
+ ensure
250
+ @batching = false
251
+ end
252
+ nil
253
+ end
254
+
255
+ # Yields to the given block. Before yielding, the current
256
+ # rules will be blanked out. This allows you to provide all
257
+ # new rules.
258
+ #
259
+ # When the block is complete, a single call will be made to save
260
+ # the new rules.
261
+ #
262
+ # bucket.lifecycle_configuration.rules.size #=> 3
263
+ #
264
+ # # replace the existing 3 rules with a single rule
265
+ # bucket.lifecycle_configuration.replace
266
+ # add_rule 'temp/', 10
267
+ # end
268
+ #
269
+ # bucket.lifecycle_configuration.rules.size #=> 1
270
+ def replace &block
271
+ @rules = []
272
+ update(&block)
273
+ end
274
+
275
+ def clear
276
+ @rules = []
277
+ bucket.lifecycle_configuration = nil
278
+ end
279
+ alias_method :remove, :clear
280
+
281
+ # @return [String] Returns an xml string representation of this
282
+ # bucket lifecycle configuration.
283
+ def to_xml
284
+ Nokogiri::XML::Builder.new do |xml|
285
+ xml.LifecycleConfiguration do
286
+ rules.each do |rule|
287
+ xml.Rule do
288
+ xml.ID rule.id
289
+ xml.Prefix rule.prefix
290
+ xml.Status rule.status
291
+ xml.Expiration do
292
+ if Integer === rule.expiration_time
293
+ xml.Days rule.expiration_time
294
+ else
295
+ date = rule.expiration_time.to_s
296
+ xml.Date "#{date}T00:00:00Z"
297
+ end
298
+ end if rule.expiration_time
299
+ xml.Transition do
300
+ xml.StorageClass 'GLACIER'
301
+ if Integer === rule.glacier_transition_time
302
+ xml.Days rule.glacier_transition_time
303
+ else
304
+ date = rule.glacier_transition_time.to_s
305
+ xml.Date "#{date}T00:00:00Z"
306
+ end
307
+ end if rule.glacier_transition_time
308
+ xml.NoncurrentVersionTransition do
309
+ xml.StorageClass 'GLACIER'
310
+ xml.NoncurrentDays rule.noncurrent_version_transition_days
311
+ end if rule.noncurrent_version_transition_days
312
+ xml.NoncurrentVersionExpiration do
313
+ xml.NoncurrentDays rule.noncurrent_version_expiration_days
314
+ end if rule.noncurrent_version_expiration_days
315
+ end
316
+ end
317
+ end
318
+ end.doc.root.to_xml
319
+ end
320
+
321
+ protected
322
+ def persist force = false
323
+ unless @batching and force == false
324
+ if rules.empty?
325
+ bucket.lifecycle_configuration = nil
326
+ else
327
+ bucket.lifecycle_configuration = self
328
+ end
329
+ end
330
+ end
331
+
332
+ # Represents a single rule from an Amazon S3 bucket lifecycle
333
+ # configuration.
334
+ #
335
+ # # delete all objects with the prefix 'temporary/' after 10 days
336
+ # bucket.lifecycle_configuration.add_rule 'temporary/', 10
337
+ #
338
+ # # remove the rule created above
339
+ # bucket.lifecycle_configuration.remove_rule 'temporary/'
340
+ #
341
+ #
342
+ class Rule
343
+
344
+ # @api private
345
+ def initialize configuration, id, prefix, expiration_time = nil, status = nil
346
+ @configuration = configuration
347
+ @id = id
348
+ @prefix = prefix
349
+
350
+ if Hash === expiration_time
351
+ options = expiration_time
352
+ options.each do |key, value|
353
+ send("#{key}=", value) if respond_to?("#{key}=")
354
+ end
355
+ else
356
+ self.expiration_time = expiration_time
357
+ self.status = status
358
+ end
359
+ end
360
+
361
+ # @return [BucketLifecycleConfiguration]
362
+ attr_reader :configuration
363
+
364
+ # @return [String]
365
+ attr_reader :id
366
+
367
+ # @return [String]
368
+ attr_accessor :prefix
369
+
370
+ # @return [Date] the date the objects will expire
371
+ # @return [Integer] if the value is an integer, returns the number
372
+ # of days before the object will expire.
373
+ attr_reader :expiration_time
374
+
375
+ # Converts any time values to Date objects
376
+ def expiration_time=(value)
377
+ @expiration_time = convert_time_value(value)
378
+ end
379
+
380
+ alias expiration_days expiration_time
381
+ alias expiration_days= expiration_time=
382
+
383
+ # @return [Date] the date the objects will be
384
+ # transitioned into the Amazon Glacier storage tier.
385
+ # @return [Integer] if the value is an integer, returns the number
386
+ # of days before the object is transitioned into the Amazon Glacier
387
+ # storage tier.
388
+ attr_reader :glacier_transition_time
389
+
390
+ # Converts any time values to Date objects
391
+ def glacier_transition_time=(value)
392
+ @glacier_transition_time = convert_time_value(value)
393
+ end
394
+
395
+ # @return [Integer]
396
+ attr_accessor :noncurrent_version_transition_days
397
+
398
+ # @return [Integer]
399
+ attr_accessor :noncurrent_version_expiration_days
400
+
401
+ # @return [String] Returns the rule status, 'Enabled' or 'Disabled'
402
+ attr_accessor :status
403
+
404
+ def enabled?
405
+ status == 'Enabled'
406
+ end
407
+
408
+ def enable!
409
+ self.status = 'Enabled'
410
+ end
411
+
412
+ def disabled?
413
+ status == 'Disabled'
414
+ end
415
+
416
+ def disabled!
417
+ self.status = 'Disabled'
418
+ end
419
+
420
+ # @api private
421
+ def eql? other
422
+ other.is_a?(Rule) and
423
+ other.configuration.bucket == configuration.bucket and
424
+ other.id == id and
425
+ other.prefix == prefix and
426
+ other.expiration_time == expiration_time and
427
+ other.glacier_transition_time == glacier_transition_time and
428
+ other.status == status and
429
+ other.noncurrent_version_transition_days == noncurrent_version_transition_days and
430
+ other.noncurrent_version_expiration_days == noncurrent_version_expiration_days
431
+ end
432
+ alias_method :==, :eql?
433
+
434
+ private
435
+
436
+ # If an integer, returns the integer as days, otherwise
437
+ # converts any time-like values into Date objects
438
+ # @return [Integer] if the value is an integer
439
+ # @return [Date] if the value is a time-like object
440
+ # @return [nil] if the value is nil
441
+ def convert_time_value(value)
442
+ return nil if value.nil?
443
+ return value if value.is_a?(Integer)
444
+ Date.parse(value.to_s)
445
+ end
446
+
447
+ end
448
+
449
+ protected
450
+
451
+ def parse_xml xml
452
+ Client::XML::GetBucketLifecycleConfiguration.parse(xml).rules.map do |r|
453
+ opts = { :status => r[:status] }
454
+
455
+ if r[:expiration]
456
+ opts[:expiration_time] =
457
+ r[:expiration][:days] || r[:expiration][:date]
458
+ end
459
+
460
+ if r[:transition]
461
+ opts[:glacier_transition_time] =
462
+ r[:transition][:days] || r[:transition][:date]
463
+ end
464
+
465
+ Rule.new(self, r[:id], r[:prefix], opts)
466
+ end
467
+ end
468
+
469
+ end
470
+
471
+ end
472
+ end
@@ -0,0 +1,51 @@
1
+ require 'thread'
2
+
3
+ module MSS
4
+ class S3
5
+ class BucketRegionCache
6
+
7
+ def initialize
8
+ @regions = {}
9
+ @mutex = Mutex.new
10
+ end
11
+
12
+ def [](bucket_name)
13
+ @mutex.synchronize do
14
+ @regions[bucket_name]
15
+ end
16
+ end
17
+
18
+ def []=(bucket_name, region_name)
19
+ @mutex.synchronize do
20
+ @regions[bucket_name] = region_name
21
+ end
22
+ end
23
+
24
+ def delete(bucket_name)
25
+ @mutex.synchronize do
26
+ @regions[bucket_name] = region_name
27
+ end
28
+ end
29
+
30
+ def update!(bucket_regions)
31
+ @mutex.synchronize do
32
+ @regions.update!(bucket_regions)
33
+ end
34
+ end
35
+
36
+ def clear
37
+ @mutex.synchronize do
38
+ @regions = {}
39
+ end
40
+ end
41
+
42
+ def to_hash
43
+ @mutex.synchronize do
44
+ @regions.dup
45
+ end
46
+ end
47
+ alias to_h to_hash
48
+
49
+ end
50
+ end
51
+ end