stuartpreston-azure-sdk-for-ruby 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (292) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +10 -0
  4. data/ChangeLog.txt +40 -0
  5. data/Gemfile +16 -0
  6. data/README.md +616 -0
  7. data/Rakefile +133 -0
  8. data/azure.gemspec +44 -0
  9. data/lib/azure.rb +52 -0
  10. data/lib/azure/base_management/affinity_group.rb +32 -0
  11. data/lib/azure/base_management/base_management_service.rb +234 -0
  12. data/lib/azure/base_management/location.rb +27 -0
  13. data/lib/azure/base_management/management_http_request.rb +172 -0
  14. data/lib/azure/base_management/serialization.rb +129 -0
  15. data/lib/azure/base_management/sql_management_http_request.rb +45 -0
  16. data/lib/azure/blob/blob.rb +32 -0
  17. data/lib/azure/blob/blob_service.rb +1423 -0
  18. data/lib/azure/blob/block.rb +31 -0
  19. data/lib/azure/blob/container.rb +32 -0
  20. data/lib/azure/blob/serialization.rb +285 -0
  21. data/lib/azure/cloud_service_management/cloud_service.rb +38 -0
  22. data/lib/azure/cloud_service_management/cloud_service_management_service.rb +140 -0
  23. data/lib/azure/cloud_service_management/serialization.rb +117 -0
  24. data/lib/azure/core.rb +39 -0
  25. data/lib/azure/core/auth/authorizer.rb +36 -0
  26. data/lib/azure/core/auth/shared_key.rb +110 -0
  27. data/lib/azure/core/auth/shared_key_lite.rb +48 -0
  28. data/lib/azure/core/auth/signer.rb +48 -0
  29. data/lib/azure/core/configuration.rb +211 -0
  30. data/lib/azure/core/error.rb +22 -0
  31. data/lib/azure/core/filtered_service.rb +44 -0
  32. data/lib/azure/core/http/debug_filter.rb +36 -0
  33. data/lib/azure/core/http/http_error.rb +88 -0
  34. data/lib/azure/core/http/http_filter.rb +53 -0
  35. data/lib/azure/core/http/http_request.rb +157 -0
  36. data/lib/azure/core/http/http_response.rb +140 -0
  37. data/lib/azure/core/http/retry_policy.rb +74 -0
  38. data/lib/azure/core/http/signer_filter.rb +34 -0
  39. data/lib/azure/core/service.rb +63 -0
  40. data/lib/azure/core/signed_service.rb +43 -0
  41. data/lib/azure/core/utility.rb +190 -0
  42. data/lib/azure/queue/message.rb +30 -0
  43. data/lib/azure/queue/queue.rb +29 -0
  44. data/lib/azure/queue/queue_service.rb +568 -0
  45. data/lib/azure/queue/serialization.rb +106 -0
  46. data/lib/azure/service/access_policy.rb +26 -0
  47. data/lib/azure/service/cors.rb +11 -0
  48. data/lib/azure/service/cors_rule.rb +15 -0
  49. data/lib/azure/service/enumeration_results.rb +21 -0
  50. data/lib/azure/service/logging.rb +32 -0
  51. data/lib/azure/service/metrics.rb +31 -0
  52. data/lib/azure/service/retention_policy.rb +25 -0
  53. data/lib/azure/service/serialization.rb +298 -0
  54. data/lib/azure/service/signed_identifier.rb +30 -0
  55. data/lib/azure/service/storage_service.rb +83 -0
  56. data/lib/azure/service/storage_service_properties.rb +37 -0
  57. data/lib/azure/service_bus/action.rb +21 -0
  58. data/lib/azure/service_bus/auth/wrap_service.rb +89 -0
  59. data/lib/azure/service_bus/auth/wrap_signer.rb +69 -0
  60. data/lib/azure/service_bus/brokered_message.rb +124 -0
  61. data/lib/azure/service_bus/brokered_message_serializer.rb +159 -0
  62. data/lib/azure/service_bus/correlation_filter.rb +45 -0
  63. data/lib/azure/service_bus/empty_rule_action.rb +30 -0
  64. data/lib/azure/service_bus/false_filter.rb +38 -0
  65. data/lib/azure/service_bus/filter.rb +21 -0
  66. data/lib/azure/service_bus/interval.rb +104 -0
  67. data/lib/azure/service_bus/queue.rb +230 -0
  68. data/lib/azure/service_bus/relay.rb +88 -0
  69. data/lib/azure/service_bus/resource.rb +109 -0
  70. data/lib/azure/service_bus/rule.rb +98 -0
  71. data/lib/azure/service_bus/rule_aspect.rb +34 -0
  72. data/lib/azure/service_bus/serialization.rb +161 -0
  73. data/lib/azure/service_bus/service_bus_service.rb +897 -0
  74. data/lib/azure/service_bus/sql_filter.rb +50 -0
  75. data/lib/azure/service_bus/sql_rule_action.rb +50 -0
  76. data/lib/azure/service_bus/subscription.rb +184 -0
  77. data/lib/azure/service_bus/topic.rb +187 -0
  78. data/lib/azure/service_bus/true_filter.rb +38 -0
  79. data/lib/azure/sql_database_management/serialization.rb +111 -0
  80. data/lib/azure/sql_database_management/sql_database.rb +31 -0
  81. data/lib/azure/sql_database_management/sql_database_management_service.rb +200 -0
  82. data/lib/azure/storage_management/serialization.rb +184 -0
  83. data/lib/azure/storage_management/storage_account.rb +40 -0
  84. data/lib/azure/storage_management/storage_management_service.rb +166 -0
  85. data/lib/azure/table/auth/shared_key.rb +92 -0
  86. data/lib/azure/table/auth/shared_key_lite.rb +44 -0
  87. data/lib/azure/table/batch.rb +330 -0
  88. data/lib/azure/table/batch_response.rb +118 -0
  89. data/lib/azure/table/edmtype.rb +127 -0
  90. data/lib/azure/table/entity.rb +31 -0
  91. data/lib/azure/table/guid.rb +24 -0
  92. data/lib/azure/table/query.rb +112 -0
  93. data/lib/azure/table/serialization.rb +108 -0
  94. data/lib/azure/table/table_service.rb +560 -0
  95. data/lib/azure/version.rb +31 -0
  96. data/lib/azure/virtual_machine_image_management/serialization.rb +66 -0
  97. data/lib/azure/virtual_machine_image_management/virtual_machine_disk.rb +25 -0
  98. data/lib/azure/virtual_machine_image_management/virtual_machine_image.rb +25 -0
  99. data/lib/azure/virtual_machine_image_management/virtual_machine_image_management_service.rb +94 -0
  100. data/lib/azure/virtual_machine_management/serialization.rb +463 -0
  101. data/lib/azure/virtual_machine_management/virtual_machine.rb +45 -0
  102. data/lib/azure/virtual_machine_management/virtual_machine_management_service.rb +589 -0
  103. data/lib/azure/virtual_network_management/serialization.rb +186 -0
  104. data/lib/azure/virtual_network_management/virtual_network.rb +36 -0
  105. data/lib/azure/virtual_network_management/virtual_network_management_service.rb +109 -0
  106. data/test/fixtures/32px-fulls-black.jpg +0 -0
  107. data/test/fixtures/affinity_group.xml +33 -0
  108. data/test/fixtures/all_containers.xml +20 -0
  109. data/test/fixtures/all_tables.xml +22 -0
  110. data/test/fixtures/certificate.pem +21 -0
  111. data/test/fixtures/container_acl.xml +11 -0
  112. data/test/fixtures/create_sql_database_server.xml +2 -0
  113. data/test/fixtures/create_storage_desc_error.xml +5 -0
  114. data/test/fixtures/create_storage_extendedprop_error.xml +8 -0
  115. data/test/fixtures/create_storage_extendedpropname_error.xml +6 -0
  116. data/test/fixtures/create_storage_full_error.xml +6 -0
  117. data/test/fixtures/create_storage_label_error.xml +5 -0
  118. data/test/fixtures/create_storage_location_error.xml +5 -0
  119. data/test/fixtures/create_storage_name_error.xml +6 -0
  120. data/test/fixtures/create_table_response_entry.xml +15 -0
  121. data/test/fixtures/delete_storage_container_error.xml +5 -0
  122. data/test/fixtures/delete_storage_error.xml +5 -0
  123. data/test/fixtures/deployment_error.xml +5 -0
  124. data/test/fixtures/empty_xml_file +0 -0
  125. data/test/fixtures/get_storage_account_error.xml +5 -0
  126. data/test/fixtures/get_storage_account_properties.xml +32 -0
  127. data/test/fixtures/get_storage_account_properties_new.xml +32 -0
  128. data/test/fixtures/http_error.xml +5 -0
  129. data/test/fixtures/insert_entity_response_entry.xml +25 -0
  130. data/test/fixtures/list_affinity_groups.xml +22 -0
  131. data/test/fixtures/list_blobs.xml +121 -0
  132. data/test/fixtures/list_block_all_with_none_committed.xml +22 -0
  133. data/test/fixtures/list_blocks_all.xml +23 -0
  134. data/test/fixtures/list_blocks_committed.xml +13 -0
  135. data/test/fixtures/list_cloud_services.xml +39 -0
  136. data/test/fixtures/list_containers.xml +38 -0
  137. data/test/fixtures/list_firewall_management_endpoint.xml +27 -0
  138. data/test/fixtures/list_images.xml +110 -0
  139. data/test/fixtures/list_locations.xml +62 -0
  140. data/test/fixtures/list_page_ranges.xml +11 -0
  141. data/test/fixtures/list_sql_database.xml +36 -0
  142. data/test/fixtures/list_sql_server_firewall.xml +23 -0
  143. data/test/fixtures/list_storage_account_single.xml +25 -0
  144. data/test/fixtures/list_storage_accounts.xml +46 -0
  145. data/test/fixtures/list_virtual_networks.xml +92 -0
  146. data/test/fixtures/logging.xml +11 -0
  147. data/test/fixtures/management_certificate.pem +55 -0
  148. data/test/fixtures/messages.xml +12 -0
  149. data/test/fixtures/metrics.xml +10 -0
  150. data/test/fixtures/privatekey.key +28 -0
  151. data/test/fixtures/query_entities_empty_response.xml +7 -0
  152. data/test/fixtures/query_entities_response.xml +45 -0
  153. data/test/fixtures/queue_service_properties.xml +22 -0
  154. data/test/fixtures/queue_service_properties_original.xml +19 -0
  155. data/test/fixtures/queues.xml +16 -0
  156. data/test/fixtures/retention_policy.xml +5 -0
  157. data/test/fixtures/sb_default_create_queue_response.xml +23 -0
  158. data/test/fixtures/sb_default_create_relay_response.xml +15 -0
  159. data/test/fixtures/sb_default_create_topic_response.xml +18 -0
  160. data/test/fixtures/sb_get_access_token_response.txt +1 -0
  161. data/test/fixtures/sb_queues_runtime_peek_message_response_headers.txt +9 -0
  162. data/test/fixtures/storage_service_properties.xml +54 -0
  163. data/test/fixtures/update_storage_account.xml +16 -0
  164. data/test/fixtures/update_storage_error.xml +5 -0
  165. data/test/fixtures/updated_storage_accounts.xml +53 -0
  166. data/test/fixtures/virtual_machine.xml +113 -0
  167. data/test/fixtures/windows_virtual_machine.xml +106 -0
  168. data/test/integration/affinity_group/Affinity_test.rb +55 -0
  169. data/test/integration/affinity_group/Create_Affinity_test.rb +63 -0
  170. data/test/integration/affinity_group/Delete_Affinity_test.rb +56 -0
  171. data/test/integration/affinity_group/List_Affinity_test.rb +41 -0
  172. data/test/integration/affinity_group/Update_Affinity_test.rb +82 -0
  173. data/test/integration/blob/blob_gb18030_test.rb +199 -0
  174. data/test/integration/blob/blob_metadata_test.rb +75 -0
  175. data/test/integration/blob/blob_pages_test.rb +119 -0
  176. data/test/integration/blob/blob_properties_test.rb +77 -0
  177. data/test/integration/blob/block_blob_test.rb +254 -0
  178. data/test/integration/blob/container/container_acl_test.rb +69 -0
  179. data/test/integration/blob/container/container_metadata_test.rb +50 -0
  180. data/test/integration/blob/container/create_container_test.rb +60 -0
  181. data/test/integration/blob/container/delete_container_test.rb +39 -0
  182. data/test/integration/blob/container/get_container_properties_test.rb +48 -0
  183. data/test/integration/blob/container/list_containers_test.rb +79 -0
  184. data/test/integration/blob/container/root_container_test.rb +54 -0
  185. data/test/integration/blob/copy_blob_test.rb +113 -0
  186. data/test/integration/blob/create_blob_snapshot_test.rb +80 -0
  187. data/test/integration/blob/create_page_blob_test.rb +83 -0
  188. data/test/integration/blob/delete_blob_test.rb +159 -0
  189. data/test/integration/blob/get_blob_test.rb +65 -0
  190. data/test/integration/blob/informative_errors_test.rb +39 -0
  191. data/test/integration/blob/lease/acquire_lease_test.rb +36 -0
  192. data/test/integration/blob/lease/break_lease_test.rb +40 -0
  193. data/test/integration/blob/lease/release_lease_test.rb +40 -0
  194. data/test/integration/blob/lease/renew_lease_test.rb +42 -0
  195. data/test/integration/blob/list_blobs_test.rb +113 -0
  196. data/test/integration/cloud_service/Cloud_Create_test.rb +44 -0
  197. data/test/integration/cloud_service/Cloud_Delete_test.rb +44 -0
  198. data/test/integration/database/create_sql_server_firewall_test.rb +86 -0
  199. data/test/integration/database/create_sql_server_test.rb +53 -0
  200. data/test/integration/database/delete_sql_server_firewall_test.rb +70 -0
  201. data/test/integration/database/delete_sql_server_test.rb +58 -0
  202. data/test/integration/database/list_sql_server_firewall_test.rb +45 -0
  203. data/test/integration/database/list_sql_servers_test.rb +44 -0
  204. data/test/integration/database/reset_password_sql_server_test.rb +55 -0
  205. data/test/integration/location/Location_List_test.rb +39 -0
  206. data/test/integration/queue/clear_messages_test.rb +42 -0
  207. data/test/integration/queue/create_message_test.rb +75 -0
  208. data/test/integration/queue/create_queue_test.rb +50 -0
  209. data/test/integration/queue/delete_message_test.rb +67 -0
  210. data/test/integration/queue/delete_queue_test.rb +45 -0
  211. data/test/integration/queue/informative_errors_test.rb +42 -0
  212. data/test/integration/queue/list_messages_encoded_test.rb +79 -0
  213. data/test/integration/queue/list_messages_test.rb +79 -0
  214. data/test/integration/queue/list_queues_test.rb +44 -0
  215. data/test/integration/queue/peek_messages_test.rb +59 -0
  216. data/test/integration/queue/queue_gb18030_test.rb +131 -0
  217. data/test/integration/queue/queue_metadata_test.rb +40 -0
  218. data/test/integration/queue/update_message_test.rb +74 -0
  219. data/test/integration/service_bus/informative_errors_test.rb +37 -0
  220. data/test/integration/service_bus/queues_scenario_test.rb +200 -0
  221. data/test/integration/service_bus/queues_test.rb +266 -0
  222. data/test/integration/service_bus/relay_test.rb +132 -0
  223. data/test/integration/service_bus/rules_test.rb +145 -0
  224. data/test/integration/service_bus/sb_queue_gb18030_test.rb +182 -0
  225. data/test/integration/service_bus/scenario_test.rb +101 -0
  226. data/test/integration/service_bus/subscriptions_test.rb +211 -0
  227. data/test/integration/service_bus/topics_scenario_test.rb +406 -0
  228. data/test/integration/service_bus/topics_test.rb +129 -0
  229. data/test/integration/storage_management/storage_management_test.rb +160 -0
  230. data/test/integration/table/create_table_test.rb +36 -0
  231. data/test/integration/table/delete_entity_batch_test.rb +107 -0
  232. data/test/integration/table/delete_entity_test.rb +94 -0
  233. data/test/integration/table/delete_table_test.rb +40 -0
  234. data/test/integration/table/get_table_test.rb +37 -0
  235. data/test/integration/table/informative_errors_test.rb +39 -0
  236. data/test/integration/table/insert_entity_batch_test.rb +100 -0
  237. data/test/integration/table/insert_entity_test.rb +88 -0
  238. data/test/integration/table/insert_or_merge_entity_batch_test.rb +159 -0
  239. data/test/integration/table/insert_or_merge_entity_test.rb +143 -0
  240. data/test/integration/table/insert_or_replace_entity_batch_test.rb +152 -0
  241. data/test/integration/table/insert_or_replace_entity_test.rb +137 -0
  242. data/test/integration/table/merge_entity_batch_test.rb +128 -0
  243. data/test/integration/table/merge_entity_test.rb +113 -0
  244. data/test/integration/table/query_entities_test.rb +195 -0
  245. data/test/integration/table/query_tables_test.rb +43 -0
  246. data/test/integration/table/query_test.rb +251 -0
  247. data/test/integration/table/table_acl_test.rb +52 -0
  248. data/test/integration/table/table_gb18030_test.rb +355 -0
  249. data/test/integration/table/update_entity_batch_test.rb +149 -0
  250. data/test/integration/table/update_entity_test.rb +131 -0
  251. data/test/integration/test_helper.rb +42 -0
  252. data/test/integration/vm/VM_Create_test.rb +260 -0
  253. data/test/integration/vm/VM_Delete_test.rb +55 -0
  254. data/test/integration/vm/VM_Operations_test.rb +173 -0
  255. data/test/integration/vm_image/virtual_machine_disk_test.rb +37 -0
  256. data/test/integration/vm_image/virtual_machine_image_test.rb +37 -0
  257. data/test/integration/vnet/Virtual_Network_Create_test.rb +122 -0
  258. data/test/integration/vnet/Virtual_Network_list_test.rb +53 -0
  259. data/test/support/env.rb +19 -0
  260. data/test/support/fixtures.rb +36 -0
  261. data/test/support/name_generator.rb +168 -0
  262. data/test/support/stubs.rb +42 -0
  263. data/test/support/virtual_machine_name_generator.rb +102 -0
  264. data/test/support/virtual_network_helper.rb +73 -0
  265. data/test/test_helper.rb +54 -0
  266. data/test/unit/affinity_group/affinity_group_test.rb +192 -0
  267. data/test/unit/affinity_group/serialization_test.rb +88 -0
  268. data/test/unit/base_management/location_test.rb +57 -0
  269. data/test/unit/blob/blob_service_test.rb +1947 -0
  270. data/test/unit/cloud_service_management/cloud_service_management_service_test.rb +94 -0
  271. data/test/unit/cloud_service_management/serialization_test.rb +169 -0
  272. data/test/unit/core/auth/shared_key_lite_test.rb +51 -0
  273. data/test/unit/core/auth/shared_key_test.rb +58 -0
  274. data/test/unit/core/auth/signer_test.rb +30 -0
  275. data/test/unit/core/http/http_error_test.rb +57 -0
  276. data/test/unit/core/http/http_request_test.rb +66 -0
  277. data/test/unit/core/http/http_response_test.rb +45 -0
  278. data/test/unit/core/http/retry_policy_test.rb +23 -0
  279. data/test/unit/database/serialization_test.rb +97 -0
  280. data/test/unit/database/sql_database_server_service_test.rb +288 -0
  281. data/test/unit/service/serialization_test.rb +533 -0
  282. data/test/unit/service/storage_service_test.rb +293 -0
  283. data/test/unit/storage_management/serialization_test.rb +232 -0
  284. data/test/unit/storage_management/storage_management_service_test.rb +261 -0
  285. data/test/unit/table/edmtype_test.rb +108 -0
  286. data/test/unit/virtual_machine_image_management/serialization_test.rb +35 -0
  287. data/test/unit/virtual_machine_image_management/virtual_machine_image_management_service_test.rb +65 -0
  288. data/test/unit/virtual_machine_management/serialization_test.rb +258 -0
  289. data/test/unit/virtual_machine_management/virtual_machine_management_service_test.rb +440 -0
  290. data/test/unit/vnet/serialization_test.rb +187 -0
  291. data/test/unit/vnet/virtual_network_management_service_test.rb +131 -0
  292. metadata +476 -0
