azure 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +36 -0
  3. data/README.md +3 -0
  4. data/Rakefile +81 -0
  5. data/azure.gemspec +20 -9
  6. data/lib/azure.rb +4 -0
  7. data/lib/azure/atom.rb +170 -0
  8. data/lib/azure/auth.rb +29 -0
  9. data/lib/azure/blobs.rb +620 -0
  10. data/lib/azure/blobs/blob.rb +360 -0
  11. data/lib/azure/blobs/container.rb +209 -0
  12. data/lib/azure/blobs/service.rb +396 -0
  13. data/lib/azure/blobs/shared_access_signature.rb +84 -0
  14. data/lib/azure/blobs/uri.rb +60 -0
  15. data/lib/azure/configuration.rb +121 -0
  16. data/lib/azure/core/auth/shared_key.rb +95 -0
  17. data/lib/azure/core/auth/shared_key_lite.rb +34 -0
  18. data/lib/azure/core/collection.rb +118 -0
  19. data/lib/azure/core/service.rb +43 -0
  20. data/lib/azure/core/signer.rb +32 -0
  21. data/lib/azure/core/utils/interval.rb +97 -0
  22. data/lib/azure/core/utils/queryable.rb +74 -0
  23. data/lib/azure/core/utils/storage_service_properties.rb +83 -0
  24. data/lib/azure/core/utils/string.rb +59 -0
  25. data/lib/azure/error.rb +72 -0
  26. data/lib/azure/queues.rb +272 -0
  27. data/lib/azure/queues/message.rb +174 -0
  28. data/lib/azure/queues/queue.rb +187 -0
  29. data/lib/azure/queues/service.rb +263 -0
  30. data/lib/azure/queues/service_properties.rb +152 -0
  31. data/lib/azure/queues/uri.rb +78 -0
  32. data/lib/azure/request.rb +102 -0
  33. data/lib/azure/response.rb +93 -0
  34. data/lib/azure/service_bus.rb +4 -0
  35. data/lib/azure/service_bus/auth/authorizer.rb +22 -0
  36. data/lib/azure/service_bus/auth/uri.rb +52 -0
  37. data/lib/azure/service_bus/auth/wrap.rb +37 -0
  38. data/lib/azure/service_bus/auth/wrap_service.rb +76 -0
  39. data/lib/azure/service_bus/auth/wrap_token.rb +45 -0
  40. data/lib/azure/service_bus/auth/wrap_token_manager.rb +46 -0
  41. data/lib/azure/service_bus/brokered_message.rb +139 -0
  42. data/lib/azure/service_bus/brokered_message_serializer.rb +113 -0
  43. data/lib/azure/service_bus/queues.rb +194 -0
  44. data/lib/azure/service_bus/queues/queue.rb +100 -0
  45. data/lib/azure/service_bus/queues/queue_serializer.rb +51 -0
  46. data/lib/azure/service_bus/queues/service.rb +154 -0
  47. data/lib/azure/service_bus/queues/uri.rb +80 -0
  48. data/lib/azure/service_bus/rules.rb +110 -0
  49. data/lib/azure/service_bus/rules/rule.rb +97 -0
  50. data/lib/azure/service_bus/rules/service.rb +122 -0
  51. data/lib/azure/service_bus/rules/uri.rb +39 -0
  52. data/lib/azure/service_bus/service_bus_service.rb +22 -0
  53. data/lib/azure/service_bus/subscriptions.rb +170 -0
  54. data/lib/azure/service_bus/subscriptions/service.rb +133 -0
  55. data/lib/azure/service_bus/subscriptions/subscription.rb +164 -0
  56. data/lib/azure/service_bus/subscriptions/subscription_serializer.rb +74 -0
  57. data/lib/azure/service_bus/subscriptions/uri.rb +71 -0
  58. data/lib/azure/service_bus/topics.rb +120 -0
  59. data/lib/azure/service_bus/topics/service.rb +98 -0
  60. data/lib/azure/service_bus/topics/topic.rb +122 -0
  61. data/lib/azure/service_bus/topics/topic_serializer.rb +44 -0
  62. data/lib/azure/service_bus/topics/uri.rb +58 -0
  63. data/lib/azure/service_runtime/client/goal_state_pipe_monitor.rb +21 -0
  64. data/lib/azure/service_runtime/client/goal_state_protocol.rb +18 -0
  65. data/lib/azure/service_runtime/client/runtime_client.rb +135 -0
  66. data/lib/azure/service_runtime/deployment.rb +24 -0
  67. data/lib/azure/service_runtime/local_resource.rb +15 -0
  68. data/lib/azure/service_runtime/role.rb +17 -0
  69. data/lib/azure/service_runtime/role_environment.rb +206 -0
  70. data/lib/azure/service_runtime/role_environment_change.rb +32 -0
  71. data/lib/azure/service_runtime/role_instance.rb +35 -0
  72. data/lib/azure/service_runtime/role_instance_endpoint.rb +14 -0
  73. data/lib/azure/tables.rb +215 -0
  74. data/lib/azure/tables/auth/shared_key.rb +71 -0
  75. data/lib/azure/tables/auth/shared_key_lite.rb +30 -0
  76. data/lib/azure/tables/entities_collection.rb +66 -0
  77. data/lib/azure/tables/entity.rb +127 -0
  78. data/lib/azure/tables/service.rb +211 -0
  79. data/lib/azure/tables/table.rb +129 -0
  80. data/lib/azure/tables/tables_collection.rb +62 -0
  81. data/lib/azure/tables/types.rb +65 -0
  82. data/lib/azure/tables/uri.rb +62 -0
  83. data/test/fixtures/32px-fulls-black.jpg +0 -0
  84. data/test/fixtures/all_containers.xml +20 -0
  85. data/test/fixtures/all_tables.xml +22 -0
  86. data/test/fixtures/create_table_response_entry.xml +15 -0
  87. data/test/fixtures/error.xml +5 -0
  88. data/test/fixtures/insert_entity_response_entry.xml +25 -0
  89. data/test/fixtures/messages.xml +12 -0
  90. data/test/fixtures/query_entities_empty_response.xml +7 -0
  91. data/test/fixtures/query_entities_response.xml +45 -0
  92. data/test/fixtures/queue_service_properties.xml +22 -0
  93. data/test/fixtures/queue_service_properties_original.xml +19 -0
  94. data/test/fixtures/queues.xml +16 -0
  95. data/test/fixtures/sb_default_create_queue_response.xml +23 -0
  96. data/test/fixtures/sb_default_create_topic_response.xml +18 -0
  97. data/test/fixtures/sb_get_access_token_response.txt +1 -0
  98. data/test/fixtures/sb_queues_runtime_peek_message_response_headers.txt +9 -0
  99. data/test/integration/blobs/auth_test.rb +19 -0
  100. data/test/integration/blobs/blob_test.rb +61 -0
  101. data/test/integration/blobs/clear_page_range_test.rb +19 -0
  102. data/test/integration/blobs/copy_test.rb +33 -0
  103. data/test/integration/blobs/create_blobs_test.rb +51 -0
  104. data/test/integration/blobs/create_container_test.rb +13 -0
  105. data/test/integration/blobs/create_snapshot_test.rb +17 -0
  106. data/test/integration/blobs/delete_blob_snapshots_test.rb +19 -0
  107. data/test/integration/blobs/delete_blobs_test.rb +25 -0
  108. data/test/integration/blobs/delete_container_test.rb +24 -0
  109. data/test/integration/blobs/delete_snapshot_test.rb +17 -0
  110. data/test/integration/blobs/get_blob_snapshot_test.rb +18 -0
  111. data/test/integration/blobs/get_blobs_test.rb +31 -0
  112. data/test/integration/blobs/get_page_range_test.rb +19 -0
  113. data/test/integration/blobs/list_blobs_test.rb +39 -0
  114. data/test/integration/blobs/list_containers_test.rb +28 -0
  115. data/test/integration/blobs/manage_blob_leases_test.rb +45 -0
  116. data/test/integration/blobs/manage_blob_metadata_test.rb +51 -0
  117. data/test/integration/blobs/manage_blob_properties_test.rb +25 -0
  118. data/test/integration/blobs/manage_blob_service_properties_test.rb +38 -0
  119. data/test/integration/blobs/manage_container_metadata_test.rb +46 -0
  120. data/test/integration/blobs/manage_container_permissions_test.rb +17 -0
  121. data/test/integration/blobs/update_page_range_test.rb +20 -0
  122. data/test/integration/queues/clear_messages_test.rb +22 -0
  123. data/test/integration/queues/create_queue_test.rb +13 -0
  124. data/test/integration/queues/delete_message_test.rb +42 -0
  125. data/test/integration/queues/delete_queue_test.rb +24 -0
  126. data/test/integration/queues/get_messages_test.rb +39 -0
  127. data/test/integration/queues/list_queues_test.rb +43 -0
  128. data/test/integration/queues/manage_queue_metadata_test.rb +45 -0
  129. data/test/integration/queues/manage_queue_service_properties_test.rb +27 -0
  130. data/test/integration/queues/peek_messages_test.rb +55 -0
  131. data/test/integration/queues/put_message_test.rb +31 -0
  132. data/test/integration/queues/update_message_test.rb +46 -0
  133. data/test/integration/service_bus/auth_test.rb +18 -0
  134. data/test/integration/service_bus/queues/create_queue_test.rb +25 -0
  135. data/test/integration/service_bus/queues/delete_message_from_queue_test.rb +29 -0
  136. data/test/integration/service_bus/queues/delete_queue_test.rb +25 -0
  137. data/test/integration/service_bus/queues/get_queue_test.rb +23 -0
  138. data/test/integration/service_bus/queues/list_queues_test.rb +39 -0
  139. data/test/integration/service_bus/queues/peek_message_from_queue_test.rb +34 -0
  140. data/test/integration/service_bus/queues/read_and_delete_message_from_queue_test.rb +31 -0
  141. data/test/integration/service_bus/queues/send_message_to_queue_test.rb +22 -0
  142. data/test/integration/service_bus/queues/unlock_message_from_queue_test.rb +36 -0
  143. data/test/integration/service_bus/rules/create_rule_test.rb +19 -0
  144. data/test/integration/service_bus/rules/delete_rule_test.rb +17 -0
  145. data/test/integration/service_bus/rules/get_rule_test.rb +21 -0
  146. data/test/integration/service_bus/rules/list_rules_test.rb +24 -0
  147. data/test/integration/service_bus/rules/rule_test.rb +16 -0
  148. data/test/integration/service_bus/subscriptions/create_subscription_test.rb +25 -0
  149. data/test/integration/service_bus/subscriptions/delete_message_from_subscription_test.rb +31 -0
  150. data/test/integration/service_bus/subscriptions/delete_subscription_test.rb +30 -0
  151. data/test/integration/service_bus/subscriptions/fetch_subscription_test.rb +28 -0
  152. data/test/integration/service_bus/subscriptions/list_subscriptions_test.rb +23 -0
  153. data/test/integration/service_bus/subscriptions/peek_lock_message_from_subscription_test.rb +42 -0
  154. data/test/integration/service_bus/subscriptions/read_delete_message_from_subscription_test.rb +36 -0
  155. data/test/integration/service_bus/subscriptions/subscription_test.rb +31 -0
  156. data/test/integration/service_bus/subscriptions/unlock_message_from_subscription_test.rb +43 -0
  157. data/test/integration/service_bus/topics/create_topic_test.rb +25 -0
  158. data/test/integration/service_bus/topics/delete_topic_test.rb +25 -0
  159. data/test/integration/service_bus/topics/get_topic_test.rb +23 -0
  160. data/test/integration/service_bus/topics/list_topics_test.rb +39 -0
  161. data/test/integration/service_bus/topics/send_message_to_topic_test.rb +23 -0
  162. data/test/integration/tables/auth_test.rb +29 -0
  163. data/test/integration/tables/creating_tables_test.rb +16 -0
  164. data/test/integration/tables/delete_entity_test.rb +39 -0
  165. data/test/integration/tables/deleting_table_test.rb +22 -0
  166. data/test/integration/tables/insert_entity_test.rb +23 -0
  167. data/test/integration/tables/merge_entity_test.rb +28 -0
  168. data/test/integration/tables/query_entities_test.rb +131 -0
  169. data/test/integration/tables/query_tables_test.rb +63 -0
  170. data/test/integration/tables/update_entity_test.rb +54 -0
  171. data/test/integration/test_helper.rb +14 -0
  172. data/test/support/blobs.rb +12 -0
  173. data/test/support/env.rb +5 -0
  174. data/test/support/fixtures.rb +22 -0
  175. data/test/support/stubs.rb +28 -0
  176. data/test/support/table_names.rb +44 -0
  177. data/test/test_helper.rb +10 -0
  178. data/test/unit/atom_test.rb +58 -0
  179. data/test/unit/auth_test.rb +24 -0
  180. data/test/unit/blobs/blob_test.rb +5 -0
  181. data/test/unit/blobs/container_test.rb +67 -0
  182. data/test/unit/blobs/service_test.rb +17 -0
  183. data/test/unit/blobs/shared_access_signature_test.rb +66 -0
  184. data/test/unit/blobs_test.rb +156 -0
  185. data/test/unit/core/service_test.rb +57 -0
  186. data/test/unit/core/utils/interval_test.rb +70 -0
  187. data/test/unit/core/utils/queryable_test.rb +69 -0
  188. data/test/unit/core/utils/storage_service_properties_test.rb +66 -0
  189. data/test/unit/error_test.rb +39 -0
  190. data/test/unit/queues/message_test.rb +40 -0
  191. data/test/unit/queues/queue_test.rb +64 -0
  192. data/test/unit/queues/service_properties.rb +35 -0
  193. data/test/unit/request_test.rb +38 -0
  194. data/test/unit/response_test.rb +43 -0
  195. data/test/unit/service_bus/auth/authorizer_test.rb +27 -0
  196. data/test/unit/service_bus/auth/wrap_token_test.rb +28 -0
  197. data/test/unit/service_bus/queues/queue_test.rb +38 -0
  198. data/test/unit/service_bus/topics/topic_test.rb +33 -0
  199. data/test/unit/service_runtime/data/goalstate.xml +9 -0
  200. data/test/unit/service_runtime/data/roleenvironmentdata.xml +29 -0
  201. data/test/unit/service_runtime/data/runtime.xml +6 -0
  202. data/test/unit/service_runtime/role_environment_test.rb +144 -0
  203. data/test/unit/tables/auth/shared_key_lite_test.rb +39 -0
  204. data/test/unit/tables/auth/shared_key_test.rb +45 -0
  205. data/test/unit/tables/entities_collection_test.rb +39 -0
  206. data/test/unit/tables/entity_test.rb +72 -0
  207. data/test/unit/tables/table_test.rb +57 -0
  208. data/test/unit/tables_test.rb +302 -0
  209. data/test/unit/types_test.rb +67 -0
  210. metadata +310 -47
  211. data/LICENSE +0 -0
  212. data/README +0 -0
