azure 0.5.0 → 0.6.0

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