azure-storage 0.10.0.preview

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/lib/azure/storage.rb +58 -0
  3. data/lib/azure/storage/autoload.rb +71 -0
  4. data/lib/azure/storage/blob/append.rb +154 -0
  5. data/lib/azure/storage/blob/blob.rb +821 -0
  6. data/lib/azure/storage/blob/blob_service.rb +510 -0
  7. data/lib/azure/storage/blob/block.rb +264 -0
  8. data/lib/azure/storage/blob/container.rb +552 -0
  9. data/lib/azure/storage/blob/page.rb +380 -0
  10. data/lib/azure/storage/blob/serialization.rb +297 -0
  11. data/lib/azure/storage/client.rb +185 -0
  12. data/lib/azure/storage/configurable.rb +137 -0
  13. data/lib/azure/storage/core.rb +33 -0
  14. data/lib/azure/storage/core/auth/shared_access_signature.rb +27 -0
  15. data/lib/azure/storage/core/auth/shared_access_signature_generator.rb +194 -0
  16. data/lib/azure/storage/core/auth/shared_access_signature_signer.rb +49 -0
  17. data/lib/azure/storage/core/auth/shared_key.rb +125 -0
  18. data/lib/azure/storage/core/auth/shared_key_lite.rb +55 -0
  19. data/lib/azure/storage/core/auth/signer.rb +60 -0
  20. data/lib/azure/storage/core/autoload.rb +35 -0
  21. data/lib/azure/storage/core/client_options.rb +334 -0
  22. data/lib/azure/storage/core/client_options_error.rb +39 -0
  23. data/lib/azure/storage/core/constants.rb +1077 -0
  24. data/lib/azure/storage/core/error.rb +47 -0
  25. data/lib/azure/storage/core/filtered_service.rb +54 -0
  26. data/lib/azure/storage/core/http/debug_filter.rb +45 -0
  27. data/lib/azure/storage/core/http/http_error.rb +95 -0
  28. data/lib/azure/storage/core/http/http_filter.rb +62 -0
  29. data/lib/azure/storage/core/http/http_request.rb +182 -0
  30. data/lib/azure/storage/core/http/http_response.rb +105 -0
  31. data/lib/azure/storage/core/http/retry_policy.rb +83 -0
  32. data/lib/azure/storage/core/http/signer_filter.rb +42 -0
  33. data/lib/azure/storage/core/http_client.rb +63 -0
  34. data/lib/azure/storage/core/service.rb +55 -0
  35. data/lib/azure/storage/core/signed_service.rb +54 -0
  36. data/lib/azure/storage/core/sr.rb +83 -0
  37. data/lib/azure/storage/core/utility.rb +254 -0
  38. data/lib/azure/storage/queue/message.rb +39 -0
  39. data/lib/azure/storage/queue/queue.rb +37 -0
  40. data/lib/azure/storage/queue/queue_service.rb +580 -0
  41. data/lib/azure/storage/queue/serialization.rb +113 -0
  42. data/lib/azure/storage/service/access_policy.rb +35 -0
  43. data/lib/azure/storage/service/cors.rb +36 -0
  44. data/lib/azure/storage/service/cors_rule.rb +46 -0
  45. data/lib/azure/storage/service/enumeration_results.rb +30 -0
  46. data/lib/azure/storage/service/logging.rb +45 -0
  47. data/lib/azure/storage/service/metrics.rb +43 -0
  48. data/lib/azure/storage/service/retention_policy.rb +35 -0
  49. data/lib/azure/storage/service/serialization.rb +308 -0
  50. data/lib/azure/storage/service/signed_identifier.rb +39 -0
  51. data/lib/azure/storage/service/storage_service.rb +131 -0
  52. data/lib/azure/storage/service/storage_service_properties.rb +46 -0
  53. data/lib/azure/storage/table/auth/shared_key.rb +68 -0
  54. data/lib/azure/storage/table/auth/shared_key_lite.rb +53 -0
  55. data/lib/azure/storage/table/batch.rb +339 -0
  56. data/lib/azure/storage/table/batch_response.rb +127 -0
  57. data/lib/azure/storage/table/edmtype.rb +136 -0
  58. data/lib/azure/storage/table/entity.rb +40 -0
  59. data/lib/azure/storage/table/guid.rb +33 -0
  60. data/lib/azure/storage/table/query.rb +121 -0
  61. data/lib/azure/storage/table/serialization.rb +117 -0
  62. data/lib/azure/storage/table/table_service.rb +571 -0
  63. data/lib/azure/storage/version.rb +46 -0
  64. metadata +329 -0
