stuartpreston-azure-sdk-for-ruby 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -11
  3. data/.travis.yml +10 -10
  4. data/ChangeLog.txt +70 -68
  5. data/Gemfile +15 -15
  6. data/README.md +618 -618
  7. data/Rakefile +133 -133
  8. data/azure.gemspec +44 -44
  9. data/lib/azure.rb +52 -52
  10. data/lib/azure/base_management/affinity_group.rb +32 -32
  11. data/lib/azure/base_management/base_management_service.rb +304 -304
  12. data/lib/azure/base_management/location.rb +27 -27
  13. data/lib/azure/base_management/management_http_request.rb +171 -171
  14. data/lib/azure/base_management/serialization.rb +129 -129
  15. data/lib/azure/base_management/sql_management_http_request.rb +45 -45
  16. data/lib/azure/blob/blob.rb +31 -31
  17. data/lib/azure/blob/blob_service.rb +1423 -1423
  18. data/lib/azure/blob/block.rb +30 -30
  19. data/lib/azure/blob/container.rb +31 -31
  20. data/lib/azure/blob/serialization.rb +284 -284
  21. data/lib/azure/cloud_service_management/cloud_service.rb +38 -38
  22. data/lib/azure/cloud_service_management/cloud_service_management_service.rb +140 -140
  23. data/lib/azure/cloud_service_management/serialization.rb +117 -117
  24. data/lib/azure/core.rb +39 -39
  25. data/lib/azure/core/auth/authorizer.rb +36 -36
  26. data/lib/azure/core/auth/shared_key.rb +110 -110
  27. data/lib/azure/core/auth/shared_key_lite.rb +48 -48
  28. data/lib/azure/core/auth/signer.rb +48 -48
  29. data/lib/azure/core/configuration.rb +211 -211
  30. data/lib/azure/core/error.rb +22 -22
  31. data/lib/azure/core/filtered_service.rb +43 -43
  32. data/lib/azure/core/http/debug_filter.rb +35 -35
  33. data/lib/azure/core/http/http_error.rb +88 -88
  34. data/lib/azure/core/http/http_filter.rb +52 -52
  35. data/lib/azure/core/http/http_request.rb +157 -157
  36. data/lib/azure/core/http/http_response.rb +140 -140
  37. data/lib/azure/core/http/retry_policy.rb +73 -73
  38. data/lib/azure/core/http/signer_filter.rb +33 -33
  39. data/lib/azure/core/service.rb +62 -62
  40. data/lib/azure/core/signed_service.rb +42 -42
  41. data/lib/azure/core/utility.rb +190 -190
  42. data/lib/azure/queue/message.rb +29 -29
  43. data/lib/azure/queue/queue.rb +28 -28
  44. data/lib/azure/queue/queue_service.rb +567 -567
  45. data/lib/azure/queue/serialization.rb +106 -106
  46. data/lib/azure/service/access_policy.rb +25 -25
  47. data/lib/azure/service/cors.rb +11 -11
  48. data/lib/azure/service/cors_rule.rb +15 -15
  49. data/lib/azure/service/enumeration_results.rb +20 -20
  50. data/lib/azure/service/logging.rb +31 -31
  51. data/lib/azure/service/metrics.rb +30 -30
  52. data/lib/azure/service/retention_policy.rb +24 -24
  53. data/lib/azure/service/serialization.rb +297 -297
  54. data/lib/azure/service/signed_identifier.rb +29 -29
  55. data/lib/azure/service/storage_service.rb +82 -82
  56. data/lib/azure/service/storage_service_properties.rb +37 -37
  57. data/lib/azure/service_bus/action.rb +21 -21
  58. data/lib/azure/service_bus/auth/wrap_service.rb +88 -88
  59. data/lib/azure/service_bus/auth/wrap_signer.rb +68 -68
  60. data/lib/azure/service_bus/brokered_message.rb +123 -123
  61. data/lib/azure/service_bus/brokered_message_serializer.rb +159 -159
  62. data/lib/azure/service_bus/correlation_filter.rb +45 -45
  63. data/lib/azure/service_bus/empty_rule_action.rb +29 -29
  64. data/lib/azure/service_bus/false_filter.rb +38 -38
  65. data/lib/azure/service_bus/filter.rb +21 -21
  66. data/lib/azure/service_bus/interval.rb +103 -103
  67. data/lib/azure/service_bus/queue.rb +229 -229
  68. data/lib/azure/service_bus/relay.rb +87 -87
  69. data/lib/azure/service_bus/resource.rb +108 -108
  70. data/lib/azure/service_bus/rule.rb +97 -97
  71. data/lib/azure/service_bus/rule_aspect.rb +34 -34
  72. data/lib/azure/service_bus/serialization.rb +161 -161
  73. data/lib/azure/service_bus/service_bus_service.rb +896 -896
  74. data/lib/azure/service_bus/sql_filter.rb +50 -50
  75. data/lib/azure/service_bus/sql_rule_action.rb +50 -50
  76. data/lib/azure/service_bus/subscription.rb +183 -183
  77. data/lib/azure/service_bus/topic.rb +186 -186
  78. data/lib/azure/service_bus/true_filter.rb +38 -38
  79. data/lib/azure/sql_database_management/serialization.rb +111 -111
  80. data/lib/azure/sql_database_management/sql_database.rb +31 -31
  81. data/lib/azure/sql_database_management/sql_database_management_service.rb +200 -200
  82. data/lib/azure/storage_management/serialization.rb +184 -184
  83. data/lib/azure/storage_management/storage_account.rb +40 -40
  84. data/lib/azure/storage_management/storage_management_service.rb +166 -166
  85. data/lib/azure/table/auth/shared_key.rb +92 -92
  86. data/lib/azure/table/auth/shared_key_lite.rb +44 -44
  87. data/lib/azure/table/batch.rb +329 -329
  88. data/lib/azure/table/batch_response.rb +118 -118
  89. data/lib/azure/table/edmtype.rb +126 -126
  90. data/lib/azure/table/entity.rb +30 -30
  91. data/lib/azure/table/guid.rb +23 -23
  92. data/lib/azure/table/query.rb +111 -111
  93. data/lib/azure/table/serialization.rb +107 -107
  94. data/lib/azure/table/table_service.rb +559 -559
  95. data/lib/azure/version.rb +31 -31
  96. data/lib/azure/virtual_machine_image_management/serialization.rb +66 -66
  97. data/lib/azure/virtual_machine_image_management/virtual_machine_disk.rb +25 -25
  98. data/lib/azure/virtual_machine_image_management/virtual_machine_image.rb +25 -25
  99. data/lib/azure/virtual_machine_image_management/virtual_machine_image_management_service.rb +94 -94
  100. data/lib/azure/virtual_machine_management/serialization.rb +462 -462
  101. data/lib/azure/virtual_machine_management/virtual_machine.rb +45 -45
  102. data/lib/azure/virtual_machine_management/virtual_machine_management_service.rb +588 -588
  103. data/lib/azure/virtual_network_management/serialization.rb +190 -190
  104. data/lib/azure/virtual_network_management/virtual_network.rb +37 -37
  105. data/lib/azure/virtual_network_management/virtual_network_management_service.rb +109 -109
  106. data/test/fixtures/affinity_group.xml +33 -33
  107. data/test/fixtures/all_containers.xml +20 -20
  108. data/test/fixtures/all_tables.xml +22 -22
  109. data/test/fixtures/certificate.pem +21 -21
  110. data/test/fixtures/container_acl.xml +11 -11
  111. data/test/fixtures/create_sql_database_server.xml +1 -1
  112. data/test/fixtures/create_storage_desc_error.xml +5 -5
  113. data/test/fixtures/create_storage_extendedprop_error.xml +8 -8
  114. data/test/fixtures/create_storage_extendedpropname_error.xml +6 -6
  115. data/test/fixtures/create_storage_full_error.xml +6 -6
  116. data/test/fixtures/create_storage_label_error.xml +5 -5
  117. data/test/fixtures/create_storage_location_error.xml +5 -5
  118. data/test/fixtures/create_storage_name_error.xml +6 -6
  119. data/test/fixtures/create_table_response_entry.xml +15 -15
  120. data/test/fixtures/delete_storage_container_error.xml +5 -5
  121. data/test/fixtures/delete_storage_error.xml +5 -5
  122. data/test/fixtures/deployment_error.xml +5 -5
  123. data/test/fixtures/get_storage_account_error.xml +5 -5
  124. data/test/fixtures/get_storage_account_properties.xml +31 -31
  125. data/test/fixtures/get_storage_account_properties_new.xml +31 -31
  126. data/test/fixtures/http_error.xml +5 -5
  127. data/test/fixtures/insert_entity_response_entry.xml +25 -25
  128. data/test/fixtures/list_affinity_groups.xml +22 -22
  129. data/test/fixtures/list_blobs.xml +120 -120
  130. data/test/fixtures/list_block_all_with_none_committed.xml +21 -21
  131. data/test/fixtures/list_blocks_all.xml +22 -22
  132. data/test/fixtures/list_blocks_committed.xml +12 -12
  133. data/test/fixtures/list_cloud_services.xml +38 -38
  134. data/test/fixtures/list_containers.xml +37 -37
  135. data/test/fixtures/list_firewall_management_endpoint.xml +27 -27
  136. data/test/fixtures/list_images.xml +110 -110
  137. data/test/fixtures/list_locations.xml +62 -62
  138. data/test/fixtures/list_page_ranges.xml +10 -10
  139. data/test/fixtures/list_sql_database.xml +36 -36
  140. data/test/fixtures/list_sql_server_firewall.xml +23 -23
  141. data/test/fixtures/list_storage_account_single.xml +24 -24
  142. data/test/fixtures/list_storage_accounts.xml +45 -45
  143. data/test/fixtures/list_virtual_networks.xml +92 -92
  144. data/test/fixtures/logging.xml +11 -11
  145. data/test/fixtures/management_certificate.pem +55 -55
  146. data/test/fixtures/messages.xml +12 -12
  147. data/test/fixtures/metrics.xml +10 -10
  148. data/test/fixtures/privatekey.key +28 -28
  149. data/test/fixtures/query_entities_empty_response.xml +7 -7
  150. data/test/fixtures/query_entities_response.xml +45 -45
  151. data/test/fixtures/queue_service_properties.xml +22 -22
  152. data/test/fixtures/queue_service_properties_original.xml +19 -19
  153. data/test/fixtures/queues.xml +16 -16
  154. data/test/fixtures/retention_policy.xml +5 -5
  155. data/test/fixtures/sb_default_create_queue_response.xml +23 -23
  156. data/test/fixtures/sb_default_create_relay_response.xml +15 -15
  157. data/test/fixtures/sb_default_create_topic_response.xml +18 -18
  158. data/test/fixtures/sb_get_access_token_response.txt +1 -1
  159. data/test/fixtures/sb_queues_runtime_peek_message_response_headers.txt +9 -9
  160. data/test/fixtures/storage_service_properties.xml +54 -54
  161. data/test/fixtures/update_storage_account.xml +16 -16
  162. data/test/fixtures/update_storage_error.xml +4 -4
  163. data/test/fixtures/updated_storage_accounts.xml +52 -52
  164. data/test/fixtures/virtual_machine.xml +113 -113
  165. data/test/fixtures/windows_virtual_machine.xml +106 -106
  166. data/test/integration/affinity_group/Affinity_test.rb +55 -55
  167. data/test/integration/affinity_group/Create_Affinity_test.rb +63 -63
  168. data/test/integration/affinity_group/Delete_Affinity_test.rb +56 -56
  169. data/test/integration/affinity_group/List_Affinity_test.rb +41 -41
  170. data/test/integration/affinity_group/Update_Affinity_test.rb +82 -82
  171. data/test/integration/blob/blob_gb18030_test.rb +199 -199
  172. data/test/integration/blob/blob_metadata_test.rb +75 -75
  173. data/test/integration/blob/blob_pages_test.rb +119 -119
  174. data/test/integration/blob/blob_properties_test.rb +77 -77
  175. data/test/integration/blob/block_blob_test.rb +254 -254
  176. data/test/integration/blob/container/container_acl_test.rb +69 -69
  177. data/test/integration/blob/container/container_metadata_test.rb +50 -50
  178. data/test/integration/blob/container/create_container_test.rb +60 -60
  179. data/test/integration/blob/container/delete_container_test.rb +39 -39
  180. data/test/integration/blob/container/get_container_properties_test.rb +48 -48
  181. data/test/integration/blob/container/list_containers_test.rb +79 -79
  182. data/test/integration/blob/container/root_container_test.rb +53 -53
  183. data/test/integration/blob/copy_blob_test.rb +113 -113
  184. data/test/integration/blob/create_blob_snapshot_test.rb +80 -80
  185. data/test/integration/blob/create_page_blob_test.rb +83 -83
  186. data/test/integration/blob/delete_blob_test.rb +159 -159
  187. data/test/integration/blob/get_blob_test.rb +65 -65
  188. data/test/integration/blob/informative_errors_test.rb +38 -38
  189. data/test/integration/blob/lease/acquire_lease_test.rb +36 -36
  190. data/test/integration/blob/lease/break_lease_test.rb +40 -40
  191. data/test/integration/blob/lease/release_lease_test.rb +40 -40
  192. data/test/integration/blob/lease/renew_lease_test.rb +42 -42
  193. data/test/integration/blob/list_blobs_test.rb +113 -113
  194. data/test/integration/cloud_service/Cloud_Create_test.rb +44 -44
  195. data/test/integration/cloud_service/Cloud_Delete_test.rb +44 -44
  196. data/test/integration/database/create_sql_server_firewall_test.rb +86 -86
  197. data/test/integration/database/create_sql_server_test.rb +53 -53
  198. data/test/integration/database/delete_sql_server_firewall_test.rb +70 -70
  199. data/test/integration/database/delete_sql_server_test.rb +58 -58
  200. data/test/integration/database/list_sql_server_firewall_test.rb +45 -45
  201. data/test/integration/database/list_sql_servers_test.rb +44 -44
  202. data/test/integration/database/reset_password_sql_server_test.rb +55 -55
  203. data/test/integration/location/Location_List_test.rb +39 -39
  204. data/test/integration/queue/clear_messages_test.rb +42 -42
  205. data/test/integration/queue/create_message_test.rb +75 -75
  206. data/test/integration/queue/create_queue_test.rb +50 -50
  207. data/test/integration/queue/delete_message_test.rb +67 -67
  208. data/test/integration/queue/delete_queue_test.rb +45 -45
  209. data/test/integration/queue/informative_errors_test.rb +41 -41
  210. data/test/integration/queue/list_messages_encoded_test.rb +79 -79
  211. data/test/integration/queue/list_messages_test.rb +79 -79
  212. data/test/integration/queue/list_queues_test.rb +44 -44
  213. data/test/integration/queue/peek_messages_test.rb +59 -59
  214. data/test/integration/queue/queue_gb18030_test.rb +131 -131
  215. data/test/integration/queue/queue_metadata_test.rb +40 -40
  216. data/test/integration/queue/update_message_test.rb +74 -74
  217. data/test/integration/service_bus/informative_errors_test.rb +36 -36
  218. data/test/integration/service_bus/queues_scenario_test.rb +200 -200
  219. data/test/integration/service_bus/queues_test.rb +265 -265
  220. data/test/integration/service_bus/relay_test.rb +131 -131
  221. data/test/integration/service_bus/rules_test.rb +144 -144
  222. data/test/integration/service_bus/sb_queue_gb18030_test.rb +182 -182
  223. data/test/integration/service_bus/scenario_test.rb +101 -101
  224. data/test/integration/service_bus/subscriptions_test.rb +211 -211
  225. data/test/integration/service_bus/topics_scenario_test.rb +406 -406
  226. data/test/integration/service_bus/topics_test.rb +129 -129
  227. data/test/integration/storage_management/storage_management_test.rb +160 -160
  228. data/test/integration/table/create_table_test.rb +35 -35
  229. data/test/integration/table/delete_entity_batch_test.rb +106 -106
  230. data/test/integration/table/delete_entity_test.rb +93 -93
  231. data/test/integration/table/delete_table_test.rb +39 -39
  232. data/test/integration/table/get_table_test.rb +36 -36
  233. data/test/integration/table/informative_errors_test.rb +38 -38
  234. data/test/integration/table/insert_entity_batch_test.rb +99 -99
  235. data/test/integration/table/insert_entity_test.rb +87 -87
  236. data/test/integration/table/insert_or_merge_entity_batch_test.rb +158 -158
  237. data/test/integration/table/insert_or_merge_entity_test.rb +142 -142
  238. data/test/integration/table/insert_or_replace_entity_batch_test.rb +151 -151
  239. data/test/integration/table/insert_or_replace_entity_test.rb +136 -136
  240. data/test/integration/table/merge_entity_batch_test.rb +127 -127
  241. data/test/integration/table/merge_entity_test.rb +112 -112
  242. data/test/integration/table/query_entities_test.rb +194 -194
  243. data/test/integration/table/query_tables_test.rb +42 -42
  244. data/test/integration/table/query_test.rb +250 -250
  245. data/test/integration/table/table_acl_test.rb +51 -51
  246. data/test/integration/table/table_gb18030_test.rb +355 -355
  247. data/test/integration/table/update_entity_batch_test.rb +148 -148
  248. data/test/integration/table/update_entity_test.rb +130 -130
  249. data/test/integration/test_helper.rb +42 -42
  250. data/test/integration/vm/VM_Create_test.rb +260 -260
  251. data/test/integration/vm/VM_Delete_test.rb +55 -55
  252. data/test/integration/vm/VM_Operations_test.rb +173 -173
  253. data/test/integration/vm_image/virtual_machine_disk_test.rb +37 -37
  254. data/test/integration/vm_image/virtual_machine_image_test.rb +36 -36
  255. data/test/integration/vnet/Virtual_Network_Create_test.rb +122 -122
  256. data/test/integration/vnet/Virtual_Network_list_test.rb +53 -53
  257. data/test/support/env.rb +19 -19
  258. data/test/support/fixtures.rb +36 -36
  259. data/test/support/name_generator.rb +168 -168
  260. data/test/support/stubs.rb +42 -42
  261. data/test/support/virtual_machine_name_generator.rb +102 -102
  262. data/test/support/virtual_network_helper.rb +73 -73
  263. data/test/test_helper.rb +53 -53
  264. data/test/unit/affinity_group/affinity_group_test.rb +192 -192
  265. data/test/unit/affinity_group/serialization_test.rb +88 -88
  266. data/test/unit/base_management/location_test.rb +57 -57
  267. data/test/unit/blob/blob_service_test.rb +1946 -1946
  268. data/test/unit/cloud_service_management/cloud_service_management_service_test.rb +94 -94
  269. data/test/unit/cloud_service_management/serialization_test.rb +169 -169
  270. data/test/unit/core/auth/shared_key_lite_test.rb +51 -51
  271. data/test/unit/core/auth/shared_key_test.rb +58 -58
  272. data/test/unit/core/auth/signer_test.rb +30 -30
  273. data/test/unit/core/http/http_error_test.rb +57 -57
  274. data/test/unit/core/http/http_request_test.rb +66 -66
  275. data/test/unit/core/http/http_response_test.rb +45 -45
  276. data/test/unit/core/http/retry_policy_test.rb +23 -23
  277. data/test/unit/database/serialization_test.rb +97 -97
  278. data/test/unit/database/sql_database_server_service_test.rb +288 -288
  279. data/test/unit/service/serialization_test.rb +532 -532
  280. data/test/unit/service/storage_service_test.rb +292 -292
  281. data/test/unit/storage_management/serialization_test.rb +232 -232
  282. data/test/unit/storage_management/storage_management_service_test.rb +261 -261
  283. data/test/unit/table/edmtype_test.rb +107 -107
  284. data/test/unit/virtual_machine_image_management/serialization_test.rb +35 -35
  285. data/test/unit/virtual_machine_image_management/virtual_machine_image_management_service_test.rb +65 -65
  286. data/test/unit/virtual_machine_management/serialization_test.rb +258 -258
  287. data/test/unit/virtual_machine_management/virtual_machine_management_service_test.rb +440 -440
  288. data/test/unit/vnet/serialization_test.rb +187 -187
  289. data/test/unit/vnet/virtual_network_management_service_test.rb +131 -131
  290. metadata +34 -27