@@ -0,0 +1,360 @@
1
+ require "nokogiri"
2
+ require "uri"
3
+ require "azure/error"
4
+ require "azure/blobs"
5
+ require "azure/blobs/uri"
6
+ require "digest/sha1"
7
+
8
+ module Azure
9
+ module Blobs
10
+ class Blob
11
+ include ErrorHandler
12
+
13
+ # List of valid property names.
14
+ PROPERTIES = [
15
+ "content-length",
16
+ "content-type",
17
+ "content-md5",
18
+ "content-encoding",
19
+ "content-language",
20
+ "cache-control",
21
+ "last-modified",
22
+ "etag",
23
+ "x-ms-lease-status",
24
+ "x-ms-lease-time",
25
+ "x-ms-lease-id",
26
+ "x-ms-blob-sequence-number",
27
+ "x-ms-snapshot"
28
+ ].freeze
29
+
30
+ # Public: Get/Set the container where this blob belongs.
31
+ attr_accessor :container
32
+
33
+ # Public: Get the name of the blob.
34
+ attr :name
35
+
36
+ # Public: Get the Properties of the blob.
37
+ #
38
+ # Following are *Optional*
39
+ # - "x-ms-blob-cache-control" Modifies the cache control string for the blob.
40
+ # - "x-ms-blob-content-type" Sets the blob’s content type.
41
+ # - "x-ms-blob-content-md5" Sets the blob's MD5 hash.
42
+ # - "x-ms-blob-content-encoding" Sets the blob's content encoding.
43
+ # - "x-ms-blob-content-languag" Sets the blob's content language.
44
+ #
45
+ # Following may be *Required*
46
+ # - "x-ms-lease-id" Required if the blob has an active lease.
47
+ #
48
+ # Following properties only apply to Page Blobs.
49
+ # - Optional "x-ms-blob-content-length" Resizes a page blob to the specified size.
50
+ # If the specified value is less than the current size of the blob, then all
51
+ # pages above the specified value are cleared.
52
+ #
53
+ # - "x-ms-sequence-number-action" Optional, but required if the x-ms-blob-sequence-number
54
+ # header is set for the request. Posible values: {max, update, increment}
55
+ #
56
+ # - "x-ms-blob-sequence-number" Optional, but required if the x-ms-sequence-number-action
57
+ # property is set to max or update.
58
+ #
59
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691966.
60
+ attr :properties
61
+
62
+ # Public: Get the Metadata of the blob.
63
+ attr :metadata
64
+
65
+ # Public: Get the Content of the blob.
66
+ attr :content
67
+
68
+ # Public: Initialize a blob from an XML node as returned from an API
69
+ # response.
70
+ #
71
+ # container - A instance of Azure::Blobs::Container
72
+ # node - A Nokogiri::Node.
73
+ #
74
+ # Returns a Blob.
75
+ def self.from_node(node)
76
+ name = (node % "Name").text
77
+
78
+ properties = (node / "Properties *").each_with_object({}) do |no, props|
79
+ props[no.name] = no.text
80
+ end
81
+
82
+ metadata = (node / "Metadata *").each_with_object({}) do |no, meta|
83
+ meta[no.name] = no.text
84
+ end
85
+
86
+ container_name = (node / "Url").text.split("/")[-2..-2].first
87
+ container = Azure::Blobs::Container.new(container_name)
88
+
89
+ new(name, container) do |blob|
90
+ blob.metadata.replace(metadata)
91
+ blob.properties.replace(properties)
92
+ yield blob if block_given?
93
+ end
94
+ end
95
+
96
+ # Public: Instantiate a blob from an error object.
97
+ #
98
+ # error - An Azure::Error.
99
+ #
100
+ # Returns a Table.
101
+ def self.from_error(error)
102
+ new(nil, nil, nil) do |blob|
103
+ blob.error = error
104
+ end
105
+ end
106
+
107
+ # Public: Initialize a Blob.
108
+ #
109
+ # name - A String with the name of the Blob.
110
+ # container - An Azure::Blobs::Container instance.
111
+ # content - The content of this Blob.
112
+ # service - The Blobs service to perform external calls.
113
+ def initialize(name, container=nil, content=nil, service=Azure::Blobs)
114
+ @name = name
115
+ @container = container
116
+ @content = content
117
+ @properties = {}
118
+ @metadata = {}
119
+ @service = service
120
+ yield self if block_given?
121
+ end
122
+
123
+ # Public: The url of this blob.
124
+ #
125
+ # Returns a URI.
126
+ def url
127
+ Blobs::URI.blob(container.name, name)
128
+ end
129
+
130
+ # Public: Check equality between blobs. Two blobs are equal if they have
131
+ # the same name and belong to the same container.
132
+ #
133
+ # other - A Blob.
134
+ #
135
+ # Returns true|false.
136
+ def ==(other)
137
+ !container.nil? && container == other.container && name == other.name
138
+ end
139
+
140
+ # Public: Delete this blob from the storage service. If the operation is
141
+ # unsuccessful this invalidates the blob.
142
+ #
143
+ # Returns true|false to indicate success.
144
+ def delete
145
+ @service.delete_blob(self)
146
+ end
147
+
148
+ # Public: Force a reload of this blob's metadata from the service.
149
+ #
150
+ # Returns the Hash of metadata.
151
+ def load_metadata!
152
+ @service.load_blob_metadata(self)
153
+ end
154
+
155
+ # Public: Put the current blob's metadata into the storage service.
156
+ #
157
+ # Returns true|false to indicate success.
158
+ def save_metadata!
159
+ @service.save_blob_metadata(self)
160
+ end
161
+
162
+ # Public: Extracts metadata from a hash containing HTTP headers (so
163
+ # "x-ms-meta-Name" => "Foo" is extracted as "Name" => "Foo"). This
164
+ # replaces the metadata of this container.
165
+ #
166
+ # hash - A hash of String => String with HTTP header values.
167
+ #
168
+ # Returns a Hash with the extracted metadata.
169
+ def extract_metadata(hash)
170
+ new_metadata = hash.each_with_object({}) do |(k,v), hash|
171
+ if key = k[/^x-ms-meta-(?<key>.*)?/, :key]
172
+ hash[key] = v
173
+ end
174
+ end
175
+
176
+ metadata.replace(new_metadata)
177
+ end
178
+
179
+ # Public: Put the current blob's properties into the storage service.
180
+ #
181
+ # headers - A Hash with user defined headers for this operation.
182
+ #
183
+ # Returns true|false to indicate success.
184
+ def save_properties!(headers={})
185
+ @service.save_blob_properties(self, headers)
186
+ end
187
+
188
+ # Public: Force a reload of this blob's properties from the server.
189
+ #
190
+ # headers - A Hash with user defined headers for this operation.
191
+ #
192
+ # Returns the Hash of properties.
193
+ def load_properties!(headers={})
194
+ @service.load_blob_properties(self, headers)
195
+ end
196
+
197
+ # Public: Extracts properties from a hash containing HTTP headers. This
198
+ # replaces the properties of this container. Any headers that are
199
+ # contained in `PROPERTIES` are extracted.
200
+ #
201
+ # hash - A hash of String => String with HTTP header values.
202
+ #
203
+ # Returns a Hash with the extracted properties.
204
+ def extract_properties(hash)
205
+ new_properties = hash.select do |key, _|
206
+ PROPERTIES.include?(key)
207
+ end
208
+ new_properties.merge!("x-ms-lease-id" => lease_id) if lease_id
209
+ properties.replace(new_properties)
210
+ end
211
+
212
+ # Public: Generate a Shared Access Signature that can be used to provide
213
+ # anonymous access to this blob.
214
+ #
215
+ # permissions - A String with the permissions you want to grant on this
216
+ # blob. Might contain any of "r", "w", "d", or "l" *in this
217
+ # order*.
218
+ # to - Either a Date, Time or duration in seconds.
219
+ # from - A Date or Time (if `to` is a duration in seconds, then
220
+ # this is ignored).
221
+ # id - An identifier (optional).
222
+ # clock - Dependency on Time for calculations (optional).
223
+ # signature - Dependency on SharedAccessSignature (optional).
224
+ #
225
+ # Examples:
226
+ #
227
+ # # Valid for 10 minutes.
228
+ # blob.shared_access_signature("r", 10.minutes)
229
+ #
230
+ # # Read until Christmas 2012.
231
+ # blob.shared_access_signature("r", Date.new(2012, 12, 25))
232
+ #
233
+ # # Associate this signature with an access control policy:
234
+ # blob.shared_access_signature("r", 10.minutes, "policy-id")
235
+ #
236
+ # Returns a URL for this resource that includes the SAS.
237
+ def shared_access_signature(permissions, to, from=nil, id=nil, clock=Time, signature=SharedAccessSignature)
238
+ if to.respond_to?(:to_int)
239
+ id, to, from = from, clock.now.utc + to, clock.now.utc
240
+ end
241
+
242
+ signature.new(permissions, from, to, id).url(self)
243
+ end
244
+
245
+ # Public: String identifying which type of resource this is (used to
246
+ # generate shared access signatures).
247
+ #
248
+ # Returns the string "b".
249
+ def resource_type
250
+ "b"
251
+ end
252
+
253
+ # Public: Creates a snapshot of this Blob.
254
+ #
255
+ # metadata - A Hash representing blob metadata as :name => value. (optional)
256
+ #
257
+ # Returns an instance of Azure::Blobs::Snapshot.
258
+ def create_snapshot(metadata={})
259
+ Azure::Blobs.create_snapshot(self, metadata)
260
+ end
261
+
262
+ # Public: Get the lease_id from blob properties.
263
+ def lease_id
264
+ properties["x-ms-lease-id"]
265
+ end
266
+ end
267
+
268
+ class Snapshot < Blob
269
+ # Public: Return the datetime value for x-ms-snapshot property.
270
+ def id
271
+ properties["x-ms-snapshot"]
272
+ end
273
+
274
+ # Public: Delete this snapshot.
275
+ def delete
276
+ @service.delete_snapshot(self)
277
+ end
278
+
279
+ # Public: Acquire a Lease ID for this blob.
280
+ #
281
+ # http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
282
+ def acquire_lease(service=Azure::Blobs)
283
+ service.lease(@blob, :acquire)
284
+ end
285
+
286
+ # Public: Renew Lease ID for this blob.
287
+ #
288
+ # http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
289
+ def renew_lease(service=Azure::Blobs)
290
+ service.lease(@blob, :renew)
291
+ end
292
+
293
+ # Public: Release Lease ID for this blob.
294
+ #
295
+ # http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
296
+ def release_lease(service=Azure::Blobs)
297
+ service.lease(@blob, :release)
298
+ end
299
+
300
+ # Public: Break Lease ID for this blob.
301
+ #
302
+ # http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
303
+ def break_lease(service=Azure::Blobs)
304
+ service.lease(@blob, :break)
305
+ end
306
+ end
307
+
308
+ class BlockBlob < Blob
309
+
310
+ attr :content_type
311
+
312
+ # Public: Upload a file to this BlockBlob, override content if exist.
313
+ # Blob metadata and properties will be sent as well to preserve them.
314
+ #
315
+ # filename_or_stream - IO or String representing the resource on the filesystem.
316
+ # content_type - String representing the content-type of the uploaded blob. (optional)
317
+ # byte_partition - Optional. Integer representing the size of the chunks to be uploaded. (optional)
318
+ #
319
+ # Returns boolean indicating success.
320
+ def update(filename_or_stream, content_type=nil, byte_partition=nil, service=Azure::Blobs)
321
+
322
+ stream = filename_or_stream.is_a?(String) ? File.open(filename_or_stream) : filename_or_stream
323
+
324
+ @content_type = content_type ||= "application/octet-stream"
325
+
326
+ block_ids = service.update_block_blob_content(self, stream, byte_partition)
327
+
328
+ if block_ids.any? && service.put_block_list(self, block_ids)
329
+ stream.rewind
330
+ @content = stream.read
331
+ true
332
+ else
333
+ false
334
+ end
335
+ end
336
+ end
337
+
338
+ class PageBlob < Blob
339
+ # Public: Write Range of pages.
340
+ def update_range(start_byte, end_byte, stream)
341
+ if Azure::Blobs.update_page_range(self, start_byte, end_byte, stream)
342
+ @content = stream
343
+ true
344
+ else
345
+ false
346
+ end
347
+ end
348
+
349
+ # Public: Clear Range of pages.
350
+ def clear_range(start_byte, end_byte)
351
+ Azure::Blobs.clear_page_range(self, start_byte, end_byte)
352
+ end
353
+
354
+ # Public: Get Range of pages.
355
+ def get_range(start_byte=nil, end_byte=nil)
356
+ Azure::Blobs.get_page_range(self, start_byte, end_byte)
357
+ end
358
+ end
359
+ end
360
+ end
@@ -0,0 +1,209 @@
1
+ require "nokogiri"
2
+ require "uri"
3
+ require "azure/error"
4
+ require "azure/blobs"
5
+ require "azure/blobs/uri"
6
+ require "azure/blobs/shared_access_signature"
7
+
8
+ module Azure
9
+ module Blobs
10
+ class Container
11
+ include ErrorHandler
12
+
13
+ # Public: Indicates the both the information of the container and of its
14
+ # blobs is accessible by an anonymous request.
15
+ CONTAINER = :container
16
+
17
+ # Public: Indicates the blobs in this container can be accessed by an
18
+ # anonymous request, but not the information in the container.
19
+ BLOB = :blob
20
+
21
+ # Public: Indicates neither this container nor any of its blobs can be
22
+ # accessed by an anonymous request.
23
+ PRIVATE = :private
24
+
25
+ # Public: Get the name of the container.
26
+ attr :name
27
+
28
+ # Public: Get the URI of the container.
29
+ attr :url
30
+
31
+ # Public: Get/Set the User defined Metadata of the container.
32
+ attr :metadata
33
+
34
+ # Public: Get the Properties of the container.
35
+ attr :properties
36
+
37
+ # Public: Get the current container visibility for anonymous requests. See
38
+ # the x-ms-blob-public-access header on:
39
+ #
40
+ # http://msdn.microsoft.com/en-us/library/windowsazure/dd179468
41
+ attr_accessor :visibility
42
+
43
+ # Convert the value of a x-ms-blob-public-access header to one of our
44
+ # visibility constants.
45
+ #
46
+ # header_value - A string or nil.
47
+ #
48
+ # Returns either PRIVATE, BLOB, or CONTAINER.
49
+ def self.visibility(header_value)
50
+ case header_value
51
+ when "container", "true"
52
+ CONTAINER
53
+ when "blob"
54
+ BLOB
55
+ else
56
+ PRIVATE
57
+ end
58
+ end
59
+
60
+ # Public: Initialize a container from an XML node as returned from an API
61
+ # response.
62
+ #
63
+ # node - A Nokogiri::Node.
64
+ #
65
+ # Returns a Container.
66
+ def self.from_node(node)
67
+ name = (node % "Name").text
68
+ url = URI((node % "Url").text)
69
+
70
+ metadata = (node / "Metadata *").each_with_object({}) do |n, metadata|
71
+ metadata[n.name] = n.text
72
+ end
73
+
74
+ properties = (node / "Properties *").each_with_object({}) do |n, props|
75
+ props[n.name] = n.text
76
+ end
77
+
78
+ new(name, url) do |container|
79
+ container.properties.replace(properties)
80
+ container.metadata.replace(metadata)
81
+ end
82
+ end
83
+
84
+ # Public: Initialize an invalid container from an erroneous response.
85
+ #
86
+ # error - An Azure::Error.
87
+ #
88
+ # Returns a Container.
89
+ def self.from_error(error)
90
+ container = new(nil, nil)
91
+ container.error = error
92
+ container
93
+ end
94
+
95
+ # Public: Initialize a Container.
96
+ #
97
+ # name - A String with the name of the Container.
98
+ # url - The URI that represents this container (optional).
99
+ # service - The Blobs service to perform external calls.
100
+ #
101
+ # Yields self (optional).
102
+ def initialize(name, url=Blobs::URI.container(name), service=Azure::Blobs)
103
+ @name = name
104
+ @url = url
105
+ @metadata = {}
106
+ @properties = {}
107
+ @service = service
108
+ yield self if block_given?
109
+ end
110
+
111
+ # Public: List the blobs inside this container.
112
+ #
113
+ # Returns an Array of Blobs.
114
+ def blobs
115
+ @service.blobs(self)
116
+ end
117
+
118
+ # Public: Check equality between containers. Two containers are equal if
119
+ # they have equal names.
120
+ #
121
+ # other - A Container.
122
+ #
123
+ # Returns true|false.
124
+ def ==(other)
125
+ name == other.name
126
+ end
127
+
128
+ # Public: Force a reload of this containers metadata from the server.
129
+ #
130
+ # Returns the Hash of metadata.
131
+ def load_metadata!
132
+ @service.load_container_metadata(self)
133
+ end
134
+
135
+ # Public: Put the current container's metadata into the storage service.
136
+ #
137
+ # Returns true|false to indicate success.
138
+ def save_metadata!
139
+ @service.save_container_metadata(self)
140
+ end
141
+
142
+ # Public: Extracts metadata from a hash containing HTTP headers (so
143
+ # "x-ms-meta-Name" => "Foo" is extracted as "Name" => "Foo"). This
144
+ # replaces the metadata of this container.
145
+ #
146
+ # hash - A hash of String => String with HTTP header values.
147
+ #
148
+ # Returns a Hash with the extracted metadata.
149
+ def extract_metadata(hash)
150
+ new_metadata = hash.each_with_object({}) do |(k,v), hash|
151
+ if key = k[/^x-ms-meta-(?<key>.*)?/, :key]
152
+ hash[key] = v
153
+ end
154
+ end
155
+
156
+ metadata.replace(new_metadata)
157
+ end
158
+
159
+ # Public: Generate a Shared Access Signature that can be used to provide
160
+ # anonymous access to this container.
161
+ #
162
+ # permissions - A String with the permissions you want to grant on this
163
+ # container. Might contain any of "r", "w", "d", or "l" *in
164
+ # this order*.
165
+ # to - Either a Date, Time or duration in seconds.
166
+ # from - A Date or Time (if `to` is a duration in seconds, then
167
+ # this is ignored).
168
+ # id - An identifier (optional).
169
+ # clock - Dependency on Time for calculations (optional).
170
+ # signature - Dependency on SharedAccessSignature (optional).
171
+ #
172
+ # Examples:
173
+ #
174
+ # # Valid for 10 minutes.
175
+ # container.shared_access_signature("r", 10.minutes)
176
+ #
177
+ # # Read until Christmas 2012.
178
+ # container.shared_access_signature("r", Date.new(2012, 12, 25))
179
+ #
180
+ # # Associate this signature with an access control policy:
181
+ # container.shared_access_signature("r", 10.minutes, "policy-id")
182
+ #
183
+ # Returns a URL for this resource that includes the SAS.
184
+ def shared_access_signature(permissions, to, from=nil, id=nil, clock=Time, signature=SharedAccessSignature)
185
+ if to.respond_to?(:to_int)
186
+ id, to, from = from, clock.now.utc + to, clock.now.utc
187
+ end
188
+
189
+ signature.new(permissions, from, to, id).url(self)
190
+ end
191
+
192
+ # Public: Delete this container from the storage service. If the operation
193
+ # fails this returns false and sets self.error.
194
+ #
195
+ # Returns true|false to indicate success.
196
+ def delete
197
+ @service.delete_container(self)
198
+ end
199
+
200
+ # Public: String identifying which type of resource this is (used to
201
+ # generate shared access signatures).
202
+ #
203
+ # Returns the string "c".
204
+ def resource_type
205
+ "c"
206
+ end
207
+ end
208
+ end
209
+ end