azure 0.0.0 → 0.1.0

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