@@ -1,560 +1,560 @@
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
-
17
- require 'azure/table/auth/shared_key'
18
-
19
- require 'azure/table/serialization'
20
- require 'azure/table/entity'
21
-
22
- module Azure
23
- module Table
24
- class TableService < Azure::Service::StorageService
25
-
26
- def initialize
27
- super(Azure::Table::Auth::SharedKey.new)
28
- @host = Azure.config.storage_table_host
29
- end
30
-
31
- # Public: Creates new table in the storage account
32
- #
33
- # ==== Attributes
34
- #
35
- # * +table_name+ - String. The table name
36
- # * +options+ - Hash. Optional parameters.
37
- #
38
- # ==== Options
39
- #
40
- # Accepted key/value pairs in options parameter are:
41
- #
42
- # * +:timeout+ - Integer. A timeout in seconds.
43
- #
44
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd135729
45
- #
46
- # Returns nil on success
47
- def create_table(table_name, options={})
48
- query = { }
49
- query["timeout"] = options[:timeout].to_s if options[:timeout]
50
-
51
- body = Azure::Table::Serialization.hash_to_entry_xml({"TableName" => table_name}).to_xml
52
- call(:post, collection_uri(query), body)
53
- nil
54
- end
55
-
56
- # Public: Deletes the specified table and any data it contains.
57
- #
58
- # ==== Attributes
59
- #
60
- # * +table_name+ - String. The table name
61
- # * +options+ - Hash. Optional parameters.
62
- #
63
- # ==== Options
64
- #
65
- # Accepted key/value pairs in options parameter are:
66
- # * +:timeout+ - Integer. A timeout in seconds.
67
- #
68
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179387
69
- #
70
- # Returns nil on success
71
- def delete_table(table_name, options={})
72
- query = { }
73
- query["timeout"] = options[:timeout].to_s if options[:timeout]
74
-
75
- call(:delete, table_uri(table_name, query))
76
- nil
77
- end
78
-
79
- # Public: Gets the table.
80
- #
81
- # ==== Attributes
82
- #
83
- # * +table_name+ - String. The table name
84
- # * +options+ - Hash. Optional parameters.
85
- #
86
- # ==== Options
87
- #
88
- # Accepted key/value pairs in options parameter are:
89
- # * +:timeout+ - Integer. A timeout in seconds.
90
- #
91
- # Returns the last updated time for the table
92
- def get_table(table_name, options={})
93
- query = { }
94
- query["timeout"] = options[:timeout].to_s if options[:timeout]
95
-
96
- response = call(:get, table_uri(table_name, query))
97
- results = Azure::Table::Serialization.hash_from_entry_xml(response.body)
98
- results[:updated]
99
- end
100
-
101
- # Public: Gets a list of all tables on the account.
102
- #
103
- # ==== Attributes
104
- #
105
- # * +options+ - Hash. Optional parameters.
106
- #
107
- # ==== Options
108
- #
109
- # Accepted key/value pairs in options parameter are:
110
- # * +:next_table_token+ - String. A token used to enumerate the next page of results, when the list of tables is
111
- # larger than a single operation can return at once. (optional)
112
- # * +:timeout+ - Integer. A timeout in seconds.
113
- #
114
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179405
115
- #
116
- # Returns an array with an extra continuation_token property on success
117
- def query_tables(options={})
118
- query = { }
119
- query["NextTable"] = options[:next_table_token] if options[:next_table_token]
120
- query["timeout"] = options[:timeout].to_s if options[:timeout]
121
-
122
- uri = collection_uri(query)
123
-
124
- response = call(:get, uri)
125
- entries = Azure::Table::Serialization.entries_from_feed_xml(response.body) || []
126
-
127
- values = Azure::Service::EnumerationResults.new(entries)
128
- values.continuation_token = response.headers["x-ms-continuation-NextTableName"]
129
- values
130
- end
131
-
132
- # Public: Gets the access control list (ACL) for the table.
133
- #
134
- # ==== Attributes
135
- #
136
- # * +table_name+ - String. The table name
137
- # * +options+ - Hash. Optional parameters.
138
- #
139
- # ==== Options
140
- #
141
- # Accepted key/value pairs in options parameter are:
142
- # * +:timeout+ - Integer. A timeout in seconds.
143
- #
144
- # See http://msdn.microsoft.com/en-us/library/windowsazure/jj159100
145
- #
146
- # Returns a list of Azure::Entity::SignedIdentifier instances
147
- def get_table_acl(table_name, options={})
148
- query = { "comp" => "acl" }
149
- query["timeout"] = options[:timeout].to_s if options[:timeout]
150
-
151
- response = call(:get, generate_uri(table_name, query))
152
-
153
- signed_identifiers = []
154
- signed_identifiers = Azure::Table::Serialization.signed_identifiers_from_xml response.body unless response.body == nil or response.body.length < 1
155
- signed_identifiers
156
- end
157
-
158
- # Public: Sets the access control list (ACL) for the table.
159
- #
160
- # ==== Attributes
161
- #
162
- # * +table_name+ - String. The table name
163
- # * +options+ - Hash. Optional parameters.
164
- #
165
- # ==== Options
166
- #
167
- # Accepted key/value pairs in options parameter are:
168
- # * +:signed_identifiers+ - Array. A list of Azure::Entity::SignedIdentifier instances
169
- # * +:timeout+ - Integer. A timeout in seconds.
170
- #
171
- # See http://msdn.microsoft.com/en-us/library/windowsazure/jj159102
172
- #
173
- # Returns nil on success
174
- def set_table_acl(table_name, options={})
175
- query = { "comp" => "acl" }
176
- query["timeout"] = options[:timeout].to_s if options[:timeout]
177
-
178
- uri = generate_uri(table_name, query)
179
- body = nil
180
- body = Azure::Table::Serialization.signed_identifiers_to_xml options[:signed_identifiers] if options[:signed_identifiers] && options[:signed_identifiers].length > 0
181
-
182
- call(:put, uri, body, {})
183
- nil
184
- end
185
-
186
- # Public: Inserts new entity to the table.
187
- #
188
- #
189
- # ==== Attributes
190
- #
191
- # * +table_name+ - String. The table name
192
- # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
193
- # * +options+ - Hash. Optional parameters.
194
- #
195
- # ==== Options
196
- #
197
- # Accepted key/value pairs in options parameter are:
198
- # * +:timeout+ - Integer. A timeout in seconds.
199
- #
200
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179433
201
- #
202
- # Returns a Azure::Entity::Table::Entity
203
- def insert_entity(table_name, entity_values, options={})
204
- body = Azure::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
205
-
206
- query = { }
207
- query["timeout"] = options[:timeout].to_s if options[:timeout]
208
-
209
- response = call(:post, entities_uri(table_name, nil, nil, query), body)
210
-
211
- result = Azure::Table::Serialization.hash_from_entry_xml(response.body)
212
-
213
- Entity.new do |entity|
214
- entity.table = table_name
215
- entity.updated = result[:updated]
216
- entity.etag = response.headers["etag"] || result[:etag]
217
- entity.properties = result[:properties]
218
- end
219
- end
220
-
221
- # Public: Queries entities for the given table name
222
- #
223
- # ==== Attributes
224
- #
225
- # * +table_name+ - String. The table name
226
- # * +options+ - Hash. Optional parameters.
227
- #
228
- # ==== Options
229
- #
230
- # Accepted key/value pairs in options parameter are:
231
- # * +:partition_key+ - String. The partition key (optional)
232
- # * +:row_key+ - String. The row key (optional)
233
- # * +:select+ - Array. An array of property names to return (optional)
234
- # * +:filter+ - String. A filter expression (optional)
235
- # * +:top+ - Integer. A limit for the number of results returned (optional)
236
- # * +:continuation_token+ - Hash. The continuation token.
237
- # * +:timeout+ - Integer. A timeout in seconds.
238
- #
239
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179421
240
- #
241
- # Returns an array with an extra continuation_token property on success
242
- def query_entities(table_name, options={})
243
- query ={}
244
- query["$select"] = options[:select].join ',' if options[:select]
245
- query["$filter"] = options[:filter] if options[:filter]
246
- query["$top"] = options[:top].to_s if options[:top] unless options[:partition_key] and options[:row_key]
247
- query["NextPartitionKey"] = options[:continuation_token][:next_partition_key] if options[:continuation_token] and options[:continuation_token][:next_partition_key]
248
- query["NextRowKey"] = options[:continuation_token][:next_row_key] if options[:continuation_token] and options[:continuation_token][:next_row_key]
249
- query["timeout"] = options[:timeout].to_s if options[:timeout]
250
-
251
- uri = entities_uri(table_name, options[:partition_key], options[:row_key], query)
252
- response = call(:get, uri, nil, { "DataServiceVersion" => "2.0;NetFx"})
253
-
254
- entities = Azure::Service::EnumerationResults.new
255
-
256
- results = (options[:partition_key] and options[:row_key]) ? [Azure::Table::Serialization.hash_from_entry_xml(response.body)] : Azure::Table::Serialization.entries_from_feed_xml(response.body)
257
-
258
- results.each do |result|
259
- entity = Entity.new do |e|
260
- e.table = table_name
261
- e.updated = result[:updated]
262
- e.etag = response.headers["etag"] || result[:etag]
263
- e.properties = result[:properties]
264
- end
265
- entities.push entity
266
- end if results
267
-
268
- entities.continuation_token = nil
269
- entities.continuation_token = {
270
- :next_partition_key=> response.headers["x-ms-continuation-NextPartitionKey"],
271
- :next_row_key => response.headers["x-ms-continuation-NextRowKey"]
272
- } if response.headers["x-ms-continuation-NextPartitionKey"]
273
-
274
- entities
275
- end
276
-
277
- # Public: Updates an existing entity in a table. The Update Entity operation replaces
278
- # the entire entity and can be used to remove properties.
279
- #
280
- # ==== Attributes
281
- #
282
- # * +table_name+ - String. The table name
283
- # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
284
- # * +options+ - Hash. Optional parameters.
285
- #
286
- # ==== Options
287
- #
288
- # Accepted key/value pairs in options parameter are:
289
- # * +:if_match+ - String. A matching condition which is required for update (optional, Default="*")
290
- # * +:create_if_not_exists+ - Boolean. If true, and partition_key and row_key do not reference and existing entity,
291
- # that entity will be inserted. If false, the operation will fail. (optional, Default=false)
292
- # * +:timeout+ - Integer. A timeout in seconds.
293
- #
294
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179427
295
- #
296
- # Returns the ETag for the entity on success
297
- def update_entity(table_name, entity_values, options={})
298
- if_match = "*"
299
- if_match = options[:if_match] if options[:if_match]
300
-
301
- query = { }
302
- query["timeout"] = options[:timeout].to_s if options[:timeout]
303
-
304
- uri = entities_uri(table_name, entity_values["PartitionKey"], entity_values["RowKey"], query)
305
-
306
- headers = {}
307
- headers["If-Match"] = if_match || "*" unless options[:create_if_not_exists]
308
-
309
- body = Azure::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
310
-
311
- response = call(:put, uri, body, headers)
312
- response.headers["etag"]
313
- end
314
-
315
- # Public: Updates an existing entity by updating the entity's properties. This operation
316
- # does not replace the existing entity, as the update_entity operation does.
317
- #
318
- # ==== Attributes
319
- #
320
- # * +table_name+ - String. The table name
321
- # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
322
- # * +options+ - Hash. Optional parameters.
323
- #
324
- # ==== Options
325
- #
326
- # Accepted key/value pairs in options parameter are:
327
- # * +:if_match+ - String. A matching condition which is required for update (optional, Default="*")
328
- # * +:create_if_not_exists+ - Boolean. If true, and partition_key and row_key do not reference and existing entity,
329
- # that entity will be inserted. If false, the operation will fail. (optional, Default=false)
330
- # * +:timeout+ - Integer. A timeout in seconds.
331
- #
332
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179392
333
- #
334
- # Returns the ETag for the entity on success
335
- def merge_entity(table_name, entity_values, options={})
336
- if_match = "*"
337
- if_match = options[:if_match] if options[:if_match]
338
-
339
- query = { }
340
- query["timeout"] = options[:timeout].to_s if options[:timeout]
341
-
342
- uri = entities_uri(table_name, entity_values["PartitionKey"], entity_values["RowKey"], query)
343
-
344
- headers = { "X-HTTP-Method"=> "MERGE" }
345
- headers["If-Match"] = if_match || "*" unless options[:create_if_not_exists]
346
-
347
- body = Azure::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
348
-
349
- response = call(:post, uri, body, headers)
350
- response.headers["etag"]
351
- end
352
-
353
- # Public: Inserts or updates an existing entity within a table by merging new property values into the entity.
354
- #
355
- # ==== Attributes
356
- #
357
- # * +table_name+ - String. The table name
358
- # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
359
- # * +options+ - Hash. Optional parameters.
360
- #
361
- # ==== Options
362
- #
363
- # Accepted key/value pairs in options parameter are:
364
- # * +:timeout+ - Integer. A timeout in seconds.
365
- #
366
- # See http://msdn.microsoft.com/en-us/library/windowsazure/hh452241
367
- #
368
- # Returns the ETag for the entity on success
369
- def insert_or_merge_entity(table_name, entity_values, options={})
370
- options[:create_if_not_exists] = true
371
- merge_entity(table_name, entity_values, options)
372
- end
373
-
374
- # Public: Inserts or updates a new entity into a table.
375
- #
376
- # ==== Attributes
377
- #
378
- # * +table_name+ - String. The table name
379
- # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
380
- # * +options+ - Hash. Optional parameters.
381
- #
382
- # ==== Options
383
- #
384
- # Accepted key/value pairs in options parameter are:
385
- # * +:timeout+ - Integer. A timeout in seconds.
386
- #
387
- # See http://msdn.microsoft.com/en-us/library/windowsazure/hh452242
388
- #
389
- # Returns the ETag for the entity on success
390
- def insert_or_replace_entity(table_name, entity_values, options={})
391
- options[:create_if_not_exists] = true
392
- update_entity(table_name, entity_values, options)
393
- end
394
-
395
- # Public: Deletes an existing entity in the table.
396
- #
397
- # ==== Attributes
398
- #
399
- # * +table_name+ - String. The table name
400
- # * +partition_key+ - String. The partition key
401
- # * +row_key+ - String. The row key
402
- # * +options+ - Hash. Optional parameters.
403
- #
404
- # ==== Options
405
- #
406
- # Accepted key/value pairs in options parameter are:
407
- # * +:if_match+ - String. A matching condition which is required for update (optional, Default="*")
408
- # * +:timeout+ - Integer. A timeout in seconds.
409
- #
410
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd135727
411
- #
412
- # Returns nil on success
413
- def delete_entity(table_name, partition_key, row_key, options={})
414
- if_match = "*"
415
- if_match = options[:if_match] if options[:if_match]
416
-
417
- query = { }
418
- query["timeout"] = options[:timeout].to_s if options[:timeout]
419
-
420
- call(:delete, entities_uri(table_name, partition_key, row_key, query), nil, { "If-Match"=> if_match })
421
- nil
422
- end
423
-
424
- # Public: Executes a batch of operations.
425
- #
426
- # ==== Attributes
427
- #
428
- # * +batch+ - The Azure::Table::Batch instance to execute.
429
- # * +options+ - Hash. Optional parameters.
430
- #
431
- # ==== Options
432
- #
433
- # Accepted key/value pairs in options parameter are:
434
- # * +:timeout+ - Integer. A timeout in seconds.
435
- #
436
- # See http://msdn.microsoft.com/en-us/library/windowsazure/dd894038
437
- #
438
- # Returns an array of results, one for each operation in the batch
439
- def execute_batch(batch, options={})
440
- headers = {
441
- "Content-Type"=> "multipart/mixed; boundary=#{batch.batch_id}",
442
- "Accept"=> 'application/atom+xml,application/xml',
443
- 'Accept-Charset'=> 'UTF-8'
444
- }
445
-
446
- query = { }
447
- query["timeout"] = options[:timeout].to_s if options[:timeout]
448
-
449
- body = batch.to_body
450
- response = call(:post, generate_uri("/$batch", query), body, headers)
451
- batch.parse_response(response)
452
- end
453
-
454
- # Public: Gets an existing entity in the table.
455
- #
456
- # ==== Attributes
457
- #
458
- # * +table_name+ - String. The table name
459
- # * +partition_key+ - String. The partition key
460
- # * +row_key+ - String. The row key
461
- # * +options+ - Hash. Optional parameters.
462
- #
463
- # ==== Options
464
- #
465
- # Accepted key/value pairs in options parameter are:
466
- # * +:timeout+ - Integer. A timeout in seconds.
467
- #
468
- # Returns an Azure::Table::Entity instance on success
469
- def get_entity(table_name, partition_key, row_key, options={})
470
- options[:partition_key] = partition_key
471
- options[:row_key] = row_key
472
- results = query_entities(table_name, options)
473
- results.length > 0 ? results[0] : nil
474
- end
475
-
476
- # Protected: Generate the URI for the collection of tables.
477
- #
478
- # Returns a URI
479
- protected
480
- def collection_uri(query={})
481
- generate_uri("Tables", query)
482
- end
483
-
484
- # Public: Generate the URI for a specific table.
485
- #
486
- # ==== Attributes
487
- #
488
- # * +name+ - The table name. If this is a URI, we just return this
489
- #
490
- # Returns a URI
491
- public
492
- def table_uri(name, query={})
493
- return name if name.kind_of? ::URI
494
- generate_uri("Tables('#{name}')", query)
495
- end
496
-
497
- # Public: Generate the URI for an entity or group of entities in a table.
498
- # If both the 'partition_key' and 'row_key' are specified, then the URI
499
- # will match the entity under those specific keys.
500
- #
501
- # ==== Attributes
502
- #
503
- # * +table_name+ - The table name
504
- # * +partition_key+ - The desired partition key (optional)
505
- # * +row_key+ - The desired row key (optional)
506
- #
507
- # Returns a URI
508
- public
509
- def entities_uri(table_name, partition_key=nil, row_key=nil, query={})
510
- return table_name if table_name.kind_of? ::URI
511
-
512
- path = if partition_key && row_key
513
- "%s(PartitionKey='%s',RowKey='%s')" % [
514
- table_name.encode("UTF-8"), encodeODataUriValue(partition_key.encode("UTF-8")), encodeODataUriValue(row_key.encode("UTF-8"))
515
- ]
516
- else
517
- "%s()" % table_name.encode("UTF-8")
518
- end
519
-
520
- uri = generate_uri(path)
521
- qs = []
522
- if query
523
- query.each do | key, val |
524
- key = key.encode("UTF-8")
525
- val = val.encode("UTF-8")
526
-
527
- if key[0] == "$"
528
- qs.push "#{key}#{::URI.encode_www_form(""=>val)}"
529
- else
530
- qs.push ::URI.encode_www_form(key=>val)
531
- end
532
- end
533
- end
534
- uri.query = qs.join '&' if qs.length > 0
535
- uri
536
- end
537
-
538
- protected
539
- def encodeODataUriValues(values)
540
- new_values = []
541
- values.each do |value|
542
- new_values.push encodeODataUriValue(value)
543
- end
544
- new_values
545
- end
546
-
547
- protected
548
- def encodeODataUriValue(value)
549
- # Replace each single quote (') with double single quotes ('') not double
550
- # quotes (")
551
- value = value.gsub("'", "''")
552
-
553
- # Encode the special URL characters
554
- value = URI.escape(value)
555
-
556
- value
557
- end
558
- end
559
- 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
+
17
+ require 'azure/table/auth/shared_key'
18
+
19
+ require 'azure/table/serialization'
20
+ require 'azure/table/entity'
21
+
22
+ module Azure
23
+ module Table
24
+ class TableService < Azure::Service::StorageService
25
+
26
+ def initialize
27
+ super(Azure::Table::Auth::SharedKey.new)
28
+ @host = Azure.config.storage_table_host
29
+ end
30
+
31
+ # Public: Creates new table in the storage account
32
+ #
33
+ # ==== Attributes
34
+ #
35
+ # * +table_name+ - String. The table name
36
+ # * +options+ - Hash. Optional parameters.
37
+ #
38
+ # ==== Options
39
+ #
40
+ # Accepted key/value pairs in options parameter are:
41
+ #
42
+ # * +:timeout+ - Integer. A timeout in seconds.
43
+ #
44
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd135729
45
+ #
46
+ # Returns nil on success
47
+ def create_table(table_name, options={})
48
+ query = { }
49
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
50
+
51
+ body = Azure::Table::Serialization.hash_to_entry_xml({"TableName" => table_name}).to_xml
52
+ call(:post, collection_uri(query), body)
53
+ nil
54
+ end
55
+
56
+ # Public: Deletes the specified table and any data it contains.
57
+ #
58
+ # ==== Attributes
59
+ #
60
+ # * +table_name+ - String. The table name
61
+ # * +options+ - Hash. Optional parameters.
62
+ #
63
+ # ==== Options
64
+ #
65
+ # Accepted key/value pairs in options parameter are:
66
+ # * +:timeout+ - Integer. A timeout in seconds.
67
+ #
68
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179387
69
+ #
70
+ # Returns nil on success
71
+ def delete_table(table_name, options={})
72
+ query = { }
73
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
74
+
75
+ call(:delete, table_uri(table_name, query))
76
+ nil
77
+ end
78
+
79
+ # Public: Gets the table.
80
+ #
81
+ # ==== Attributes
82
+ #
83
+ # * +table_name+ - String. The table name
84
+ # * +options+ - Hash. Optional parameters.
85
+ #
86
+ # ==== Options
87
+ #
88
+ # Accepted key/value pairs in options parameter are:
89
+ # * +:timeout+ - Integer. A timeout in seconds.
90
+ #
91
+ # Returns the last updated time for the table
92
+ def get_table(table_name, options={})
93
+ query = { }
94
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
95
+
96
+ response = call(:get, table_uri(table_name, query))
97
+ results = Azure::Table::Serialization.hash_from_entry_xml(response.body)
98
+ results[:updated]
99
+ end
100
+
101
+ # Public: Gets a list of all tables on the account.
102
+ #
103
+ # ==== Attributes
104
+ #
105
+ # * +options+ - Hash. Optional parameters.
106
+ #
107
+ # ==== Options
108
+ #
109
+ # Accepted key/value pairs in options parameter are:
110
+ # * +:next_table_token+ - String. A token used to enumerate the next page of results, when the list of tables is
111
+ # larger than a single operation can return at once. (optional)
112
+ # * +:timeout+ - Integer. A timeout in seconds.
113
+ #
114
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179405
115
+ #
116
+ # Returns an array with an extra continuation_token property on success
117
+ def query_tables(options={})
118
+ query = { }
119
+ query["NextTable"] = options[:next_table_token] if options[:next_table_token]
120
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
121
+
122
+ uri = collection_uri(query)
123
+
124
+ response = call(:get, uri)
125
+ entries = Azure::Table::Serialization.entries_from_feed_xml(response.body) || []
126
+
127
+ values = Azure::Service::EnumerationResults.new(entries)
128
+ values.continuation_token = response.headers["x-ms-continuation-NextTableName"]
129
+ values
130
+ end
131
+
132
+ # Public: Gets the access control list (ACL) for the table.
133
+ #
134
+ # ==== Attributes
135
+ #
136
+ # * +table_name+ - String. The table name
137
+ # * +options+ - Hash. Optional parameters.
138
+ #
139
+ # ==== Options
140
+ #
141
+ # Accepted key/value pairs in options parameter are:
142
+ # * +:timeout+ - Integer. A timeout in seconds.
143
+ #
144
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/jj159100
145
+ #
146
+ # Returns a list of Azure::Entity::SignedIdentifier instances
147
+ def get_table_acl(table_name, options={})
148
+ query = { "comp" => "acl" }
149
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
150
+
151
+ response = call(:get, generate_uri(table_name, query))
152
+
153
+ signed_identifiers = []
154
+ signed_identifiers = Azure::Table::Serialization.signed_identifiers_from_xml response.body unless response.body == nil or response.body.length < 1
155
+ signed_identifiers
156
+ end
157
+
158
+ # Public: Sets the access control list (ACL) for the table.
159
+ #
160
+ # ==== Attributes
161
+ #
162
+ # * +table_name+ - String. The table name
163
+ # * +options+ - Hash. Optional parameters.
164
+ #
165
+ # ==== Options
166
+ #
167
+ # Accepted key/value pairs in options parameter are:
168
+ # * +:signed_identifiers+ - Array. A list of Azure::Entity::SignedIdentifier instances
169
+ # * +:timeout+ - Integer. A timeout in seconds.
170
+ #
171
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/jj159102
172
+ #
173
+ # Returns nil on success
174
+ def set_table_acl(table_name, options={})
175
+ query = { "comp" => "acl" }
176
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
177
+
178
+ uri = generate_uri(table_name, query)
179
+ body = nil
180
+ body = Azure::Table::Serialization.signed_identifiers_to_xml options[:signed_identifiers] if options[:signed_identifiers] && options[:signed_identifiers].length > 0
181
+
182
+ call(:put, uri, body, {})
183
+ nil
184
+ end
185
+
186
+ # Public: Inserts new entity to the table.
187
+ #
188
+ #
189
+ # ==== Attributes
190
+ #
191
+ # * +table_name+ - String. The table name
192
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
193
+ # * +options+ - Hash. Optional parameters.
194
+ #
195
+ # ==== Options
196
+ #
197
+ # Accepted key/value pairs in options parameter are:
198
+ # * +:timeout+ - Integer. A timeout in seconds.
199
+ #
200
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179433
201
+ #
202
+ # Returns a Azure::Entity::Table::Entity
203
+ def insert_entity(table_name, entity_values, options={})
204
+ body = Azure::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
205
+
206
+ query = { }
207
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
208
+
209
+ response = call(:post, entities_uri(table_name, nil, nil, query), body)
210
+
211
+ result = Azure::Table::Serialization.hash_from_entry_xml(response.body)
212
+
213
+ Entity.new do |entity|
214
+ entity.table = table_name
215
+ entity.updated = result[:updated]
216
+ entity.etag = response.headers["etag"] || result[:etag]
217
+ entity.properties = result[:properties]
218
+ end
219
+ end
220
+
221
+ # Public: Queries entities for the given table name
222
+ #
223
+ # ==== Attributes
224
+ #
225
+ # * +table_name+ - String. The table name
226
+ # * +options+ - Hash. Optional parameters.
227
+ #
228
+ # ==== Options
229
+ #
230
+ # Accepted key/value pairs in options parameter are:
231
+ # * +:partition_key+ - String. The partition key (optional)
232
+ # * +:row_key+ - String. The row key (optional)
233
+ # * +:select+ - Array. An array of property names to return (optional)
234
+ # * +:filter+ - String. A filter expression (optional)
235
+ # * +:top+ - Integer. A limit for the number of results returned (optional)
236
+ # * +:continuation_token+ - Hash. The continuation token.
237
+ # * +:timeout+ - Integer. A timeout in seconds.
238
+ #
239
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179421
240
+ #
241
+ # Returns an array with an extra continuation_token property on success
242
+ def query_entities(table_name, options={})
243
+ query ={}
244
+ query["$select"] = options[:select].join ',' if options[:select]
245
+ query["$filter"] = options[:filter] if options[:filter]
246
+ query["$top"] = options[:top].to_s if options[:top] unless options[:partition_key] and options[:row_key]
247
+ query["NextPartitionKey"] = options[:continuation_token][:next_partition_key] if options[:continuation_token] and options[:continuation_token][:next_partition_key]
248
+ query["NextRowKey"] = options[:continuation_token][:next_row_key] if options[:continuation_token] and options[:continuation_token][:next_row_key]
249
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
250
+
251
+ uri = entities_uri(table_name, options[:partition_key], options[:row_key], query)
252
+ response = call(:get, uri, nil, { "DataServiceVersion" => "2.0;NetFx"})
253
+
254
+ entities = Azure::Service::EnumerationResults.new
255
+
256
+ results = (options[:partition_key] and options[:row_key]) ? [Azure::Table::Serialization.hash_from_entry_xml(response.body)] : Azure::Table::Serialization.entries_from_feed_xml(response.body)
257
+
258
+ results.each do |result|
259
+ entity = Entity.new do |e|
260
+ e.table = table_name
261
+ e.updated = result[:updated]
262
+ e.etag = response.headers["etag"] || result[:etag]
263
+ e.properties = result[:properties]
264
+ end
265
+ entities.push entity
266
+ end if results
267
+
268
+ entities.continuation_token = nil
269
+ entities.continuation_token = {
270
+ :next_partition_key=> response.headers["x-ms-continuation-NextPartitionKey"],
271
+ :next_row_key => response.headers["x-ms-continuation-NextRowKey"]
272
+ } if response.headers["x-ms-continuation-NextPartitionKey"]
273
+
274
+ entities
275
+ end
276
+
277
+ # Public: Updates an existing entity in a table. The Update Entity operation replaces
278
+ # the entire entity and can be used to remove properties.
279
+ #
280
+ # ==== Attributes
281
+ #
282
+ # * +table_name+ - String. The table name
283
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
284
+ # * +options+ - Hash. Optional parameters.
285
+ #
286
+ # ==== Options
287
+ #
288
+ # Accepted key/value pairs in options parameter are:
289
+ # * +:if_match+ - String. A matching condition which is required for update (optional, Default="*")
290
+ # * +:create_if_not_exists+ - Boolean. If true, and partition_key and row_key do not reference and existing entity,
291
+ # that entity will be inserted. If false, the operation will fail. (optional, Default=false)
292
+ # * +:timeout+ - Integer. A timeout in seconds.
293
+ #
294
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179427
295
+ #
296
+ # Returns the ETag for the entity on success
297
+ def update_entity(table_name, entity_values, options={})
298
+ if_match = "*"
299
+ if_match = options[:if_match] if options[:if_match]
300
+
301
+ query = { }
302
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
303
+
304
+ uri = entities_uri(table_name, entity_values["PartitionKey"], entity_values["RowKey"], query)
305
+
306
+ headers = {}
307
+ headers["If-Match"] = if_match || "*" unless options[:create_if_not_exists]
308
+
309
+ body = Azure::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
310
+
311
+ response = call(:put, uri, body, headers)
312
+ response.headers["etag"]
313
+ end
314
+
315
+ # Public: Updates an existing entity by updating the entity's properties. This operation
316
+ # does not replace the existing entity, as the update_entity operation does.
317
+ #
318
+ # ==== Attributes
319
+ #
320
+ # * +table_name+ - String. The table name
321
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
322
+ # * +options+ - Hash. Optional parameters.
323
+ #
324
+ # ==== Options
325
+ #
326
+ # Accepted key/value pairs in options parameter are:
327
+ # * +:if_match+ - String. A matching condition which is required for update (optional, Default="*")
328
+ # * +:create_if_not_exists+ - Boolean. If true, and partition_key and row_key do not reference and existing entity,
329
+ # that entity will be inserted. If false, the operation will fail. (optional, Default=false)
330
+ # * +:timeout+ - Integer. A timeout in seconds.
331
+ #
332
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd179392
333
+ #
334
+ # Returns the ETag for the entity on success
335
+ def merge_entity(table_name, entity_values, options={})
336
+ if_match = "*"
337
+ if_match = options[:if_match] if options[:if_match]
338
+
339
+ query = { }
340
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
341
+
342
+ uri = entities_uri(table_name, entity_values["PartitionKey"], entity_values["RowKey"], query)
343
+
344
+ headers = { "X-HTTP-Method"=> "MERGE" }
345
+ headers["If-Match"] = if_match || "*" unless options[:create_if_not_exists]
346
+
347
+ body = Azure::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
348
+
349
+ response = call(:post, uri, body, headers)
350
+ response.headers["etag"]
351
+ end
352
+
353
+ # Public: Inserts or updates an existing entity within a table by merging new property values into the entity.
354
+ #
355
+ # ==== Attributes
356
+ #
357
+ # * +table_name+ - String. The table name
358
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
359
+ # * +options+ - Hash. Optional parameters.
360
+ #
361
+ # ==== Options
362
+ #
363
+ # Accepted key/value pairs in options parameter are:
364
+ # * +:timeout+ - Integer. A timeout in seconds.
365
+ #
366
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/hh452241
367
+ #
368
+ # Returns the ETag for the entity on success
369
+ def insert_or_merge_entity(table_name, entity_values, options={})
370
+ options[:create_if_not_exists] = true
371
+ merge_entity(table_name, entity_values, options)
372
+ end
373
+
374
+ # Public: Inserts or updates a new entity into a table.
375
+ #
376
+ # ==== Attributes
377
+ #
378
+ # * +table_name+ - String. The table name
379
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
380
+ # * +options+ - Hash. Optional parameters.
381
+ #
382
+ # ==== Options
383
+ #
384
+ # Accepted key/value pairs in options parameter are:
385
+ # * +:timeout+ - Integer. A timeout in seconds.
386
+ #
387
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/hh452242
388
+ #
389
+ # Returns the ETag for the entity on success
390
+ def insert_or_replace_entity(table_name, entity_values, options={})
391
+ options[:create_if_not_exists] = true
392
+ update_entity(table_name, entity_values, options)
393
+ end
394
+
395
+ # Public: Deletes an existing entity in the table.
396
+ #
397
+ # ==== Attributes
398
+ #
399
+ # * +table_name+ - String. The table name
400
+ # * +partition_key+ - String. The partition key
401
+ # * +row_key+ - String. The row key
402
+ # * +options+ - Hash. Optional parameters.
403
+ #
404
+ # ==== Options
405
+ #
406
+ # Accepted key/value pairs in options parameter are:
407
+ # * +:if_match+ - String. A matching condition which is required for update (optional, Default="*")
408
+ # * +:timeout+ - Integer. A timeout in seconds.
409
+ #
410
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd135727
411
+ #
412
+ # Returns nil on success
413
+ def delete_entity(table_name, partition_key, row_key, options={})
414
+ if_match = "*"
415
+ if_match = options[:if_match] if options[:if_match]
416
+
417
+ query = { }
418
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
419
+
420
+ call(:delete, entities_uri(table_name, partition_key, row_key, query), nil, { "If-Match"=> if_match })
421
+ nil
422
+ end
423
+
424
+ # Public: Executes a batch of operations.
425
+ #
426
+ # ==== Attributes
427
+ #
428
+ # * +batch+ - The Azure::Table::Batch instance to execute.
429
+ # * +options+ - Hash. Optional parameters.
430
+ #
431
+ # ==== Options
432
+ #
433
+ # Accepted key/value pairs in options parameter are:
434
+ # * +:timeout+ - Integer. A timeout in seconds.
435
+ #
436
+ # See http://msdn.microsoft.com/en-us/library/windowsazure/dd894038
437
+ #
438
+ # Returns an array of results, one for each operation in the batch
439
+ def execute_batch(batch, options={})
440
+ headers = {
441
+ "Content-Type"=> "multipart/mixed; boundary=#{batch.batch_id}",
442
+ "Accept"=> 'application/atom+xml,application/xml',
443
+ 'Accept-Charset'=> 'UTF-8'
444
+ }
445
+
446
+ query = { }
447
+ query["timeout"] = options[:timeout].to_s if options[:timeout]
448
+
449
+ body = batch.to_body
450
+ response = call(:post, generate_uri("/$batch", query), body, headers)
451
+ batch.parse_response(response)
452
+ end
453
+
454
+ # Public: Gets an existing entity in the table.
455
+ #
456
+ # ==== Attributes
457
+ #
458
+ # * +table_name+ - String. The table name
459
+ # * +partition_key+ - String. The partition key
460
+ # * +row_key+ - String. The row key
461
+ # * +options+ - Hash. Optional parameters.
462
+ #
463
+ # ==== Options
464
+ #
465
+ # Accepted key/value pairs in options parameter are:
466
+ # * +:timeout+ - Integer. A timeout in seconds.
467
+ #
468
+ # Returns an Azure::Table::Entity instance on success
469
+ def get_entity(table_name, partition_key, row_key, options={})
470
+ options[:partition_key] = partition_key
471
+ options[:row_key] = row_key
472
+ results = query_entities(table_name, options)
473
+ results.length > 0 ? results[0] : nil
474
+ end
475
+
476
+ # Protected: Generate the URI for the collection of tables.
477
+ #
478
+ # Returns a URI
479
+ protected
480
+ def collection_uri(query={})
481
+ generate_uri("Tables", query)
482
+ end
483
+
484
+ # Public: Generate the URI for a specific table.
485
+ #
486
+ # ==== Attributes
487
+ #
488
+ # * +name+ - The table name. If this is a URI, we just return this
489
+ #
490
+ # Returns a URI
491
+ public
492
+ def table_uri(name, query={})
493
+ return name if name.kind_of? ::URI
494
+ generate_uri("Tables('#{name}')", query)
495
+ end
496
+
497
+ # Public: Generate the URI for an entity or group of entities in a table.
498
+ # If both the 'partition_key' and 'row_key' are specified, then the URI
499
+ # will match the entity under those specific keys.
500
+ #
501
+ # ==== Attributes
502
+ #
503
+ # * +table_name+ - The table name
504
+ # * +partition_key+ - The desired partition key (optional)
505
+ # * +row_key+ - The desired row key (optional)
506
+ #
507
+ # Returns a URI
508
+ public
509
+ def entities_uri(table_name, partition_key=nil, row_key=nil, query={})
510
+ return table_name if table_name.kind_of? ::URI
511
+
512
+ path = if partition_key && row_key
513
+ "%s(PartitionKey='%s',RowKey='%s')" % [
514
+ table_name.encode("UTF-8"), encodeODataUriValue(partition_key.encode("UTF-8")), encodeODataUriValue(row_key.encode("UTF-8"))
515
+ ]
516
+ else
517
+ "%s()" % table_name.encode("UTF-8")
518
+ end
519
+
520
+ uri = generate_uri(path)
521
+ qs = []
522
+ if query
523
+ query.each do | key, val |
524
+ key = key.encode("UTF-8")
525
+ val = val.encode("UTF-8")
526
+
527
+ if key[0] == "$"
528
+ qs.push "#{key}#{::URI.encode_www_form(""=>val)}"
529
+ else
530
+ qs.push ::URI.encode_www_form(key=>val)
531
+ end
532
+ end
533
+ end
534
+ uri.query = qs.join '&' if qs.length > 0
535
+ uri
536
+ end
537
+
538
+ protected
539
+ def encodeODataUriValues(values)
540
+ new_values = []
541
+ values.each do |value|
542
+ new_values.push encodeODataUriValue(value)
543
+ end
544
+ new_values
545
+ end
546
+
547
+ protected
548
+ def encodeODataUriValue(value)
549
+ # Replace each single quote (') with double single quotes ('') not double
550
+ # quotes (")
551
+ value = value.gsub("'", "''")
552
+
553
+ # Encode the special URL characters
554
+ value = URI.escape(value)
555
+
556
+ value
557
+ end
558
+ end
559
+ end
560
560
  end