azure-multistorage 0.6.4

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