@@ -0,0 +1,27 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright 2013 Microsoft Open Technologies, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require "azure/base_management/serialization"
16
+
17
+ module Azure
18
+ module BaseManagement
19
+ class Location
20
+ attr_accessor :name, :available_services
21
+
22
+ def initialize
23
+ yield self if block_given?
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,172 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright 2013 Microsoft Open Technologies, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require 'azure/core/http/http_response'
16
+ require 'azure/core/http/http_request'
17
+ include Azure::Core::Http
18
+
19
+ # Represents an HTTP request that can perform synchronous queries to
20
+ # an HTTP server, returning a HttpResponse
21
+ module Azure
22
+ module BaseManagement
23
+ class ManagementHttpRequest < HttpRequest
24
+ attr_accessor :uri, :warn, :key, :cert
25
+
26
+ # Public: Creates the ManagementHttpRequest
27
+ #
28
+ # method - Symbol. The HTTP method to use (:get, :post, :put, :del, etc...)
29
+ # path - URI. The URI of the HTTP endpoint to query
30
+ # body - IO or String. The request body (optional)
31
+ # key - String. The request key
32
+ # cert - String. The request certificate
33
+ def initialize(method, path, body = nil)
34
+ super
35
+ @warn = false
36
+ content_length = body ? body.bytesize.to_s : '0'
37
+ @headers = {
38
+ 'x-ms-version' => '2014-04-01',
39
+ 'Content-Type' => 'application/xml',
40
+ 'Content-Length' => content_length
41
+ }
42
+ @uri = URI.parse(Azure.config.management_endpoint + Azure.config.subscription_id + path)
43
+ @key = Azure.config.http_private_key
44
+ @cert = Azure.config.http_certificate_key
45
+ end
46
+
47
+ # Public: Sends a request to HTTP server and returns a HttpResponse
48
+ #
49
+ # Returns a Nokogiri::XML instance of HttpResponse body
50
+ def call
51
+ request = http_request_class.new(uri.request_uri, headers)
52
+ request.body = body if body
53
+ http = http_setup
54
+ # http.set_debug_output($stdout)
55
+ response = wait_for_completion(HttpResponse.new(http.request(request)))
56
+ Nokogiri::XML response.body unless response.nil?
57
+ end
58
+
59
+ # Public: Wait for HTTP request completion.
60
+ #
61
+ # ==== Attributes
62
+ #
63
+ # * +response+ - Azure::Core::Http::HttpResponse. HttpResponse Response
64
+ #
65
+ # Print Error or Success of HttpRequest
66
+ def wait_for_completion(response)
67
+ ret_val = Nokogiri::XML response.body
68
+ if ret_val.at_css('Error Code') && ret_val.at_css('Error Code').content == 'AuthenticationFailed'
69
+ Loggerx.error_with_exit ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content
70
+ end
71
+ if response.status_code.to_i == 200 || response.status_code.to_i == 201
72
+ return response
73
+ elsif redirected? response
74
+ rebuild_request response
75
+ elsif response.status_code.to_i > 201 && response.status_code.to_i <= 299
76
+ check_completion(response.headers['x-ms-request-id'])
77
+ elsif warn && !response.success?
78
+ # Loggerx.warn ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content
79
+ elsif response.body
80
+ if ret_val.at_css('Error Code') && ret_val.at_css('Error Message')
81
+ Loggerx.error_with_exit ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content
82
+ else
83
+ Loggerx.exception_message "http error: #{response.status_code}"
84
+ end
85
+ else
86
+ Loggerx.exception_message "http error: #{response.status_code}"
87
+ end
88
+ end
89
+
90
+ # Public: Gets the status of the specified operation and determines whether
91
+ # the operation has succeeded, failed, or is still in progress.
92
+ #
93
+ # ==== Attributes
94
+ #
95
+ # * +request_id+ - String. x-ms-request-id response header of request
96
+ #
97
+ # See: http://msdn.microsoft.com/en-us/library/windowsazure/ee460783.aspx
98
+ #
99
+ # Print Error or Success of Operation.
100
+ def check_completion(request_id)
101
+ request_path = "/#{Azure.config.subscription_id}/operations/#{request_id}"
102
+ http = http_setup
103
+ headers['Content-Length'] = '0'
104
+ @method = :get
105
+ done = false
106
+ while not done
107
+ print '# '
108
+ request = http_request_class.new(request_path, headers)
109
+ response = HttpResponse.new(http.request(request))
110
+ ret_val = Nokogiri::XML response.body
111
+ status = xml_content(ret_val, 'Operation Status')
112
+ status_code = response.status_code.to_i
113
+ if status != 'InProgress'
114
+ done = true
115
+ end
116
+ if redirected? response
117
+ host_uri = URI.parse(response.headers['location'])
118
+ http = http_setup(host_uri)
119
+ done = false
120
+ end
121
+ if done
122
+ if status.downcase != 'succeeded'
123
+ error_code = xml_content(ret_val, 'Operation Error Code')
124
+ error_msg = xml_content(ret_val, 'Operation Error Message')
125
+ Loggerx.exception_message "#{error_code}: #{error_msg}"
126
+ else
127
+ Loggerx.success "#{status.downcase} (#{status_code})"
128
+ end
129
+ return
130
+ else
131
+ sleep(5)
132
+ end
133
+ end
134
+ end
135
+
136
+ def rebuild_request(response)
137
+ host_uri = URI.parse(response.headers['location'])
138
+ request = http_request_class.new(host_uri.request_uri, headers)
139
+ request.body = body if body
140
+ http = http_setup(host_uri)
141
+ wait_for_completion(HttpResponse.new(http.request(request)))
142
+ end
143
+
144
+ def redirected?(response)
145
+ (response.status_code.to_i == 307)
146
+ end
147
+
148
+ def http_setup(host_uri = nil)
149
+ @uri = host_uri if host_uri
150
+ http = nil
151
+ if ENV['HTTP_PROXY'] || ENV['HTTPS_PROXY']
152
+ if ENV['HTTP_PROXY']
153
+ proxy_uri = URI.parse(ENV['HTTP_PROXY'])
154
+ else
155
+ proxy_uri = URI.parse(ENV['HTTPS_PROXY'])
156
+ end
157
+ http = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new(uri.host, uri.port)
158
+ else
159
+ http = Net::HTTP.new(uri.host, uri.port)
160
+ end
161
+
162
+ if uri.scheme.downcase == 'https'
163
+ http.use_ssl = true
164
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
165
+ http.cert = cert
166
+ http.key = key
167
+ end
168
+ http
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,129 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright 2013 Microsoft Open Technologies, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+
16
+ module Azure
17
+ module BaseManagement
18
+ module Serialization
19
+ def self.locations_from_xml(locationXML)
20
+ location_objs = []
21
+ xml = locationXML.css('Locations Location')
22
+ xml.each do |meta_node|
23
+ loc = Location.new
24
+ loc.name = xml_content(meta_node, 'Name')
25
+ available_services = meta_node.css('AvailableServices').children
26
+ loc.available_services = available_services.to_ary.join(', ')
27
+ location_objs << loc
28
+ end
29
+ location_objs
30
+ end
31
+
32
+ def self.affinity_group_to_xml(name, location, label, options = {})
33
+ builder = Nokogiri::XML::Builder.new do |xml|
34
+ xml.CreateAffinityGroup(
35
+ 'xmlns' => 'http://schemas.microsoft.com/windowsazure'
36
+ ) do
37
+ xml.Name name
38
+ xml.Label Base64.encode64(label).strip
39
+ xml.Description options[:description]
40
+ xml.Location location
41
+ end
42
+ end
43
+ builder.doc.to_xml
44
+ end
45
+
46
+ def self.affinity_groups_from_xml(affinity_xml)
47
+ affinity_groups = []
48
+ affinity_group_services_xml = affinity_xml.css(
49
+ 'AffinityGroups AffinityGroup'
50
+ )
51
+
52
+ affinity_group_services_xml.each do |ag_xml|
53
+ affinity_group = AffinityGroup.new
54
+ affinity_group.name = xml_content(ag_xml, 'Name')
55
+ affinity_group.label = Base64.decode64(xml_content(ag_xml, 'Label'))
56
+ affinity_group.description = xml_content(ag_xml, 'Description')
57
+ affinity_group.location = xml_content(ag_xml, 'Location')
58
+
59
+ capabilities = ag_xml.css('Capabilities Capability')
60
+ affinity_group.capability = capabilities.map { |x| x.content }
61
+ affinity_groups << affinity_group
62
+ end
63
+ affinity_groups.compact
64
+ end
65
+
66
+ def self.affinity_group_from_xml(affinity_xml)
67
+ hosted_services_xml = affinity_xml.css(
68
+ 'AffinityGroup HostedServices HostedService'
69
+ )
70
+
71
+ storage_services_xml = affinity_xml.css(
72
+ 'AffinityGroup StorageServices StorageService'
73
+ )
74
+
75
+ capability_xml = affinity_xml.css(
76
+ 'AffinityGroup Capabilities Capability'
77
+ )
78
+
79
+ AffinityGroup.new do |affinity_group|
80
+ affinity_group.name = xml_content(
81
+ affinity_xml,
82
+ 'AffinityGroup Name'
83
+ )
84
+ affinity_group.label = Base64.decode64(
85
+ xml_content(
86
+ affinity_xml,
87
+ 'AffinityGroup Label'
88
+ )
89
+ )
90
+ affinity_group.description = xml_content(
91
+ affinity_xml,
92
+ 'AffinityGroup Description'
93
+ )
94
+ affinity_group.location = xml_content(
95
+ affinity_xml,
96
+ 'AffinityGroup Location'
97
+ )
98
+ affinity_group.hosted_services = []
99
+ hosted_services_xml.each do |hosted_service_xml|
100
+ affinity_group.hosted_services << {
101
+ url: xml_content(hosted_service_xml, 'Url'),
102
+ service_name: xml_content(hosted_service_xml, 'ServiceName')
103
+ }
104
+ end
105
+ affinity_group.storage_services = []
106
+ storage_services_xml.each do |storage_service_xml|
107
+ affinity_group.storage_services << {
108
+ url: xml_content(storage_service_xml, 'Url'),
109
+ service_name: xml_content(storage_service_xml, 'ServiceName')
110
+ }
111
+ end
112
+ affinity_group.capability = capability_xml.map { |x| x.content }
113
+ end
114
+ end
115
+
116
+ def self.resource_to_xml(label, options = {})
117
+ builder = Nokogiri::XML::Builder.new do |xml|
118
+ xml.UpdateAffinityGroup(
119
+ 'xmlns' => 'http://schemas.microsoft.com/windowsazure'
120
+ ) do
121
+ xml.Label Base64.encode64(label).strip
122
+ xml.Description options[:description] if options[:description]
123
+ end
124
+ end
125
+ builder.doc.to_xml
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,45 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright 2013 Microsoft Open Technologies, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ # Represents an HTTP request that can perform synchronous queries to
16
+ # an HTTP server, returning a HttpResponse
17
+ module Azure
18
+ module BaseManagement
19
+ # This class is used for communicating with the Management certificate authentication API endpoint
20
+ class SqlManagementHttpRequest < ManagementHttpRequest
21
+ attr_accessor :uri
22
+ # Public: Creates the ManagementHttpRequest
23
+ #
24
+ # method - Symbol. The HTTP method to use (:get, :post, :put, :del, etc...)
25
+ # path - URI. The URI of the HTTP endpoint to query
26
+ # body - IO or String. The request body (optional)
27
+ def initialize(method, path, body = nil)
28
+ if sql_endpoint?
29
+ super(method, path, body)
30
+ @headers['x-ms-version'] = '1.0'
31
+ @uri = URI.parse(Azure.config.sql_database_management_endpoint + Azure.config.subscription_id + path)
32
+ else
33
+ path = "/services/sqlservers#{path}"
34
+ super(method, path, body)
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def sql_endpoint?
41
+ Azure.config.sql_database_authentication_mode == :sql_server
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,32 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+
16
+ module Azure
17
+ module Blob
18
+ class Blob
19
+
20
+ def initialize
21
+ @properties = {}
22
+ @metadata = {}
23
+ yield self if block_given?
24
+ end
25
+
26
+ attr_accessor :name
27
+ attr_accessor :snapshot
28
+ attr_accessor :properties
29
+ attr_accessor :metadata
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,1423 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #--------------------------------------------------------------------------
15
+ require 'azure/service/storage_service'
16
+ require 'azure/blob/serialization'
17
+ require 'base64'
18
+
19
+ module Azure
20
+ module Blob
21
+ class BlobService < Service::StorageService
22
+
23
+ def initialize
24
+ super()
25
+ @host = Azure.config.storage_blob_host
26
+ end
27
+
28
+ # Public: Get a list of Containers from the server
29
+ #
30
+ # ==== Attributes
31
+ #
32
+ # * +options+ - Hash. Optional parameters.
33
+ #
34
+ # ==== Options
35
+ #
36
+ # Accepted key/value pairs in options parameter are:
37
+ # * +:prefix+ - String. Filters the results to return only containers
38
+ # whose name begins with the specified prefix. (optional)
39
+ #
40
+ # * +:marker+ - String. An identifier the specifies the portion of the
41
+ # list to be returned. This value comes from the property
42
+ # Azure::Service::EnumerationResults.continuation_token when there
43
+ # are more containers available than were returned. The
44
+ # marker value may then be used here to request the next set
45
+ # of list items. (optional)
46
+ #
47
+ # * +:max_results+ - Integer. Specifies the maximum number of containers to return.
48
+ # If max_results is not specified, or is a value greater than
49
+ # 5,000, the server will return up to 5,000 items. If it is set
50
+ # to a value less than or equal to zero, the server will return
51
+ # status code 400 (Bad Request). (optional)
52
+ #
53
+ # * +:metadata+ - Boolean. Specifies whether or not to return the container metadata.
54
+ # (optional, Default=false)
55
+ #
56
+ # * +:timeout+ - Integer. A timeout in seconds.
57
+ #
58
+ # NOTE: Metadata requested with the :metadata parameter must have been stored in
59
+ # accordance with the naming restrictions imposed by the 2009-09-19 version of the Blob
60
+ # service. Beginning with that version, all metadata names must adhere to the naming
61
+ # conventions for C# identifiers.
62
+ #
63
+ # See: http://msdn.microsoft.com/en-us/library/aa664670(VS.71).aspx
64
+ #
65
+ # Any metadata with invalid names which were previously stored, will be returned with the
66
+ # key "x-ms-invalid-name" in the metadata hash. This may contain multiple values and be an
67
+ # Array (vs a String if it only contains a single value).
68
+ #
69
+ # Returns an Azure::Service::EnumerationResults
70
+ def list_containers(options={})
71
+ query = { }
72
+ if options
73
+ query["prefix"] = options[:prefix] if options[:prefix]
74
+ query["marker"] = options[:marker] if options[:marker]
75
+ query["maxresults"] = options[:max_results].to_s if options[:max_results]
76
+ query["include"] = "metadata" if options[:metadata] == true
77
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
78
+ end
79
+
80
+ uri = containers_uri(query)
81
+ response = call(:get, uri)
82
+
83
+ Serialization.container_enumeration_results_from_xml(response.body)
84
+ end
85
+
86
+ # Public: Create a new container
87
+ #
88
+ # ==== Attributes
89
+ #
90
+ # * +name+ - String. The name of the container
91
+ # * +options+ - Hash. Optional parameters.
92
+ #
93
+ # ==== Options
94
+ #
95
+ # Accepted key/value pairs in options parameter are:
96
+ # * +:metadata+ - Hash. User defined metadata for the container (optional)
97
+ # * +:public_access_level+ - String. One of "container" or "blob" (optional)
98
+ # * +:timeout+ - Integer. A timeout in seconds.
99
+ #
100
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179468.aspx
101
+ #
102
+ # Returns a Container
103
+ def create_container(name, options={})
104
+ query = { }
105
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
106
+
107
+ uri = container_uri(name, query)
108
+
109
+ headers = { }
110
+
111
+ add_metadata_to_headers(options[:metadata], headers) if options[:metadata]
112
+
113
+ headers["x-ms-blob-public-access"] = options[:public_access_level].to_s if options[:public_access_level]
114
+
115
+ response = call(:put, uri, nil, headers)
116
+
117
+ container = Serialization.container_from_headers(response.headers)
118
+ container.name = name
119
+ container.metadata = options[:metadata]
120
+ container
121
+ end
122
+
123
+ # Public: Deletes a container
124
+ #
125
+ # ==== Attributes
126
+ #
127
+ # * +name+ - String. The name of the container
128
+ # * +options+ - Hash. Optional parameters.
129
+ #
130
+ # ==== Options
131
+ #
132
+ # Accepted key/value pairs in options parameter are:
133
+ # * +:timeout+ - Integer. A timeout in seconds.
134
+ #
135
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179408.aspx
136
+ #
137
+ # Returns nil on success
138
+ def delete_container(name, options={})
139
+ query = { }
140
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
141
+
142
+ call(:delete, container_uri(name, query))
143
+ nil
144
+ end
145
+
146
+ # Public: Returns all properties and metadata on the container.
147
+ #
148
+ # ==== Attributes
149
+ #
150
+ # * +name+ - String. The name of the container
151
+ # * +options+ - Hash. Optional parameters.
152
+ #
153
+ # ==== Options
154
+ #
155
+ # Accepted key/value pairs in options parameter are:
156
+ # * +:timeout+ - Integer. A timeout in seconds.
157
+ #
158
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179370.aspx
159
+ #
160
+ # Returns a Container
161
+ def get_container_properties(name, options={})
162
+ query = { }
163
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
164
+
165
+ response = call(:get, container_uri(name, query))
166
+
167
+ container = Serialization.container_from_headers(response.headers)
168
+ container.name = name
169
+ container
170
+ end
171
+
172
+ # Public: Returns only user-defined metadata for the specified container.
173
+ #
174
+ # ==== Attributes
175
+ #
176
+ # * +name+ - String. The name of the container
177
+ # * +options+ - Hash. Optional parameters.
178
+ #
179
+ # ==== Options
180
+ #
181
+ # Accepted key/value pairs in options parameter are:
182
+ # * +:timeout+ - Integer. A timeout in seconds.
183
+ #
184
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691976.aspx
185
+ #
186
+ # Returns a Container
187
+ def get_container_metadata(name, options={})
188
+ query = { "comp" => "metadata" }
189
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
190
+
191
+ response = call(:get, container_uri(name, query))
192
+
193
+ container = Serialization.container_from_headers(response.headers)
194
+ container.name = name
195
+ container
196
+ end
197
+
198
+ # Public: Gets the access control list (ACL) and any container-level access policies
199
+ # for the container.
200
+ #
201
+ # ==== Attributes
202
+ #
203
+ # * +name+ - String. The name of the container
204
+ # * +options+ - Hash. Optional parameters.
205
+ #
206
+ # ==== Options
207
+ #
208
+ # Accepted key/value pairs in options parameter are:
209
+ # * +:timeout+ - Integer. A timeout in seconds.
210
+ #
211
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179469.aspx
212
+ #
213
+ # Returns a tuple of (container, signed_identifiers)
214
+ # container - A Azure::Entity::Blob::Container instance
215
+ # signed_identifiers - A list of Azure::Entity::SignedIdentifier instances
216
+ #
217
+ def get_container_acl(name, options={})
218
+ query = { "comp" => "acl" }
219
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
220
+ response = call(:get, container_uri(name, query))
221
+
222
+ container = Serialization.container_from_headers(response.headers)
223
+ container.name = name
224
+
225
+ signed_identifiers = nil
226
+ signed_identifiers = Serialization.signed_identifiers_from_xml(response.body) if response.body != nil && response.body.length > 0
227
+
228
+ return container, signed_identifiers
229
+ end
230
+
231
+ # Public: Sets the ACL and any container-level access policies for the container.
232
+ #
233
+ # ==== Attributes
234
+ #
235
+ # * +name+ - String. The name of the container
236
+ # * +public_access_level+ - String. The container public access level
237
+ # * +options+ - Hash. Optional parameters.
238
+ #
239
+ # ==== Options
240
+ #
241
+ # Accepted key/value pairs in options parameter are:
242
+ # * +:signed_identifiers+ - Array. A list of Azure::Entity::SignedIdentifier instances (optional)
243
+ # * +:timeout+ - Integer. A timeout in seconds.
244
+ #
245
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179391.aspx
246
+ #
247
+ # Returns a tuple of (container, signed_identifiers)
248
+ # * +container+ - A Azure::Entity::Blob::Container instance
249
+ # * +signed_identifiers+ - A list of Azure::Entity::SignedIdentifier instances
250
+ #
251
+ def set_container_acl(name, public_access_level, options={})
252
+ query = { "comp" => "acl" }
253
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
254
+ uri =container_uri(name, query)
255
+
256
+ headers = { }
257
+ headers["x-ms-blob-public-access"] = public_access_level if public_access_level && public_access_level.to_s.length > 0
258
+
259
+ signed_identifiers = nil
260
+ signed_identifiers = options[:signed_identifiers] if options[:signed_identifiers]
261
+
262
+ body = nil
263
+ body = Serialization.signed_identifiers_to_xml(signed_identifiers) if signed_identifiers && headers["x-ms-blob-public-access"] == "container"
264
+
265
+ response = call(:put, uri, body, headers)
266
+
267
+ container = Serialization.container_from_headers(response.headers)
268
+ container.name = name
269
+ container.public_access_level = public_access_level
270
+
271
+ return container, signed_identifiers || []
272
+
273
+ end
274
+
275
+ # Public: Sets custom metadata for the container.
276
+ #
277
+ # ==== Attributes
278
+ #
279
+ # * +name+ - String. The name of the container
280
+ # * +metadata+ - Hash. A Hash of the metadata values
281
+ # * +options+ - Hash. Optional parameters.
282
+ #
283
+ # ==== Options
284
+ #
285
+ # Accepted key/value pairs in options parameter are:
286
+ # * +:timeout+ - Integer. A timeout in seconds.
287
+ #
288
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179362.aspx
289
+ #
290
+ # Returns nil on success
291
+ def set_container_metadata(name, metadata, options={})
292
+ query = { "comp" => "metadata" }
293
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
294
+
295
+ headers = { }
296
+ add_metadata_to_headers(metadata, headers) if metadata
297
+
298
+ call(:put, container_uri(name, query), nil, headers)
299
+ nil
300
+ end
301
+
302
+ # Public: Get a list of Blobs from the server
303
+ #
304
+ # ==== Attributes
305
+ #
306
+ # * +name+ - String. The name of the container to list blobs for.
307
+ # * +options+ - Hash. Optional parameters.
308
+ #
309
+ # ==== Options
310
+ #
311
+ # Accepted key/value pairs in options parameter are:
312
+ # * +:prefix+ - String. Filters the results to return only blobs
313
+ # whose name begins with the specified prefix. (optional)
314
+ # * +:delimiter+ - String. When the request includes this parameter, the operation
315
+ # returns a BlobPrefix element in the response body that acts as a
316
+ # placeholder for all blobs whose names begin with the same substring
317
+ # up to the appearance of the delimiter character. The delimiter may
318
+ # be a single character or a string.
319
+ # * +:marker+ - String. An identifier that specifies the portion of the
320
+ # list to be returned. This value comes from the property
321
+ # Azure::Service::EnumerationResults.continuation_token when
322
+ # there are more blobs available than were returned. The
323
+ # marker value may then be used here to request the next set
324
+ # of list items. (optional)
325
+ # * +:max_results+ - Integer. Specifies the maximum number of blobs to return.
326
+ # If max_results is not specified, or is a value greater than
327
+ # 5,000, the server will return up to 5,000 items. If it is set
328
+ # to a value less than or equal to zero, the server will return
329
+ # status code 400 (Bad Request). (optional)
330
+ # * +:metadata+ - Boolean. Specifies whether or not to return the blob metadata.
331
+ # (optional, Default=false)
332
+ # * +:snapshots+ - Boolean. Specifies that snapshots should be included in the
333
+ # enumeration. Snapshots are listed from oldest to newest in the
334
+ # response. (optional, Default=false)
335
+ # * +:uncomittedblobs+ - Boolean. Specifies that blobs for which blocks have been uploaded,
336
+ # but which have not been committed using put_block_list, be included
337
+ # in the response. (optional, Default=false)
338
+ # * +:copy+ - Boolean. Specifies that metadata related to any current or previous
339
+ # copy_blob operation should be included in the response.
340
+ # (optional, Default=false)
341
+ # * +:timeout+ - Integer. A timeout in seconds.
342
+ #
343
+ # NOTE: Metadata requested with the :metadata parameter must have been stored in
344
+ # accordance with the naming restrictions imposed by the 2009-09-19 version of the Blob
345
+ # service. Beginning with that version, all metadata names must adhere to the naming
346
+ # conventions for C# identifiers.
347
+ #
348
+ # See: http://msdn.microsoft.com/en-us/library/windowsazure/dd135734.aspx
349
+ #
350
+ # Any metadata with invalid names which were previously stored, will be returned with the
351
+ # key "x-ms-invalid-name" in the metadata hash. This may contain multiple values and be an
352
+ # Array (vs a String if it only contains a single value).
353
+ #
354
+ # Returns an Azure::Service::EnumerationResults
355
+ def list_blobs(name, options={})
356
+ query = { "comp" => "list" }
357
+ query["prefix"] = options[:prefix].gsub(/\\/, "/") if options[:prefix]
358
+ query["delimiter"] = options[:delimiter] if options[:delimiter]
359
+ query["marker"] = options[:marker] if options[:marker]
360
+ query["maxresults"] = options[:max_results].to_s if options[:max_results]
361
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
362
+
363
+ included_datasets = []
364
+ included_datasets.push("metadata") if options[:metadata] == true
365
+ included_datasets.push("snapshots") if options[:snapshots] == true
366
+ included_datasets.push("uncommittedblobs") if options[:uncommittedblobs] == true
367
+ included_datasets.push("copy") if options[:copy] == true
368
+
369
+ query["include"] = included_datasets.join ',' if included_datasets.length > 0
370
+
371
+ uri = container_uri(name, query)
372
+ response = call(:get, uri)
373
+
374
+ Serialization.blob_enumeration_results_from_xml(response.body)
375
+ end
376
+
377
+ # Public: Creates a new page blob. Note that calling create_page_blob to create a page
378
+ # blob only initializes the blob. To add content to a page blob, call create_blob_pages method.
379
+ #
380
+ # ==== Attributes
381
+ #
382
+ # * +container+ - String. The container name.
383
+ # * +blob+ - String. The blob name.
384
+ # * +length+ - Integer. Specifies the maximum size for the page blob, up to 1 TB. The page blob size must be aligned to a 512-byte boundary.
385
+ # * +options+ - Hash. Optional parameters.
386
+ #
387
+ # ==== Options
388
+ #
389
+ # Accepted key/value pairs in options parameter are:
390
+ # * +:content_type+ - String. Content type for the request. Will be saved with blob unless alternate value is provided in blob_content_type.
391
+ # * +:content_encoding+ - String. Content encoding for the request. Will be saved with blob unless alternate value is provided in blob_content_encoding.
392
+ # * +:content_language+ - String. Content language for the request. Will be saved with blob unless alternate value is provided in blob_content_language.
393
+ # * +:content_md5+ - String. Content MD5 for the request. Will be saved with blob unless alternate value is provided in blob_content_md5.
394
+ # * +:cache_control+ - String. Cache control for the request. Will be saved with blob unless alternate value is provided in blob_cache_control.
395
+ # * +:blob_content_type+ - String. Content type for the blob. Will be saved with blob.
396
+ # * +:blob_content_encoding+ - String. Content encoding for the blob. Will be saved with blob.
397
+ # * +:blob_content_language+ - String. Content language for the blob. Will be saved with blob.
398
+ # * +:blob_content_md5+ - String. Content MD5 for the blob. Will be saved with blob.
399
+ # * +:blob_cache_control+ - String. Cache control for the blob. Will be saved with blob.
400
+ # * +:metadata+ - Hash. Custom metadata values to store with the blob.
401
+ # * +:sequence_number+ - Integer. The sequence number is a user-controlled value that you can use to track requests. The value of the sequence number must be between 0 and 2^63 - 1.The default value is 0.
402
+ # * +:timeout+ - Integer. A timeout in seconds.
403
+ #
404
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179451.aspx
405
+ #
406
+ # Returns a Blob
407
+ def create_page_blob(container, blob, length, options={})
408
+ query = { }
409
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
410
+
411
+ uri = blob_uri(container, blob, query)
412
+
413
+ headers = { }
414
+
415
+ # set x-ms-blob-type to PageBlob
416
+ headers["x-ms-blob-type"] = "PageBlob"
417
+
418
+ # ensure content-length is 0 and x-ms-blob-content-length is the blob length
419
+ headers["Content-Length"] = 0.to_s
420
+ headers["x-ms-blob-content-length"] = length.to_s
421
+
422
+ # set x-ms-sequence-number from options (or default to 0)
423
+ headers["x-ms-sequence-number"] = (options[:sequence_number] || 0).to_s
424
+
425
+ # set the rest of the optional headers
426
+ headers["Content-Type"] = options[:content_type] if options[:content_type]
427
+ headers["Content-Encoding"] = options[:content_encoding] if options[:content_encoding]
428
+ headers["Content-Language"] = options[:content_language] if options[:content_language]
429
+ headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
430
+ headers["Cache-Control"] = options[:cache_control] if options[:cache_control]
431
+
432
+ headers["x-ms-blob-content-type"] = options[:blob_content_type] if options[:blob_content_type]
433
+ headers["x-ms-blob-content-encoding"] = options[:blob_content_encoding] if options[:blob_content_encoding]
434
+ headers["x-ms-blob-content-language"] = options[:blob_content_language] if options[:blob_content_language]
435
+ headers["x-ms-blob-content-md5"] = options[:blob_content_md5] if options[:blob_content_md5]
436
+ headers["x-ms-blob-cache-control"] = options[:blob_cache_control] if options[:blob_cache_control]
437
+
438
+ add_metadata_to_headers(options[:metadata], headers) if options[:metadata]
439
+
440
+ # call PutBlob with empty body
441
+ response = call(:put, uri, nil, headers)
442
+
443
+ result = Serialization.blob_from_headers(response.headers)
444
+ result.name = blob
445
+
446
+ result
447
+ end
448
+
449
+ # Public: Creates a range of pages in a page blob.
450
+ #
451
+ # ==== Attributes
452
+ #
453
+ # * +container+ - String. Name of container
454
+ # * +blob+ - String. Name of blob
455
+ # * +start_range+ - Integer. Position of first byte of first page
456
+ # * +end_range+ - Integer. Position of last byte of of last page
457
+ # * +content+ - IO or String. Content to write. Length in bytes should equal end_range - start_range
458
+ # * +options+ - Hash. A collection of options.
459
+ #
460
+ # ==== Options
461
+ #
462
+ # Accepted key/value pairs in options parameter are:
463
+ # * +:if_sequence_number_le+ - If the blob's sequence number is less than or equal to the specified value, the request proceeds; otherwise it fails with the SequenceNumberConditionNotMet error (HTTP status code 412 - Precondition Failed).
464
+ # * +:if_sequence_number_lt+ - If the blob's sequence number is less than the specified value, the request proceeds; otherwise it fails with SequenceNumberConditionNotMet error (HTTP status code 412 - Precondition Failed).
465
+ # * +:if_sequence_number_eq+ - If the blob's sequence number is equal to the specified value, the request proceeds; otherwise it fails with SequenceNumberConditionNotMet error (HTTP status code 412 - Precondition Failed).
466
+ # * +:if_modified_since+ - A DateTime value. Specify this conditional header to write the page only if the blob has been modified since the specified date/time. If the blob has not been modified, the Blob service returns status code 412 (Precondition Failed).
467
+ # * +:if_unmodified_since+ - A DateTime value. Specify this conditional header to write the page only if the blob has not been modified since the specified date/time. If the blob has been modified, the Blob service returns status code 412 (Precondition Failed).
468
+ # * +:if_match+ - An ETag value. Specify an ETag value for this conditional header to write the page only if the blob's ETag value matches the value specified. If the values do not match, the Blob service returns status code 412 (Precondition Failed).
469
+ # * +:if_none_match+ - An ETag value. Specify an ETag value for this conditional header to write the page only if the blob's ETag value does not match the value specified. If the values are identical, the Blob service returns status code 412 (Precondition Failed).
470
+ # * +:timeout+ - Integer. A timeout in seconds.
471
+ #
472
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691975.aspx
473
+ #
474
+ # Returns Blob
475
+ def create_blob_pages(container, blob, start_range, end_range, content, options={})
476
+ query = { "comp" => "page" }
477
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
478
+
479
+ uri = blob_uri(container, blob, query)
480
+ headers = { }
481
+ headers["x-ms-range"] = "bytes=#{start_range}-#{end_range}"
482
+ headers["x-ms-page-write"] = "update"
483
+
484
+ # clear default content type
485
+ headers["Content-Type"] = ""
486
+
487
+ # set optional headers
488
+ unless options.empty?
489
+ headers["x-ms-if-sequence-number-le"] = options[:if_sequence_number_le] if options[:if_sequence_number_le]
490
+ headers["x-ms-if-sequence-number-lt"] = options[:if_sequence_number_lt] if options[:if_sequence_number_lt]
491
+ headers["x-ms-if-sequence-number-eq"] = options[:if_sequence_number_eq] if options[:if_sequence_number_eq]
492
+ headers["If-Modified-Since"] = options[:if_modified_since] if options[:if_modified_since]
493
+ headers["If-Unmodified-Since"] = options[:if_unmodified_since] if options[:if_unmodified_since]
494
+ headers["If-Match"] = options[:if_match] if options[:if_match]
495
+ headers["If-None-Match"] = options[:if_none_match] if options[:if_none_match]
496
+ end
497
+
498
+ response = call(:put, uri, content, headers)
499
+
500
+ result = Serialization.blob_from_headers(response.headers)
501
+ result.name = blob
502
+
503
+ result
504
+ end
505
+
506
+ # Public: Clears a range of pages from the blob.
507
+ #
508
+ # ==== Attributes
509
+ #
510
+ # * +container+ - String. Name of container.
511
+ # * +blob+ - String. Name of blob.
512
+ # * +start_range+ - Integer. Position of first byte of first page.
513
+ # * +end_range+ - Integer. Position of last byte of of last page.
514
+ # * +options+ - Hash. Optional parameters.
515
+ #
516
+ # ==== Options
517
+ #
518
+ # Accepted key/value pairs in options parameter are:
519
+ # * +:timeout+ - Integer. A timeout in seconds.
520
+ #
521
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691975.aspx
522
+ #
523
+ # Returns Blob
524
+ def clear_blob_pages(container, blob, start_range, end_range, options={})
525
+ query = { "comp" => "page" }
526
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
527
+
528
+ uri = blob_uri(container, blob, query)
529
+
530
+ headers = { }
531
+ headers["x-ms-range"] = "bytes=#{start_range}-#{end_range}"
532
+ headers["x-ms-page-write"] = "clear"
533
+
534
+ # clear default content type
535
+ headers["Content-Type"] = ""
536
+
537
+ response = call(:put, uri, nil, headers)
538
+
539
+ result = Serialization.blob_from_headers(response.headers)
540
+ result.name = blob
541
+
542
+ result
543
+ end
544
+
545
+ # Public: Creates a new block blob or updates the content of an existing block blob.
546
+ #
547
+ # Updating an existing block blob overwrites any existing metadata on the blob
548
+ # Partial updates are not supported with create_block_blob the content of the
549
+ # existing blob is overwritten with the content of the new blob. To perform a
550
+ # partial update of the content of a block blob, use the create_block_list
551
+ # method.
552
+ #
553
+ # Note that the default content type is application/octet-stream.
554
+ #
555
+ # ==== Attributes
556
+ #
557
+ # * +container+ - String. The container name.
558
+ # * +blob+ - String. The blob name.
559
+ # * +content+ - IO or String. The content of the blob.
560
+ # * +options+ - Hash. Optional parameters.
561
+ #
562
+ # ==== Options
563
+ #
564
+ # Accepted key/value pairs in options parameter are:
565
+ # * +:content_type+ - String. Content type for the request. Will be saved with blob unless alternate value is provided in blob_content_type.
566
+ # * +:content_encoding+ - String. Content encoding for the request. Will be saved with blob unless alternate value is provided in blob_content_encoding.
567
+ # * +:content_language+ - String. Content language for the request. Will be saved with blob unless alternate value is provided in blob_content_language.
568
+ # * +:content_md5+ - String. Content MD5 for the request. Will be saved with blob unless alternate value is provided in blob_content_md5.
569
+ # * +:cache_control+ - String. Cache control for the request. Will be saved with blob unless alternate value is provided in blob_cache_control.
570
+ # * +:blob_content_type+ - String. Content type for the blob. Will be saved with blob.
571
+ # * +:blob_content_encoding+ - String. Content encoding for the blob. Will be saved with blob.
572
+ # * +:blob_content_language+ - String. Content language for the blob. Will be saved with blob.
573
+ # * +:blob_content_md5+ - String. Content MD5 for the blob. Will be saved with blob.
574
+ # * +:blob_cache_control+ - String. Cache control for the blob. Will be saved with blob.
575
+ # * +:metadata+ - Hash. Custom metadata values to store with the blob.
576
+ # * +:timeout+ - Integer. A timeout in seconds.
577
+ #
578
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179451.aspx
579
+ #
580
+ # Returns a Blob
581
+ def create_block_blob(container, blob, content, options={})
582
+ query = { }
583
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
584
+
585
+ uri = blob_uri(container, blob, query)
586
+
587
+ headers = { }
588
+
589
+ # set x-ms-blob-type to BlockBlob
590
+ headers["x-ms-blob-type"] = "BlockBlob"
591
+
592
+ # set the rest of the optional headers
593
+ headers["Content-Type"] = options[:content_type] || "application/octet-stream"
594
+ headers["Content-Encoding"] = options[:content_encoding] if options[:content_encoding]
595
+ headers["Content-Language"] = options[:content_language] if options[:content_language]
596
+ headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
597
+ headers["Cache-Control"] = options[:cache_control] if options[:cache_control]
598
+
599
+ headers["x-ms-blob-content-type"] = options[:blob_content_type] if options[:blob_content_type]
600
+ headers["x-ms-blob-content-encoding"] = options[:blob_content_encoding] if options[:blob_content_encoding]
601
+ headers["x-ms-blob-content-language"] = options[:blob_content_language] if options[:blob_content_language]
602
+ headers["x-ms-blob-content-md5"] = options[:blob_content_md5] if options[:blob_content_md5]
603
+ headers["x-ms-blob-cache-control"] = options[:blob_cache_control] if options[:blob_cache_control]
604
+
605
+ add_metadata_to_headers(options[:metadata], headers) if options[:metadata]
606
+
607
+ # call PutBlob with empty body
608
+ response = call(:put, uri, content, headers)
609
+
610
+ result = Serialization.blob_from_headers(response.headers)
611
+ result.name = blob
612
+
613
+ result
614
+ end
615
+
616
+ # Public: Creates a new block to be committed as part of a block blob.
617
+ #
618
+ # ==== Attributes
619
+ #
620
+ # * +container+ - String. The container name.
621
+ # * +blob+ - String. The blob name.
622
+ # * +block_id+ - String. The block id. Note: this should be the raw block id, not Base64 encoded.
623
+ # * +content+ - IO or String. The content of the blob.
624
+ # * +options+ - Hash. Optional parameters.
625
+ #
626
+ # ==== Options
627
+ #
628
+ # Accepted key/value pairs in options parameter are:
629
+ # * +:content_md5+ - String. Content MD5 for the request contents.
630
+ # * +:timeout+ - Integer. A timeout in seconds.
631
+ #
632
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd135726.aspx
633
+ #
634
+ # Returns the MD5 of the uploaded block (as calculated by the server)
635
+ def create_blob_block(container, blob, block_id, content, options={})
636
+ query = { "comp" => "block" }
637
+ query["blockid"] = Base64.strict_encode64(block_id)
638
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
639
+
640
+ uri = blob_uri(container, blob, query)
641
+
642
+ headers = { }
643
+ headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
644
+
645
+ response = call(:put, uri, content, headers)
646
+
647
+ response.headers["Content-MD5"]
648
+ end
649
+
650
+ # Public: Commits existing blob blocks to a blob.
651
+ #
652
+ # This method writes a blob by specifying the list of block IDs that make up the
653
+ # blob. In order to be written as part of a blob, a block must have been
654
+ # successfully written to the server in a prior create_blob_block method.
655
+ #
656
+ # You can call Put Block List to update a blob by uploading only those blocks
657
+ # that have changed, then committing the new and existing blocks together.
658
+ # You can do this by specifying whether to commit a block from the committed
659
+ # block list or from the uncommitted block list, or to commit the most recently
660
+ # uploaded version of the block, whichever list it may belong to.
661
+ #
662
+ # ==== Attributes
663
+ #
664
+ # * +container+ - String. The container name.
665
+ # * +blob+ - String. The blob name.
666
+ # * +block_list+ - Array. A ordered list of lists in the following format:
667
+ # [ ["block_id1", :committed], ["block_id2", :uncommitted], ["block_id3"], ["block_id4", :committed]... ]
668
+ # The first element of the inner list is the block_id, the second is optional
669
+ # and can be either :committed or :uncommitted to indicate in which group of blocks
670
+ # the id should be looked for. If it is omitted, the latest of either group will be used.
671
+ # * +options+ - Hash. Optional parameters.
672
+ #
673
+ # ==== Options
674
+ #
675
+ # Accepted key/value pairs in options parameter are:
676
+ # * +:content_md5+ - String. Content MD5 for the request contents (not the blob contents!)
677
+ # * +:blob_content_type+ - String. Content type for the blob. Will be saved with blob.
678
+ # * +:blob_content_encoding+ - String. Content encoding for the blob. Will be saved with blob.
679
+ # * +:blob_content_language+ - String. Content language for the blob. Will be saved with blob.
680
+ # * +:blob_content_md5+ - String. Content MD5 for the blob. Will be saved with blob.
681
+ # * +:blob_cache_control+ - String. Cache control for the blob. Will be saved with blob.
682
+ # * +:metadata+ - Hash. Custom metadata values to store with the blob.
683
+ # * +:timeout+ - Integer. A timeout in seconds.
684
+ #
685
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179467.aspx
686
+ #
687
+ # Returns nil on success
688
+ def commit_blob_blocks(container, blob, block_list, options={})
689
+ query = { "comp" => "blocklist" }
690
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
691
+
692
+ uri = blob_uri(container, blob, query)
693
+
694
+ headers = { }
695
+ unless options.empty?
696
+ headers["Content-MD5"] = options[:content_md5] if options[:content_md5]
697
+ headers["x-ms-blob-content-type"] = options[:blob_content_type] if options[:blob_content_type]
698
+ headers["x-ms-blob-content-encoding"] = options[:blob_content_encoding] if options[:blob_content_encoding]
699
+ headers["x-ms-blob-content-language"] = options[:blob_content_language] if options[:blob_content_language]
700
+ headers["x-ms-blob-content-md5"] = options[:blob_content_md5] if options[:blob_content_md5]
701
+ headers["x-ms-blob-cache-control"] = options[:blob_cache_control] if options[:blob_cache_control]
702
+
703
+ add_metadata_to_headers(options[:metadata], headers) if options[:metadata]
704
+ end
705
+
706
+ body = Serialization.block_list_to_xml(block_list)
707
+ call(:put, uri, body, headers)
708
+ nil
709
+ end
710
+
711
+ # Public: Retrieves the list of blocks that have been uploaded as part of a block blob.
712
+ #
713
+ # There are two block lists maintained for a blob:
714
+ # 1) Committed Block List: The list of blocks that have been successfully
715
+ # committed to a given blob with commitBlobBlocks.
716
+ # 2) Uncommitted Block List: The list of blocks that have been uploaded for a
717
+ # blob using Put Block (REST API), but that have not yet been committed.
718
+ # These blocks are stored in Windows Azure in association with a blob, but do
719
+ # not yet form part of the blob.
720
+ #
721
+ # ==== Attributes
722
+ #
723
+ # * +container+ - String. The container name.
724
+ # * +blob+ - String. The blob name.
725
+ # * +options+ - Hash. Optional parameters.
726
+ #
727
+ # ==== Options
728
+ #
729
+ # Accepted key/value pairs in options parameter are:
730
+ # * +:blocklist_type+ - Symbol. One of :all, :committed, :uncommitted. Defaults to :all (optional)
731
+ # * +:snapshot+ - String. An opaque DateTime value that specifies the blob snapshot to
732
+ # retrieve information from. (optional)
733
+ # * +:timeout+ - Integer. A timeout in seconds.
734
+ #
735
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179400.aspx
736
+ #
737
+ # Returns a list of Azure::Entity::Blob::Block instances
738
+ def list_blob_blocks(container, blob, options={})
739
+
740
+ options[:blocklist_type] = options[:blocklist_type] || :all
741
+
742
+ query = { "comp" => "blocklist" }
743
+ query["snapshot"] = options[:snapshot] if options[:snapshot]
744
+ query["blocklisttype"] = options[:blocklist_type].to_s if options[:blocklist_type]
745
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
746
+
747
+ uri = blob_uri(container, blob, query)
748
+
749
+ response = call(:get, uri)
750
+
751
+ Serialization.block_list_from_xml(response.body)
752
+ end
753
+
754
+ # Public: Returns all properties and metadata on the blob.
755
+ #
756
+ # ==== Attributes
757
+ #
758
+ # * +container+ - String. The container name.
759
+ # * +blob+ - String. The blob name.
760
+ # * +options+ - Hash. Optional parameters.
761
+ #
762
+ # ==== Options
763
+ #
764
+ # Accepted key/value pairs in options parameter are:
765
+ # * +:snapshot+ - String. An opaque DateTime value that specifies the blob snapshot to
766
+ # retrieve information from.
767
+ # * +:timeout+ - Integer. A timeout in seconds.
768
+ #
769
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179394.aspx
770
+ #
771
+ # Returns a Blob
772
+ def get_blob_properties(container, blob, options={})
773
+ query = { }
774
+ query["snapshot"] = options[:snapshot] if options[:snapshot]
775
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
776
+
777
+ uri = blob_uri(container, blob, query)
778
+
779
+ response = call(:head, uri)
780
+
781
+ result = Serialization.blob_from_headers(response.headers)
782
+
783
+ result.name = blob
784
+ result.snapshot = options[:snapshot]
785
+
786
+ result
787
+ end
788
+
789
+ # Public: Returns metadata on the blob.
790
+ #
791
+ # ==== Attributes
792
+ #
793
+ # * +container+ - String. The container name.
794
+ # * +blob+ - String. The blob name.
795
+ # * +options+ - Hash. Optional parameters.
796
+ #
797
+ # ==== Options
798
+ #
799
+ # Accepted key/value pairs in options parameter are:
800
+ # * +:snapshot+ - String. An opaque DateTime value that specifies the blob snapshot to
801
+ # retrieve information from.
802
+ # * +:timeout+ - Integer. A timeout in seconds.
803
+ #
804
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179350.aspx
805
+ #
806
+ # Returns a Blob
807
+ def get_blob_metadata(container, blob, options={})
808
+ query = {"comp"=>"metadata"}
809
+ query["snapshot"] = options[:snapshot] if options[:snapshot]
810
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
811
+
812
+ uri = blob_uri(container, blob, query)
813
+
814
+ response = call(:get, uri)
815
+
816
+ result = Serialization.blob_from_headers(response.headers)
817
+
818
+ result.name = blob
819
+ result.snapshot = options[:snapshot]
820
+
821
+ result
822
+ end
823
+
824
+ # Public: Returns a list of active page ranges for a page blob. Active page ranges are
825
+ # those that have been populated with data.
826
+ #
827
+ # ==== Attributes
828
+ #
829
+ # * +container+ - String. The container name.
830
+ # * +blob+ - String. The blob name.
831
+ # * +options+ - Hash. Optional parameters.
832
+ #
833
+ # ==== Options
834
+ #
835
+ # Accepted key/value pairs in options parameter are:
836
+ # * +:start_range+ - Integer. Position of first byte of first page. (optional)
837
+ # * +:end_range+ - Integer. Position of last byte of of last page. (optional)
838
+ # * +:snapshot+ - String. An opaque DateTime value that specifies the blob snapshot to
839
+ # retrieve information from. (optional)
840
+ # * +:timeout+ - Integer. A timeout in seconds.
841
+ #
842
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691973.aspx
843
+ #
844
+ # Returns a list of page ranges in the format [ [start, end], [start, end], ... ]
845
+ #
846
+ # eg. [ [0, 511], [512, 1024], ... ]
847
+ #
848
+ def list_page_blob_ranges(container, blob, options={})
849
+ query = {"comp"=>"pagelist"}
850
+ query.update({"snapshot" => options[:snapshot]}) if options[:snapshot]
851
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
852
+
853
+ uri = blob_uri(container, blob, query)
854
+
855
+ options[:start_range] = 0 if options[:end_range] and not options[:start_range]
856
+
857
+ headers = { }
858
+ headers = { "x-ms-range" => "bytes=#{options[:start_range]}-#{options[:end_range]}" } if options[:start_range]
859
+
860
+ response = call(:get, uri, nil, headers)
861
+
862
+ pagelist = Serialization.page_list_from_xml(response.body)
863
+ pagelist
864
+ end
865
+
866
+ # Public: Sets system properties defined for a blob.
867
+ #
868
+ # ==== Attributes
869
+ #
870
+ # * +container+ - String. The container name.
871
+ # * +blob+ - String. The blob name.
872
+ # * +options+ - Hash. Optional parameters.
873
+ #
874
+ # ==== Options
875
+ #
876
+ # Accepted key/value pairs in options parameter are:
877
+ # * +:content_type+ - String. Content type for the blob. Will be saved with blob.
878
+ # * +:content_encoding+ - String. Content encoding for the blob. Will be saved with blob.
879
+ # * +:content_language+ - String. Content language for the blob. Will be saved with blob.
880
+ # * +:content_md5+ - String. Content MD5 for the blob. Will be saved with blob.
881
+ # * +:cache_control+ - String. Cache control for the blob. Will be saved with blob.
882
+ # * +:content_length+ - Integer. Resizes a page blob to the specified size. If the specified
883
+ # value is less than the current size of the blob, then all pages above
884
+ # the specified value are cleared. This property cannot be used to change
885
+ # the size of a block blob. Setting this property for a block blob returns
886
+ # status code 400 (Bad Request).
887
+ # * +:sequence_number_action+ - Symbol. This property indicates how the service should modify the sequence
888
+ # number for the blob. Required if :sequence_number is used. This property
889
+ # applies to page blobs only.
890
+ #
891
+ # Specify one of the following options for this property:
892
+ #
893
+ # * +:max+ - Sets the sequence number to be the higher of the value included with
894
+ # the request and the value currently stored for the blob.
895
+ # * +:update+ - Sets the sequence number to the value included with the request.
896
+ # * +:increment+ - Increments the value of the sequence number by 1. If specifying this
897
+ # option, do not include the sequence_number option; doing so will return
898
+ # status code 400 (Bad Request).
899
+ # * +:sequence_number+ - Integer. This property sets the blob's sequence number. The sequence number is a
900
+ # user-controlled property that you can use to track requests and manage concurrency
901
+ # issues. Required if the :sequence_number_action option is set to :max or :update.
902
+ # This property applies to page blobs only.
903
+ #
904
+ # Use this together with the :sequence_number_action to update the blob's sequence
905
+ # number, either to the specified value or to the higher of the values specified with
906
+ # the request or currently stored with the blob.
907
+ #
908
+ # This header should not be specified if :sequence_number_action is set to :increment;
909
+ # in this case the service automatically increments the sequence number by one.
910
+ #
911
+ # To set the sequence number to a value of your choosing, this property must be specified
912
+ # together with :sequence_number_action
913
+ # * +:timeout+ - Integer. A timeout in seconds.
914
+ #
915
+ # Remarks:
916
+ #
917
+ # The semantics for updating a blob's properties are as follows:
918
+ #
919
+ # * A page blob's sequence number is updated only if the request meets either of the following conditions:
920
+ #
921
+ # * The :sequence_number_action property is set to :max or :update, and a value for :sequence_number is also set.
922
+ # * The :sequence_number_action property is set to :increment, indicating that the service should increment
923
+ # the sequence number by one.
924
+ #
925
+ # * The size of the page blob is modified only if a value for :content_length is specified.
926
+ #
927
+ # * If :sequence_number and/or :content_length are the only properties specified, then the other properties of the blob
928
+ # will NOT be modified.
929
+ #
930
+ # * If any one or more of the following properties are set, then all of these properties are set together. If a value is
931
+ # not provided for a given property when at least one of the properties listed below is set, then that property will be
932
+ # cleared for the blob.
933
+ #
934
+ # * :cache_control
935
+ # * :content_type
936
+ # * :content_md5
937
+ # * :content_encoding
938
+ # * :content_language
939
+ #
940
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691966.aspx
941
+ #
942
+ # Returns nil on success.
943
+ def set_blob_properties(container, blob, options={})
944
+ query = { "comp" => "properties" }
945
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
946
+ uri = blob_uri(container, blob, query)
947
+
948
+ headers = { }
949
+
950
+ unless options.empty?
951
+ headers["x-ms-blob-content-type"] = options[:blob_content_type] if options[:blob_content_type]
952
+ headers["x-ms-blob-content-encoding"] = options[:blob_content_encoding] if options[:blob_content_encoding]
953
+ headers["x-ms-blob-content-language"] = options[:blob_content_language] if options[:blob_content_language]
954
+ headers["x-ms-blob-content-md5"] = options[:blob_content_md5] if options[:blob_content_md5]
955
+ headers["x-ms-blob-cache-control"] = options[:blob_cache_control] if options[:blob_cache_control]
956
+ headers["x-ms-blob-content-length"] = options[:blob_content_length].to_s if options[:blob_content_length]
957
+ headers["x-ms-blob-sequence-number-action"] = options[:sequence_number_action].to_s if options[:sequence_number_action]
958
+ headers["x-ms-blob-sequence-number"] = options[:sequence_number].to_s if options[:sequence_number]
959
+ end
960
+
961
+ call(:put, uri, nil, headers)
962
+ nil
963
+ end
964
+
965
+ # Public: Sets metadata headers on the blob.
966
+ #
967
+ # ==== Attributes
968
+ #
969
+ # * +container+ - String. The container name.
970
+ # * +blob+ - String. The blob name.
971
+ # * +metadata+ - Hash. The custom metadata.
972
+ # * +options+ - Hash. Optional parameters.
973
+ #
974
+ # ==== Options
975
+ #
976
+ # Accepted key/value pairs in options parameter are:
977
+ # * +:timeout+ - Integer. A timeout in seconds.
978
+ #
979
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179414.aspx
980
+ #
981
+ # Returns nil on success.
982
+ def set_blob_metadata(container, blob, metadata, options={})
983
+ query = { "comp" => "metadata" }
984
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
985
+ uri = blob_uri(container, blob, query)
986
+
987
+ headers = { }
988
+
989
+ add_metadata_to_headers(metadata, headers) if metadata
990
+
991
+ call(:put, uri, nil, headers)
992
+ nil
993
+ end
994
+
995
+ # Public: Reads or downloads a blob from the system, including its metadata and properties.
996
+ #
997
+ # ==== Attributes
998
+ #
999
+ # * +container+ - String. The container name.
1000
+ # * +blob+ - String. The blob name.
1001
+ # * +options+ - Hash. Optional parameters.
1002
+ #
1003
+ # ==== Options
1004
+ #
1005
+ # Accepted key/value pairs in options parameter are:
1006
+ # * +:start_range+ - Integer. Position of first byte of first page. (optional)
1007
+ # * +:end_range+ - Integer. Position of last byte of of last page. (optional)
1008
+ # * +:snapshot+ - String. An opaque DateTime value that specifies the blob snapshot to
1009
+ # retrieve information from. (optional)
1010
+ # * +:get_content_md5+ - Boolean. Return the MD5 hash for the range. This option only valid if
1011
+ # start_range and end_range are specified. (optional)
1012
+ # * +:timeout+ - Integer. A timeout in seconds.
1013
+ #
1014
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179440.aspx
1015
+ #
1016
+ # Returns a blob and the blob body
1017
+ def get_blob(container, blob, options={})
1018
+ query = { }
1019
+ query["snapshot"] = options[:snapshot] if options[:snapshot]
1020
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1021
+ uri = blob_uri(container, blob, query)
1022
+
1023
+ headers = { }
1024
+ options[:start_range] = 0 if options[:end_range] and not options[:start_range]
1025
+ if options[:start_range]
1026
+ headers["x-ms-range"] = "bytes=#{options[:start_range]}-#{options[:end_range]}"
1027
+ headers["x-ms-range-get-content-md5"] = true if options[:get_content_md5]
1028
+ end
1029
+
1030
+ response = call(:get, uri, nil, headers)
1031
+ result = Serialization.blob_from_headers(response.headers)
1032
+ result.name = blob if not result.name
1033
+ return result, response.body
1034
+ end
1035
+
1036
+ # Public: Deletes a blob or blob snapshot.
1037
+ #
1038
+ # ==== Attributes
1039
+ #
1040
+ # * +container+ - String. The container name.
1041
+ # * +blob+ - String. The blob name.
1042
+ # * +options+ - Hash. Optional parameters.
1043
+ #
1044
+ # ==== Options
1045
+ #
1046
+ # Accepted key/value pairs in options parameter are:
1047
+ # * +:snapshot+ - String. An opaque DateTime value that specifies the blob snapshot to
1048
+ # retrieve information from. (optional)
1049
+ # * +:delete_snapshots+ - Symbol. Used to specify the scope of the delete operation for snapshots.
1050
+ # This parameter is ignored if a blob does not have snapshots, or if a
1051
+ # snapshot is specified in the snapshot parameter. (optional)
1052
+ #
1053
+ # Possible values include:
1054
+ # * +:only+ - Deletes only the snapshots for the blob, but leaves the blob
1055
+ # * +:include+ - Deletes the blob and all of the snapshots for the blob
1056
+ # * +:timeout+ - Integer. A timeout in seconds.
1057
+ #
1058
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179440.aspx
1059
+ #
1060
+ # Returns nil on success
1061
+ def delete_blob(container, blob, options={})
1062
+ query = { }
1063
+ query["snapshot"] = options[:snapshot] if options[:snapshot]
1064
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1065
+
1066
+ uri = blob_uri(container, blob, query)
1067
+
1068
+ options[:delete_snapshots] = :include if !options[:delete_snapshots]
1069
+
1070
+ headers = { }
1071
+ headers["x-ms-delete-snapshots"] = options[:delete_snapshots].to_s if options[:delete_snapshots] && options[:snapshot] == nil
1072
+
1073
+ call(:delete, uri, nil, headers)
1074
+ nil
1075
+ end
1076
+
1077
+ # Public: Creates a snapshot of a blob.
1078
+ #
1079
+ # ==== Attributes
1080
+ #
1081
+ # * +container+ - String. The container name.
1082
+ # * +blob+ - String. The blob name.
1083
+ # * +options+ - Hash. Optional parameters.
1084
+ #
1085
+ # ==== Options
1086
+ #
1087
+ # Accepted key/value pairs in options parameter are:
1088
+ # * +:metadata+ - Hash. Custom metadata values to store with the blob snapshot.
1089
+ # * +:if_modified_since+ - A DateTime value. Specify this option to write the page only if the blob has been
1090
+ # modified since the specified date/time. If the blob has not been modified, the
1091
+ # Blob service returns status code 412 (Precondition Failed).
1092
+ # * +:if_unmodified_since+ - A DateTime value. Specify this option to write the page only if the blob has not
1093
+ # been modified since the specified date/time. If the blob has been modified, the
1094
+ # Blob service returns status code 412 (Precondition Failed).
1095
+ # * +:if_match+ - An ETag value. Specify an ETag value to write the page only if the blob's ETag
1096
+ # value matches the value specified. If the values do not match, the Blob service
1097
+ # returns status code 412 (Precondition Failed).
1098
+ # * +:if_none_match+ - An ETag value. Specify an ETag value to write the page only if the blob's ETag
1099
+ # value does not match the value specified. If the values are identical, the Blob
1100
+ # service returns status code 412 (Precondition Failed).
1101
+ # * +:timeout+ - Integer. A timeout in seconds.
1102
+ #
1103
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691971.aspx
1104
+ #
1105
+ # Returns the snapshot DateTime value
1106
+ def create_blob_snapshot(container, blob, options={})
1107
+ query = { "comp" => "snapshot" }
1108
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1109
+
1110
+ uri = blob_uri(container, blob, query)
1111
+
1112
+ headers = { }
1113
+ unless options.empty?
1114
+ add_metadata_to_headers(options[:metadata], headers) if options[:metadata]
1115
+
1116
+ headers["If-Modified-Since"] = options[:if_modified_since] if options[:if_modified_since]
1117
+ headers["If-Unmodified-Since"] = options[:if_unmodified_since] if options[:if_unmodified_since]
1118
+ headers["If-Match"] = options[:if_match] if options[:if_match]
1119
+ headers["If-None-Match"] = options[:if_none_match] if options[:if_none_match]
1120
+ end
1121
+
1122
+ response = call(:put, uri, nil, headers)
1123
+
1124
+ response.headers["x-ms-snapshot"]
1125
+ end
1126
+
1127
+ # Public: Copies a source blob to a destination blob within the same storage account.
1128
+ #
1129
+ # ==== Attributes
1130
+ #
1131
+ # * +source_container+ - String. The destination container name to copy to.
1132
+ # * +source_blob+ - String. The destination blob name to copy to.
1133
+ # * +destination_container+ - String. The source container name to copy from.
1134
+ # * +destination_blob+ - String. The source blob name to copy from.
1135
+ # * +options+ - Hash. Optional parameters.
1136
+ #
1137
+ # ==== Options
1138
+ #
1139
+ # Accepted key/value pairs in options parameter are:
1140
+ # * +:source_snapshot+ - String. A snapshot id for the source blob
1141
+ # * +:metadata+ - Hash. Custom metadata values to store with the copy. If this parameter is not
1142
+ # specified, the operation will copy the source blob metadata to the destination
1143
+ # blob. If this parameter is specified, the destination blob is created with the
1144
+ # specified metadata, and metadata is not copied from the source blob.
1145
+ # * +:source_if_modified_since+ - A DateTime value. Specify this option to write the page only if the source blob
1146
+ # has been modified since the specified date/time. If the blob has not been
1147
+ # modified, the Blob service returns status code 412 (Precondition Failed).
1148
+ # * +:source_if_unmodified_since+ - A DateTime value. Specify this option to write the page only if the source blob
1149
+ # has not been modified since the specified date/time. If the blob has been
1150
+ # modified, the Blob service returns status code 412 (Precondition Failed).
1151
+ # * +:source_if_match+ - An ETag value. Specify an ETag value to write the page only if the source blob's
1152
+ # ETag value matches the value specified. If the values do not match, the Blob
1153
+ # service returns status code 412 (Precondition Failed).
1154
+ # * +:source_if_none_match+ - An ETag value. Specify an ETag value to write the page only if the source blob's
1155
+ # ETag value does not match the value specified. If the values are identical, the
1156
+ # Blob service returns status code 412 (Precondition Failed).
1157
+ # * +:dest_if_modified_since+ - A DateTime value. Specify this option to write the page only if the destination
1158
+ # blob has been modified since the specified date/time. If the blob has not been
1159
+ # modified, the Blob service returns status code 412 (Precondition Failed).
1160
+ # * +:dest_if_unmodified_since+ - A DateTime value. Specify this option to write the page only if the destination
1161
+ # blob has not been modified since the specified date/time. If the blob has been
1162
+ # modified, the Blob service returns status code 412 (Precondition Failed).
1163
+ # * +:dest_if_match+ - An ETag value. Specify an ETag value to write the page only if the destination
1164
+ # blob's ETag value matches the value specified. If the values do not match, the
1165
+ # Blob service returns status code 412 (Precondition Failed).
1166
+ # * +:dest_if_none_match+ - An ETag value. Specify an ETag value to write the page only if the destination
1167
+ # blob's ETag value does not match the value specified. If the values are
1168
+ # identical, the Blob service returns status code 412 (Precondition Failed).
1169
+ # * +:timeout+ - Integer. A timeout in seconds.
1170
+ #
1171
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd894037.aspx
1172
+ #
1173
+ # Returns a tuple of (copy_id, copy_status).
1174
+ #
1175
+ # * +copy_id+ - String identifier for this copy operation. Use with get_blob or get_blob_properties to check
1176
+ # the status of this copy operation, or pass to abort_copy_blob to abort a pending copy.
1177
+ # * +copy_status+ - String. The state of the copy operation, with these values:
1178
+ # "success" - The copy completed successfully.
1179
+ # "pending" - The copy is in progress.
1180
+ #
1181
+ def copy_blob(destination_container, destination_blob, source_container, source_blob, options={})
1182
+ query = { }
1183
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1184
+
1185
+ uri = blob_uri(destination_container, destination_blob, query)
1186
+ headers = { }
1187
+ headers["x-ms-copy-source"] = blob_uri(source_container, source_blob, options[:source_snapshot] ? { "snapshot" => options[:source_snapshot] } : {}).to_s
1188
+
1189
+ unless options.empty?
1190
+ headers["If-Modified-Since"] = options[:dest_if_modified_since] if options[:dest_if_modified_since]
1191
+ headers["If-Unmodified-Since"] = options[:dest_if_unmodified_since] if options[:dest_if_unmodified_since]
1192
+ headers["If-Match"] = options[:dest_if_match] if options[:dest_if_match]
1193
+ headers["If-None-Match"] = options[:dest_if_none_match] if options[:dest_if_none_match]
1194
+ headers["x-ms-source-if-modified-since"] = options[:source_if_modified_since] if options[:source_if_modified_since]
1195
+ headers["x-ms-source-if-unmodified-since"] = options[:source_if_unmodified_since] if options[:source_if_unmodified_since]
1196
+ headers["x-ms-source-if-match"] = options[:source_if_match] if options[:source_if_match]
1197
+ headers["x-ms-source-if-none-match"] = options[:source_if_none_match] if options[:source_if_none_match]
1198
+
1199
+ add_metadata_to_headers(options[:metadata], headers) if options[:metadata]
1200
+ end
1201
+
1202
+ response = call(:put, uri, nil, headers)
1203
+ return response.headers["x-ms-copy-id"], response.headers["x-ms-copy-status"]
1204
+ end
1205
+
1206
+ # Public: Establishes an exclusive one-minute write lock on a blob. To write to a locked
1207
+ # blob, a client must provide a lease ID.
1208
+ #
1209
+ # ==== Attributes
1210
+ #
1211
+ # * +container+ - String. The container name.
1212
+ # * +blob+ - String. The blob name.
1213
+ # * +options+ - Hash. Optional parameters.
1214
+ #
1215
+ # ==== Options
1216
+ #
1217
+ # Accepted key/value pairs in options parameter are:
1218
+ # * +:duration+ - Integer. Default -1. Specifies the duration of the lease, in seconds, or negative one (-1)
1219
+ # for a lease that never expires. A non-infinite lease can be between 15 and 60 seconds. (optional)
1220
+ # * +:proposed_lease_id+ - String. Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request)
1221
+ # if the proposed lease ID is not in the correct format. (optional)
1222
+ # * +:timeout+ - Integer. A timeout in seconds.
1223
+ #
1224
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691972.aspx
1225
+ #
1226
+ # Returns a String of the new unique lease id. While the lease is active, you must include the lease ID with any request
1227
+ # to write to the blob, or to renew, change, or release the lease. A successful renew operation also returns the lease id
1228
+ # for the active lease.
1229
+ #
1230
+ def acquire_lease(container, blob, options={})
1231
+ query = { "comp" => "lease" }
1232
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1233
+
1234
+ uri = blob_uri(container, blob, query)
1235
+
1236
+ duration = -1
1237
+ duration = options[:duration] if options[:duration]
1238
+
1239
+ headers = { }
1240
+ headers["x-ms-lease-action"] = "acquire"
1241
+ headers["x-ms-lease-duration"] = duration.to_s if duration
1242
+ headers["x-ms-proposed-lease-id"] = options[:proposed_lease_id] if options[:proposed_lease_id]
1243
+
1244
+ response = call(:put, uri, nil, headers)
1245
+ response.headers["x-ms-lease-id"]
1246
+ end
1247
+
1248
+ # Public: Renews the lease. The lease can be renewed if the lease ID specified on the request matches that
1249
+ # associated with the blob. Note that the lease may be renewed even if it has expired as long as the blob
1250
+ # has not been modified or leased again since the expiration of that lease. When you renew a lease, the
1251
+ # lease duration clock resets.
1252
+ #
1253
+ # ==== Attributes
1254
+ #
1255
+ # * +container+ - String. The container name.
1256
+ # * +blob+ - String. The blob name.
1257
+ # * +lease+ - String. The lease id
1258
+ # * +options+ - Hash. Optional parameters.
1259
+ #
1260
+ # ==== Options
1261
+ #
1262
+ # Accepted key/value pairs in options parameter are:
1263
+ # * +:timeout+ - Integer. A timeout in seconds.
1264
+ #
1265
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691972.aspx
1266
+ #
1267
+ # Returns the renewed lease id
1268
+ def renew_lease(container, blob, lease, options={})
1269
+ query = { "comp" => "lease" }
1270
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1271
+
1272
+ uri = blob_uri(container, blob, query)
1273
+
1274
+ headers = { }
1275
+ headers["x-ms-lease-action"] = "renew"
1276
+ headers["x-ms-lease-id"] = lease
1277
+
1278
+ response = call(:put, uri, nil, headers)
1279
+ response.headers["x-ms-lease-id"]
1280
+ end
1281
+
1282
+ # Public: Releases the lease. The lease may be released if the lease ID specified on the request matches that
1283
+ # associated with the blob. Releasing the lease allows another client to immediately acquire the lease for
1284
+ # the blob as soon as the release is complete.
1285
+ #
1286
+ # ==== Attributes
1287
+ #
1288
+ # * +container+ - String. The container name.
1289
+ # * +blob+ - String. The blob name.
1290
+ # * +lease+ - String. The lease id.
1291
+ # * +options+ - Hash. Optional parameters.
1292
+ #
1293
+ # ==== Options
1294
+ #
1295
+ # Accepted key/value pairs in options parameter are:
1296
+ # * +:timeout+ - Integer. A timeout in seconds.
1297
+ #
1298
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691972.aspx
1299
+ #
1300
+ # Returns nil on success
1301
+ def release_lease(container, blob, lease, options={})
1302
+ query = { "comp" => "lease" }
1303
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1304
+
1305
+ uri = blob_uri(container, blob, query)
1306
+
1307
+ headers = { }
1308
+ headers["x-ms-lease-action"] = "release"
1309
+ headers["x-ms-lease-id"] = lease
1310
+
1311
+ call(:put, uri, nil, headers)
1312
+ nil
1313
+ end
1314
+
1315
+ # Public: Breaks the lease, if the blob has an active lease. Once a lease is broken, it cannot be renewed. Any
1316
+ # authorized request can break the lease; the request is not required to specify a matching lease ID. When a
1317
+ # lease is broken, the lease break period is allowed to elapse, during which time no lease operation except
1318
+ # break and release can be performed on the blob. When a lease is successfully broken, the response indicates
1319
+ # the interval in seconds until a new lease can be acquired.
1320
+ #
1321
+ # A lease that has been broken can also be released, in which case another client may immediately acquire the
1322
+ # lease on the blob.
1323
+ #
1324
+ # ==== Attributes
1325
+ #
1326
+ # * +container+ - String. The container name.
1327
+ # * +blob+ - String. The blob name.
1328
+ # * +options+ - Hash. Optional parameters.
1329
+ #
1330
+ # ==== Options
1331
+ #
1332
+ # Accepted key/value pairs in options parameter are:
1333
+ # * +:break_period+ - Integer. The proposed duration of seconds that the lease should continue before it is
1334
+ # broken, between 0 and 60 seconds. This break period is only used if it is shorter than
1335
+ # the time remaining on the lease. If longer, the time remaining on the lease is used. A
1336
+ # new lease will not be available before the break period has expired, but the lease may
1337
+ # be held for longer than the break period.
1338
+ #
1339
+ # If this option is not used, a fixed-duration lease breaks after the remaining lease
1340
+ # period elapses, and an infinite lease breaks immediately.
1341
+ # * +:timeout+ - Integer. A timeout in seconds.
1342
+ #
1343
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/ee691972.aspx
1344
+ #
1345
+ # Returns an Integer of the remaining lease time. This value is the approximate time remaining in the lease
1346
+ # period, in seconds. This header is returned only for a successful request to break the lease. If the break
1347
+ # is immediate, 0 is returned.
1348
+ def break_lease(container, blob, options={})
1349
+ query = { "comp" => "lease" }
1350
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
1351
+
1352
+ uri = blob_uri(container, blob, query)
1353
+
1354
+ headers = { }
1355
+ headers["x-ms-lease-action"] = "break"
1356
+ headers["x-ms-lease-break-period"] = options[:break_period].to_s if options[:break_period]
1357
+
1358
+ response = call(:put, uri, nil, headers)
1359
+ response.headers["x-ms-lease-time"].to_i
1360
+ end
1361
+
1362
+ # Protected: Generate the URI for the collection of containers.
1363
+ #
1364
+ # ==== Attributes
1365
+ #
1366
+ # * +query+ - A Hash of key => value query parameters.
1367
+ # * +host+ - The host of the API.
1368
+ #
1369
+ # Returns a URI.
1370
+ protected
1371
+ def containers_uri(query={})
1372
+ query = { "comp" => "list" }.merge(query)
1373
+ generate_uri("/", query)
1374
+ end
1375
+
1376
+ # Protected: Generate the URI for a specific container.
1377
+ #
1378
+ # ==== Attributes
1379
+ #
1380
+ # * +name+ - The container name. If this is a URI, we just return this.
1381
+ # * +query+ - A Hash of key => value query parameters.
1382
+ # * +host+ - The host of the API.
1383
+ #
1384
+ # Returns a URI.
1385
+ protected
1386
+ def container_uri(name, query={})
1387
+ return name if name.kind_of? ::URI
1388
+ query = { "restype" => "container" }.merge(query)
1389
+ generate_uri(name, query)
1390
+ end
1391
+
1392
+ # Protected: Generate the URI for a specific Blob.
1393
+ #
1394
+ # ==== Attributes
1395
+ #
1396
+ # * +container_name+ - String representing the name of the container.
1397
+ # * +blob_name+ - String representing the name of the blob.
1398
+ # * +query+ - A Hash of key => value query parameters.
1399
+ # * +host+ - The host of the API.
1400
+ #
1401
+ # Returns a URI.
1402
+ protected
1403
+ def blob_uri(container_name, blob_name, query={})
1404
+ if container_name.nil? || container_name.empty?
1405
+ path = blob_name
1406
+ else
1407
+ path = File.join(container_name, blob_name)
1408
+ end
1409
+
1410
+ path = CGI.escape(path.encode('UTF-8'))
1411
+
1412
+ # Unencode the forward slashes to match what the server expects.
1413
+ path = path.gsub(/%2F/, '/')
1414
+ # Unencode the backward slashes to match what the server expects.
1415
+ path = path.gsub(/%5C/, '/')
1416
+ # Re-encode the spaces (encoded as space) to the % encoding.
1417
+ path = path.gsub(/\+/, '%20')
1418
+
1419
+ generate_uri(path, query)
1420
+ end
1421
+ end
1422
+ end
1423
+ end