@@ -0,0 +1,380 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ require 'azure/storage/blob/blob'
25
+
26
+ module Azure::Storage
27
+ module Blob
28
+ # Public: Creates a new page blob. Note that calling create_page_blob to create a page
29
+ # blob only initializes the blob. To add content to a page blob, call put_blob_pages method.
30
+ #
31
+ # ==== Attributes
32
+ #
33
+ # * +container+ - String. The container name.
34
+ # * +blob+ - String. The blob name.
35
+ # * +length+ - Integer. Specifies the maximum size for the page blob, up to 1 TB.
36
+ # The page blob size must be aligned to a 512-byte boundary.
37
+ # * +options+ - Hash. Optional parameters.
38
+ #
39
+ # ==== Options
40
+ #
41
+ # Accepted key/value pairs in options parameter are:
42
+ # * +:transactional_md5+ - String. An MD5 hash of the blob content. This hash is used to verify the integrity of the blob during transport.
43
+ # When this header is specified, the storage service checks the hash that has arrived with the one that was sent.
44
+ # If the two hashes do not match, the operation will fail with error code 400 (Bad Request).
45
+ # * +:content_type+ - String. Content type for the blob. Will be saved with blob.
46
+ # * +:content_encoding+ - String. Content encoding for the blob. Will be saved with blob.
47
+ # * +:content_language+ - String. Content language for the blob. Will be saved with blob.
48
+ # * +:content_md5+ - String. Content MD5 for the blob. Will be saved with blob.
49
+ # * +:cache_control+ - String. Cache control for the blob. Will be saved with blob.
50
+ # * +:content_disposition+ - String. Conveys additional information about how to process the response payload,
51
+ # and also can be used to attach additional metadata
52
+ # * +:metadata+ - Hash. Custom metadata values to store with the blob.
53
+ # * +:sequence_number+ - Integer. The sequence number is a user-controlled value that you can use to track requests.
54
+ # The value of the sequence number must be between 0 and 2^63 - 1.The default value is 0.
55
+ # * +:timeout+ - Integer. A timeout in seconds.
56
+ # * +:if_modified_since+ - String. A DateTime value. Specify this conditional header to create a new blob
57
+ # only if the blob has been modified since the specified date/time. If the blob has not been modified,
58
+ # the Blob service returns status code 412 (Precondition Failed).
59
+ # * +:if_unmodified_since+ - String. A DateTime value. Specify this conditional header to create a new blob
60
+ # only if the blob has not been modified since the specified date/time. If the blob has been modified,
61
+ # the Blob service returns status code 412 (Precondition Failed).
62
+ # * +:if_match+ - String. An ETag value. Specify an ETag value for this conditional header to create a new blob
63
+ # only if the blob's ETag value matches the value specified. If the values do not match,
64
+ # the Blob service returns status code 412 (Precondition Failed).
65
+ # * +:if_none_match+ - String. An ETag value. Specify an ETag value for this conditional header to create a new blob
66
+ # only if the blob's ETag value does not match the value specified. If the values are identical,
67
+ # the Blob service returns status code 412 (Precondition Failed).
68
+ #
69
+ # See http://msdn.microsoft.com/en-us/library/azure/dd179451.aspx
70
+ #
71
+ # Returns a Blob
72
+ def create_page_blob(container, blob, length, options={})
73
+ query = { }
74
+ StorageService.with_query query, 'timeout', options[:timeout].to_s if options[:timeout]
75
+
76
+ uri = blob_uri(container, blob, query)
77
+
78
+ headers = StorageService.service_properties_headers
79
+
80
+ # set x-ms-blob-type to PageBlob
81
+ StorageService.with_header headers, 'x-ms-blob-type', 'PageBlob'
82
+
83
+ # ensure content-length is 0 and x-ms-blob-content-length is the blob length
84
+ StorageService.with_header headers, 'Content-Length', 0.to_s
85
+ StorageService.with_header headers, 'x-ms-blob-content-length', length.to_s
86
+
87
+ # set x-ms-sequence-number from options (or default to 0)
88
+ StorageService.with_header headers, 'x-ms-sequence-number', (options[:sequence_number] || 0).to_s
89
+
90
+ # set the rest of the optional headers
91
+ StorageService.with_header headers, 'Content-MD5', options[:transactional_md5]
92
+ StorageService.with_header headers, 'x-ms-blob-content-type', options[:content_type]
93
+ StorageService.with_header headers, 'x-ms-blob-content-encoding', options[:content_encoding]
94
+ StorageService.with_header headers, 'x-ms-blob-content-language', options[:content_language]
95
+ StorageService.with_header headers, 'x-ms-blob-content-md5', options[:content_md5]
96
+ StorageService.with_header headers, 'x-ms-blob-cache-control', options[:cache_control]
97
+ StorageService.with_header headers, 'x-ms-blob-content-disposition', options[:content_disposition]
98
+
99
+ StorageService.add_metadata_to_headers options[:metadata], headers
100
+ add_blob_conditional_headers options, headers
101
+
102
+ # call PutBlob with empty body
103
+ response = call(:put, uri, nil, headers)
104
+
105
+ result = Serialization.blob_from_headers(response.headers)
106
+ result.name = blob
107
+
108
+ result
109
+ end
110
+
111
+ # Public: Creates a range of pages in a page blob.
112
+ #
113
+ # ==== Attributes
114
+ #
115
+ # * +container+ - String. Name of container
116
+ # * +blob+ - String. Name of blob
117
+ # * +start_range+ - Integer. Position of first byte of first page
118
+ # * +end_range+ - Integer. Position of last byte of of last page
119
+ # * +content+ - IO or String. Content to write. Length in bytes should equal end_range - start_range
120
+ # * +options+ - Hash. A collection of options.
121
+ #
122
+ # ==== Options
123
+ #
124
+ # Accepted key/value pairs in options parameter are:
125
+ # * +:if_sequence_number_le+ - Integer. If the blob's sequence number is less than or equal to the specified value, the request proceeds;
126
+ # otherwise it fails with the SequenceNumberConditionNotMet error (HTTP status code 412 - Precondition Failed).
127
+ # * +:if_sequence_number_lt+ - Integer. If the blob's sequence number is less than the specified value, the request proceeds;
128
+ # otherwise it fails with SequenceNumberConditionNotMet error (HTTP status code 412 - Precondition Failed).
129
+ # * +:if_sequence_number_eq+ - Integer. If the blob's sequence number is equal to the specified value, the request proceeds;
130
+ # otherwise it fails with SequenceNumberConditionNotMet error (HTTP status code 412 - Precondition Failed).
131
+ # * +:if_modified_since+ - String. A DateTime value. Specify this conditional header to write the page only if
132
+ # the blob has been modified since the specified date/time. If the blob has not been modified,
133
+ # the Blob service returns status code 412 (Precondition Failed).
134
+ # * +:if_unmodified_since+ - String. A DateTime value. Specify this conditional header to write the page only if
135
+ # the blob has not been modified since the specified date/time. If the blob has been modified,
136
+ # the Blob service returns status code 412 (Precondition Failed).
137
+ # * +:if_match+ - String. An ETag value. Specify an ETag value for this conditional header to write the page only if
138
+ # the blob's ETag value matches the value specified. If the values do not match,
139
+ # the Blob service returns status code 412 (Precondition Failed).
140
+ # * +:if_none_match+ - String. An ETag value. Specify an ETag value for this conditional header to write the page only if
141
+ # the blob's ETag value does not match the value specified. If the values are identical,
142
+ # the Blob service returns status code 412 (Precondition Failed).
143
+ # * +:timeout+ - Integer. A timeout in seconds.
144
+ #
145
+ # See http://msdn.microsoft.com/en-us/library/azure/ee691975.aspx
146
+ #
147
+ # Returns Blob
148
+ def put_blob_pages(container, blob, start_range, end_range, content, options={})
149
+ query = { 'comp' => 'page' }
150
+ StorageService.with_query query, 'timeout', options[:timeout].to_s if options[:timeout]
151
+
152
+ uri = blob_uri(container, blob, query)
153
+ headers = StorageService.service_properties_headers
154
+ StorageService.with_header headers, 'x-ms-range', "bytes=#{start_range}-#{end_range}"
155
+ StorageService.with_header headers, 'x-ms-page-write', 'update'
156
+
157
+ # clear default content type
158
+ StorageService.with_header headers, 'Content-Type', ''
159
+
160
+ # set optional headers
161
+ unless options.empty?
162
+ add_blob_conditional_headers options, headers
163
+ end
164
+
165
+ response = call(:put, uri, content, headers)
166
+
167
+ result = Serialization.blob_from_headers(response.headers)
168
+ result.name = blob
169
+
170
+ result
171
+ end
172
+
173
+ # Public: Clears a range of pages from the blob.
174
+ #
175
+ # ==== Attributes
176
+ #
177
+ # * +container+ - String. Name of container.
178
+ # * +blob+ - String. Name of blob.
179
+ # * +start_range+ - Integer. Position of first byte of first page.
180
+ # * +end_range+ - Integer. Position of last byte of of last page.
181
+ # * +options+ - Hash. Optional parameters.
182
+ #
183
+ # ==== Options
184
+ #
185
+ # Accepted key/value pairs in options parameter are:
186
+ # * +:timeout+ - Integer. A timeout in seconds.
187
+ # * +:if_modified_since+ - String. A DateTime value. Specify this conditional header to clear the page only if
188
+ # the blob has been modified since the specified date/time. If the blob has not been modified,
189
+ # the Blob service returns status code 412 (Precondition Failed).
190
+ # * +:if_unmodified_since+ - String. A DateTime value. Specify this conditional header to clear the page only if
191
+ # the blob has not been modified since the specified date/time. If the blob has been modified,
192
+ # the Blob service returns status code 412 (Precondition Failed).
193
+ # * +:if_match+ - String. An ETag value. Specify an ETag value for this conditional header to clear the page only if
194
+ # the blob's ETag value matches the value specified. If the values do not match,
195
+ # the Blob service returns status code 412 (Precondition Failed).
196
+ # * +:if_none_match+ - String. An ETag value. Specify an ETag value for this conditional header to clear the page only if
197
+ # the blob's ETag value does not match the value specified. If the values are identical,
198
+ # the Blob service returns status code 412 (Precondition Failed).
199
+ #
200
+ # See http://msdn.microsoft.com/en-us/library/azure/ee691975.aspx
201
+ #
202
+ # Returns Blob
203
+ def clear_blob_pages(container, blob, start_range, end_range, options={})
204
+ query = { 'comp' => 'page' }
205
+ StorageService.with_query query, 'timeout', options[:timeout].to_s if options[:timeout]
206
+
207
+ uri = blob_uri(container, blob, query)
208
+
209
+ headers = StorageService.service_properties_headers
210
+ StorageService.with_header headers, 'x-ms-range', "bytes=#{start_range}-#{end_range}"
211
+ StorageService.with_header headers, 'x-ms-page-write', 'clear'
212
+
213
+ # clear default content type
214
+ StorageService.with_header headers, 'Content-Type', ''
215
+
216
+ # set optional headers
217
+ unless options.empty?
218
+ add_blob_conditional_headers options, headers
219
+ end
220
+
221
+ response = call(:put, uri, nil, headers)
222
+
223
+ result = Serialization.blob_from_headers(response.headers)
224
+ result.name = blob
225
+
226
+ result
227
+ end
228
+
229
+ # Public: Returns a list of active page ranges for a page blob. Active page ranges are
230
+ # those that have been populated with data.
231
+ #
232
+ # ==== Attributes
233
+ #
234
+ # * +container+ - String. The container name.
235
+ # * +blob+ - String. The blob name.
236
+ # * +options+ - Hash. Optional parameters.
237
+ #
238
+ # ==== Options
239
+ #
240
+ # Accepted key/value pairs in options parameter are:
241
+ # * +:start_range+ - Integer. Position of first byte of first page. (optional)
242
+ # * +:end_range+ - Integer. Position of last byte of of last page. (optional)
243
+ # * +:snapshot+ - String. An opaque DateTime value that specifies the blob snapshot to
244
+ # retrieve information from. (optional)
245
+ # * +:timeout+ - Integer. A timeout in seconds.
246
+ # * +:if_modified_since+ - String. A DateTime value. Specify this conditional header to list the pages only if
247
+ # the blob has been modified since the specified date/time. If the blob has not been modified,
248
+ # the Blob service returns status code 412 (Precondition Failed).
249
+ # * +:if_unmodified_since+ - String. A DateTime value. Specify this conditional header to list the pages only if
250
+ # the blob has not been modified since the specified date/time. If the blob has been modified,
251
+ # the Blob service returns status code 412 (Precondition Failed).
252
+ # * +:if_match+ - String. An ETag value. Specify an ETag value for this conditional header to list the pages only if
253
+ # the blob's ETag value matches the value specified. If the values do not match,
254
+ # the Blob service returns status code 412 (Precondition Failed).
255
+ # * +:if_none_match+ - String. An ETag value. Specify an ETag value for this conditional header to list the pages only if
256
+ # the blob's ETag value does not match the value specified. If the values are identical,
257
+ # the Blob service returns status code 412 (Precondition Failed).
258
+ #
259
+ # See http://msdn.microsoft.com/en-us/library/azure/ee691973.aspx
260
+ #
261
+ # Returns a list of page ranges in the format [ [start, end], [start, end], ... ]
262
+ #
263
+ # eg. [ [0, 511], [512, 1024], ... ]
264
+ #
265
+ def list_page_blob_ranges(container, blob, options={})
266
+ query = {'comp' => 'pagelist'}
267
+ query.update({'snapshot' => options[:snapshot]}) if options[:snapshot]
268
+ StorageService.with_query query, 'timeout', options[:timeout].to_s if options[:timeout]
269
+
270
+ uri = blob_uri(container, blob, query)
271
+
272
+ options[:start_range] = 0 if options[:end_range] and not options[:start_range]
273
+
274
+ headers = StorageService.service_properties_headers
275
+ StorageService.with_header headers, 'x-ms-range', "bytes=#{options[:start_range]}-#{options[:end_range]}" if options[:start_range]
276
+ add_blob_conditional_headers options, headers
277
+
278
+ response = call(:get, uri, nil, headers)
279
+
280
+ pagelist = Serialization.page_list_from_xml(response.body)
281
+ pagelist
282
+ end
283
+
284
+ # Public: Resizes a page blob to the specified size.
285
+ #
286
+ # ==== Attributes
287
+ #
288
+ # * +container+ - String. The container name.
289
+ # * +blob+ - String. The blob name.
290
+ # * +size+ - String. The blob size. Resizes a page blob to the specified size.
291
+ # If the specified value is less than the current size of the blob,
292
+ # then all pages above the specified value are cleared.
293
+ # * +options+ - Hash. Optional parameters.
294
+ #
295
+ # ==== Options
296
+ #
297
+ # Accepted key/value pairs in options parameter are:
298
+ # * +:timeout+ - Integer. A timeout in seconds.
299
+ # * +:if_modified_since+ - String. A DateTime value. Specify this conditional header to set the blob properties
300
+ # only if the blob has been modified since the specified date/time. If the blob has not been modified,
301
+ # the Blob service returns status code 412 (Precondition Failed).
302
+ # * +:if_unmodified_since+ - String. A DateTime value. Specify this conditional header to set the blob properties
303
+ # only if the blob has not been modified since the specified date/time. If the blob has been modified,
304
+ # the Blob service returns status code 412 (Precondition Failed).
305
+ # * +:if_match+ - String. An ETag value. Specify an ETag value for this conditional header to set the blob properties
306
+ # only if the blob's ETag value matches the value specified. If the values do not match,
307
+ # the Blob service returns status code 412 (Precondition Failed).
308
+ # * +:if_none_match+ - String. An ETag value. Specify an ETag value for this conditional header to set the blob properties
309
+ # only if the blob's ETag value does not match the value specified. If the values are identical,
310
+ # the Blob service returns status code 412 (Precondition Failed).
311
+ #
312
+ # See http://msdn.microsoft.com/en-us/library/azure/ee691966.aspx
313
+ #
314
+ # Returns nil on success.
315
+ def resize_page_blob(container, blob, size, options={})
316
+ options = { :content_length => size }.merge(options)
317
+ set_blob_properties container, blob, options
318
+ end
319
+
320
+ # Public: Sets a page blob's sequence number.
321
+ #
322
+ # ==== Attributes
323
+ #
324
+ # * +container+ - String. The container name.
325
+ # * +blob+ - String. The blob name.
326
+ # * +action+ - Symbol. Indicates how the service should modify the sequence
327
+ # number for the blob. Required if :sequence_number is used. This property
328
+ # applies to page blobs only.
329
+ #
330
+ # Specify one of the following options for this property:
331
+ #
332
+ # * +:max+ - Sets the sequence number to be the higher of the value included with
333
+ # the request and the value currently stored for the blob.
334
+ # * +:update+ - Sets the sequence number to the value included with the request.
335
+ # * +:increment+ - Increments the value of the sequence number by 1. If specifying this
336
+ # option, do not include the sequence_number option; doing so will return
337
+ # status code 400 (Bad Request).
338
+ #
339
+ # * +number+ - Integer. Sets the blob's sequence number. The sequence number is a
340
+ # user-controlled property that you can use to track requests and manage concurrency
341
+ # issues. Required if the 'action' parameter is set to :max or :update.
342
+ # This property applies to page blobs only.
343
+ #
344
+ # Use this together with the 'action' parameter to update the blob's sequence
345
+ # number, either to the specified value or to the higher of the values specified with
346
+ # the request or currently stored with the blob.
347
+ #
348
+ # This header should not be specified if the 'action' parameter is set to :increment;
349
+ # in this case the service automatically increments the sequence number by one.
350
+ #
351
+ # To set the sequence number to a value of your choosing, this property must be specified
352
+ # together with the 'action' parameter
353
+ # * +options+ - Hash. Optional parameters.
354
+ #
355
+ # ==== Options
356
+ #
357
+ # Accepted key/value pairs in options parameter are:
358
+ # * +:timeout+ - Integer. A timeout in seconds.
359
+ # * +:if_modified_since+ - String. A DateTime value. Specify this conditional header to set the blob properties
360
+ # only if the blob has been modified since the specified date/time. If the blob has not been modified,
361
+ # the Blob service returns status code 412 (Precondition Failed).
362
+ # * +:if_unmodified_since+ - String. A DateTime value. Specify this conditional header to set the blob properties
363
+ # only if the blob has not been modified since the specified date/time. If the blob has been modified,
364
+ # the Blob service returns status code 412 (Precondition Failed).
365
+ # * +:if_match+ - String. An ETag value. Specify an ETag value for this conditional header to set the blob properties
366
+ # only if the blob's ETag value matches the value specified. If the values do not match,
367
+ # the Blob service returns status code 412 (Precondition Failed).
368
+ # * +:if_none_match+ - String. An ETag value. Specify an ETag value for this conditional header to set the blob properties
369
+ # only if the blob's ETag value does not match the value specified. If the values are identical,
370
+ # the Blob service returns status code 412 (Precondition Failed).
371
+ #
372
+ # See http://msdn.microsoft.com/en-us/library/azure/ee691966.aspx
373
+ #
374
+ # Returns nil on success.
375
+ def set_sequence_number(container, blob, action, number, options={})
376
+ options = { :sequence_number_action => action, :sequence_number => number }.merge(options)
377
+ set_blob_properties container, blob, options
378
+ end
379
+ end
380
+ end
@@ -0,0 +1,297 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ require 'azure/storage/service/serialization'
25
+
26
+ require 'azure/storage/blob/container'
27
+ require 'azure/storage/blob/blob'
28
+ require 'azure/storage/blob/block'
29
+
30
+ require 'base64'
31
+
32
+ module Azure::Storage
33
+ module Blob
34
+ module Serialization
35
+ include Azure::Storage::Service::Serialization
36
+
37
+ def self.container_enumeration_results_from_xml(xml)
38
+ xml = slopify(xml)
39
+ expect_node("EnumerationResults", xml)
40
+
41
+ results = enumeration_results_from_xml(xml, Azure::Service::EnumerationResults.new)
42
+
43
+ return results unless (xml > "Containers").any? && ((xml > "Containers") > "Container").any?
44
+
45
+ if xml.Containers.Container.count == 0
46
+ results.push(container_from_xml(xml.Containers.Container))
47
+ else
48
+ xml.Containers.Container.each { |container_node|
49
+ results.push(container_from_xml(container_node))
50
+ }
51
+ end
52
+
53
+ results
54
+ end
55
+
56
+ def self.container_from_xml(xml)
57
+ xml = slopify(xml)
58
+ expect_node("Container", xml)
59
+
60
+ Container::Container.new do |container|
61
+ container.name = xml.Name.text if (xml > "Name").any?
62
+ container.properties = container_properties_from_xml(xml.Properties) if (xml > "Properties").any?
63
+ container.metadata = metadata_from_xml(xml.Metadata) if (xml > "Metadata").any?
64
+ end
65
+ end
66
+
67
+ def self.container_from_headers(headers)
68
+ Container::Container.new do |container|
69
+ container.properties = container_properties_from_headers(headers)
70
+ container.public_access_level = public_access_level_from_headers(headers)
71
+ container.metadata = metadata_from_headers(headers)
72
+ end
73
+ end
74
+
75
+ def self.container_properties_from_xml(xml)
76
+ xml = slopify(xml)
77
+ expect_node("Properties", xml)
78
+
79
+ props = {}
80
+
81
+ props[:last_modified] = (xml > "Last-Modified").text if (xml > "Last-Modified").any?
82
+ props[:etag] = xml.Etag.text if (xml > "Etag").any?
83
+ props[:lease_status] = xml.LeaseStatus.text if (xml > "LeaseStatus").any?
84
+ props[:lease_state] = xml.LeaseState.text if (xml > "LeaseState").any?
85
+ props[:lease_duration] = xml.LeaseDuration.text if (xml > "LeaseDuration").any?
86
+
87
+ props
88
+ end
89
+
90
+ def self.container_properties_from_headers(headers)
91
+ props = {}
92
+
93
+ props[:last_modified] = headers["Last-Modified"]
94
+ props[:etag] = headers["Etag"]
95
+ props[:lease_status] = headers["x-ms-lease-status"]
96
+ props[:lease_state] = headers["x-ms-lease-state"]
97
+ props[:lease_duration] = headers["x-ms-lease-duration"]
98
+
99
+ props
100
+ end
101
+
102
+ def self.public_access_level_from_headers(headers)
103
+ headers["x-ms-blob-public-access"]
104
+ end
105
+
106
+ def self.blob_enumeration_results_from_xml(xml)
107
+
108
+ xml = slopify(xml)
109
+ expect_node("EnumerationResults", xml)
110
+
111
+ results = enumeration_results_from_xml(xml, Azure::Service::EnumerationResults.new)
112
+
113
+ return results unless (xml > "Blobs").any?
114
+
115
+ if ((xml > "Blobs") > "Blob").any?
116
+ if xml.Blobs.Blob.count == 0
117
+ results.push(blob_from_xml(xml.Blobs.Blob))
118
+ else
119
+ xml.Blobs.Blob.each { |blob_node|
120
+ results.push(blob_from_xml(blob_node))
121
+ }
122
+ end
123
+ end
124
+
125
+ results
126
+ end
127
+
128
+ def self.blob_from_xml(xml)
129
+ xml = slopify(xml)
130
+ expect_node("Blob", xml)
131
+
132
+ Blob.new do |blob|
133
+ blob.name = xml.Name.text if (xml > "Name").any?
134
+ blob.snapshot = xml.Snapshot.text if (xml > "Snapshot").any?
135
+
136
+ blob.properties = blob_properties_from_xml(xml.Properties) if (xml > "Properties").any?
137
+ blob.metadata = metadata_from_xml(xml.Metadata) if (xml > "Metadata").any?
138
+ end
139
+ end
140
+
141
+ def self.blob_from_headers(headers)
142
+ Blob.new do |blob|
143
+ blob.properties = blob_properties_from_headers(headers)
144
+ blob.metadata = metadata_from_headers(headers)
145
+ end
146
+ end
147
+
148
+ def self.blob_properties_from_xml(xml)
149
+ xml = slopify(xml)
150
+ expect_node("Properties", xml)
151
+
152
+ props = {}
153
+
154
+ props[:last_modified] = (xml > "Last-Modified").text if (xml > "Last-Modified").any?
155
+ props[:etag] = xml.Etag.text if (xml > "Etag").any?
156
+ props[:lease_status] = xml.LeaseStatus.text if (xml > "LeaseStatus").any?
157
+ props[:lease_state] = xml.LeaseState.text if (xml > "LeaseState").any?
158
+ props[:lease_duration] = xml.LeaseDuration.text if (xml > "LeaseDuration").any?
159
+ props[:content_length] = (xml > "Content-Length").text.to_i if (xml > "Content-Length").any?
160
+ props[:content_type] = (xml > "Content-Type").text if (xml > "Content-Type").any?
161
+ props[:content_encoding] = (xml > "Content-Encoding").text if (xml > "Content-Encoding").any?
162
+ props[:content_language] = (xml > "Content-Language").text if (xml > "Content-Language").any?
163
+ props[:content_md5] = (xml > "Content-MD5").text if (xml > "Content-MD5").any?
164
+
165
+ props[:cache_control] = (xml > "Cache-Control").text if (xml > "Cache-Control").any?
166
+ props[:sequence_number] = (xml > "x-ms-blob-sequence-number").text.to_i if (xml > "x-ms-blob-sequence-number").any?
167
+ props[:blob_type] = xml.BlobType.text if (xml > "BlobType").any?
168
+ props[:copy_id] = xml.CopyId.text if (xml > "CopyId").any?
169
+ props[:copy_status] = xml.CopyStatus.text if (xml > "CopyStatus").any?
170
+ props[:copy_source] = xml.CopySource.text if (xml > "CopySource").any?
171
+ props[:copy_progress] = xml.CopyProgress.text if (xml > "CopyProgress").any?
172
+ props[:copy_completion_time] = xml.CopyCompletionTime.text if (xml > "CopyCompletionTime").any?
173
+ props[:copy_status_description] = xml.CopyStatusDescription.text if (xml > "CopyStatusDescription").any?
174
+
175
+ props
176
+ end
177
+
178
+ def self.blob_properties_from_headers(headers)
179
+ props = {}
180
+
181
+ props[:last_modified] = headers["Last-Modified"]
182
+ props[:etag] = headers["Etag"]
183
+ props[:lease_status] = headers["x-ms-lease-status"]
184
+ props[:lease_state] = headers["x-ms-lease-state"]
185
+ props[:lease_duration] = headers["x-ms-lease-duration"]
186
+
187
+ props[:content_length] = headers["x-ms-blob-content-length"] || headers["Content-Length"]
188
+ props[:content_length] = props[:content_length].to_i if props[:content_length]
189
+
190
+ props[:content_type] = headers["x-ms-blob-content-type"] || headers["Content-Type"]
191
+ props[:content_encoding] = headers["x-ms-blob-content-encoding"] || headers["Content-Encoding"]
192
+ props[:content_language] = headers["x-ms-blob-content-language"] || headers["Content-Language"]
193
+ props[:content_disposition] = headers["x-ms-blob-content-disposition"] || headers["Content-Disposition"]
194
+ props[:content_md5] = headers["x-ms-blob-content-md5"] || headers["Content-MD5"]
195
+
196
+ props[:cache_control] = headers["x-ms-blob-cache-control"] || headers["Cache-Control"]
197
+ props[:sequence_number] = headers["x-ms-blob-sequence-number"].to_i if headers["x-ms-blob-sequence-number"]
198
+ props[:blob_type] = headers["x-ms-blob-type"]
199
+
200
+ props[:copy_id] = headers["x-ms-copy-id"]
201
+ props[:copy_status] = headers["x-ms-copy-status"]
202
+ props[:copy_source] = headers["x-ms-copy-source"]
203
+ props[:copy_progress] = headers["x-ms-copy-progress"]
204
+ props[:copy_completion_time] = headers["x-ms-copy-completion-time"]
205
+ props[:copy_status_description] = headers["x-ms-copy-status-description"]
206
+
207
+ props[:accept_ranges] = headers["Accept-Ranges"].to_i if headers["Accept-Ranges"]
208
+
209
+ props[:append_offset] = headers["x-ms-blob-append-offset"].to_i if headers["x-ms-blob-append-offset"]
210
+ props[:committed_count] = headers["x-ms-blob-committed-block-count"].to_i if headers["x-ms-blob-committed-block-count"]
211
+
212
+ props
213
+ end
214
+
215
+ def self.block_list_to_xml(block_list)
216
+ builder = Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
217
+ xml.BlockList {
218
+ block_list.each { |block|
219
+ encoded_id = Base64.strict_encode64(block[0])
220
+ case block[1]
221
+ when :uncommitted
222
+ xml.Uncommitted encoded_id
223
+ when :committed
224
+ xml.Committed encoded_id
225
+ else
226
+ xml.Latest encoded_id
227
+ end
228
+ }
229
+ }
230
+ end
231
+ builder.to_xml
232
+ end
233
+
234
+ def self.block_list_from_xml(xml)
235
+ xml = slopify(xml)
236
+ expect_node("BlockList", xml)
237
+
238
+ block_list = {
239
+ :committed => [],
240
+ :uncommitted => []
241
+ }
242
+
243
+ if ((xml > "CommittedBlocks") > "Block").any?
244
+ if xml.CommittedBlocks.Block.count == 0
245
+ add_block(:committed, xml.CommittedBlocks.Block, block_list)
246
+ else
247
+ xml.CommittedBlocks.Block.each { |block_node|
248
+ add_block(:committed, block_node, block_list)
249
+ }
250
+ end
251
+ end
252
+
253
+ return block_list unless (xml > "UncommittedBlocks")
254
+
255
+ if ((xml > "UncommittedBlocks") > "Block").any?
256
+ if xml.UncommittedBlocks.Block.count == 0
257
+ add_block(:uncommitted, xml.UncommittedBlocks.Block, block_list)
258
+ else
259
+ xml.UncommittedBlocks.Block.each { |block_node|
260
+ add_block(:uncommitted, block_node, block_list)
261
+ }
262
+ end
263
+ end
264
+
265
+ block_list
266
+ end
267
+
268
+ def self.add_block(type, block_node, block_list)
269
+ block = Block.new do |b|
270
+ b.name = Base64.strict_decode64(block_node.Name.text) if (block_node > "Name").any?
271
+ b.size = block_node.Size.text.to_i if (block_node > "Size").any?
272
+ b.type = type
273
+ end
274
+ block_list[type].push block
275
+ end
276
+
277
+ def self.page_list_from_xml(xml)
278
+ xml = slopify(xml)
279
+ expect_node("PageList", xml)
280
+
281
+ page_list = []
282
+
283
+ return page_list unless (xml > "PageRange").any?
284
+
285
+ if xml.PageRange.count == 0
286
+ page_list.push [xml.PageRange.Start.text.to_i, xml.PageRange.End.text.to_i]
287
+ else
288
+ xml.PageRange.each { |page_range|
289
+ page_list.push [page_range.Start.text.to_i, page_range.End.text.to_i]
290
+ }
291
+ end
292
+
293
+ page_list
294
+ end
295
+ end
296
+ end
297
+ end