azure-storage-table 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 402740750d3b6341f9a771184e3c8fc4bdf0cad7
4
+ data.tar.gz: 533ac2a5d1d11074fd714cd3cb0e442dcd335f2b
5
+ SHA512:
6
+ metadata.gz: 6a0b48932284241d92ad64288b041552c647521ed02bb894e2684026ba36228b47ac92f78b1fb30b52d42ec1320bd685116e516b9dcbf0a5afc16fed6bbf2bb1
7
+ data.tar.gz: 80eaf676183660f4e661ab64a30987bd86c793f207de3b305420057388777e56f8fa6e5560239d512cd657e0cd6e9cc2551131a3bae7925394f90bf58516fa95
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+ require "azure/storage/table/autoload"
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+ require "cgi"
27
+ require "azure/storage/common/core/auth/shared_key"
28
+
29
+ module Azure::Storage
30
+ module Table
31
+ module Auth
32
+ class SharedKey < Azure::Storage::Common::Core::Auth::SharedKey
33
+ # The account name
34
+ attr :account_name
35
+
36
+ # Generate the string to sign.
37
+ #
38
+ # @param method [Symbol] The HTTP request method.
39
+ # @param uri [URI] The URI of the request we're signing.
40
+ # @param headers [Hash] The HTTP request headers.
41
+ #
42
+ # Returns a plain text string.
43
+ def signable_string(method, uri, headers)
44
+ [
45
+ method.to_s.upcase,
46
+ headers.fetch("Content-MD5", ""),
47
+ headers.fetch("Content-Type", ""),
48
+ headers.fetch("Date") { headers.fetch("x-ms-date") },
49
+ canonicalized_resource(uri)
50
+ ].join("\n")
51
+ end
52
+
53
+ # Calculate the Canonicalized Resource string for a request.
54
+ #
55
+ # @param uri [URI] The request's URI.
56
+ #
57
+ # @return [String] with the canonicalized resource.
58
+ def canonicalized_resource(uri)
59
+ resource = "/#{account_name}#{uri.path}"
60
+
61
+ comp = CGI.parse(uri.query.to_s).fetch("comp", nil)
62
+ resource = [resource, "comp=" + comp[0]].join("?") if comp
63
+
64
+ resource
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+ require "rubygems"
27
+ require "nokogiri"
28
+ require "base64"
29
+
30
+ require "azure/storage/common"
31
+
32
+ module Azure
33
+ module Storage
34
+ module Table
35
+ autoload :Default, "azure/storage/table/default"
36
+ autoload :TableConstants, "azure/storage/table/default"
37
+ autoload :Version, "azure/storage/table/version"
38
+ autoload :Serialization, "azure/storage/table/serialization"
39
+ autoload :TableService, "azure/storage/table/table_service"
40
+ autoload :Batch, "azure/storage/table/batch"
41
+ autoload :Query, "azure/storage/table/query"
42
+ autoload :BatchResponse, "azure/storage/table/batch_response"
43
+ autoload :EdmType, "azure/storage/table/edmtype"
44
+ autoload :Entity, "azure/storage/table/entity"
45
+ autoload :GUID, "azure/storage/table/guid"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,366 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ require "securerandom"
25
+ require "azure/core/http/http_error"
26
+
27
+ module Azure::Storage
28
+ module Table
29
+ # Represents a batch of table operations.
30
+ #
31
+ # Example usage:
32
+ #
33
+ # svc = TableSerice.new
34
+ #
35
+ # batch = Batch.new "table", "partition"
36
+ # batch.insert "row1", {"meta"=>"data"}
37
+ # batch.insert "row2", {"meta"=>"data"}
38
+ #
39
+ # results = svc.execute_batch batch
40
+ #
41
+ class Batch
42
+ def initialize(table, partition, &block)
43
+ @table = table
44
+ @partition = partition
45
+ @operations = []
46
+ @entity_keys = []
47
+ @batch_id = "batch_" + SecureRandom.uuid
48
+ @changeset_id = "changeset_" + SecureRandom.uuid
49
+
50
+ self.instance_eval(&block) if block_given?
51
+ end
52
+
53
+ private
54
+ attr_reader :table
55
+ attr_reader :partition
56
+
57
+ attr_accessor :operations
58
+ attr_accessor :entity_keys
59
+ attr_accessor :changeset_id
60
+
61
+ public
62
+ attr_accessor :batch_id
63
+
64
+ protected
65
+ class ResponseWrapper
66
+ def initialize(hash)
67
+ @hash = hash
68
+ end
69
+
70
+ def uri
71
+ @hash[:uri]
72
+ end
73
+
74
+ def status_code
75
+ @hash[:status_code].to_i
76
+ end
77
+
78
+ def body
79
+ @hash[:body]
80
+ end
81
+ end
82
+
83
+ protected
84
+ def add_operation(method, row_key = nil, body = nil, headers = nil)
85
+ raise Azure::Storage::Common::Core::StorageError.new("Get operation should be the only operation in the batch.") if operations.length > 0 && (method == :get || operations[0][:method] == :get)
86
+ op = {
87
+ method: method,
88
+ row_key: row_key,
89
+ body: body,
90
+ headers: headers.merge(
91
+ Azure::Storage::Common::HeaderConstants::CONTENT_TYPE => Azure::Storage::Common::HeaderConstants::JSON_CONTENT_TYPE_VALUE,
92
+ Azure::Storage::Common::HeaderConstants::DATA_SERVICE_VERSION => TableConstants::DEFAULT_DATA_SERVICE_VERSION
93
+ )
94
+ }
95
+ operations.push op
96
+ end
97
+
98
+ protected
99
+ def check_entity_key(key)
100
+ raise ArgumentError, "Only allowed to perform a single operation per entity, and there is already a operation registered in this batch for the key: #{key}." if entity_keys.include? key
101
+ entity_keys.push key
102
+ end
103
+
104
+ public
105
+ def parse_response(response)
106
+ responses = BatchResponse.parse response.body, (!operations.empty? && operations[0][:method] == :get)
107
+ new_responses = []
108
+
109
+ (0..responses.length - 1).each { |index|
110
+ operation = operations[index]
111
+ response = responses[index]
112
+
113
+ if response[:status_code].to_i > 299
114
+ # failed
115
+ error = Azure::Core::Http::HTTPError.new(ResponseWrapper.new(response.merge(uri: operation[:uri])))
116
+ error.description = response[:message] if (error.description || "").strip == ""
117
+ raise error
118
+ else
119
+ # success
120
+ case operation[:method]
121
+ when :post, :get
122
+ # entity from body
123
+ entity = Serialization.entity_from_json(response[:body])
124
+
125
+ entity.etag = response[:headers]["etag"] if entity.etag.nil?
126
+
127
+ new_responses.push entity
128
+ when :put, :merge
129
+ # etag from headers
130
+ new_responses.push response[:headers]["etag"]
131
+ when :delete
132
+ # true
133
+ new_responses.push nil
134
+ end
135
+ end
136
+ }
137
+
138
+ new_responses
139
+ end
140
+
141
+ public
142
+ def to_body(table_service)
143
+ body = ""
144
+ body.define_singleton_method(:add_line) do |a| self << (a || nil) + "\n" end
145
+
146
+ is_get = true if !operations.empty? && operations[0][:method] == :get
147
+
148
+ body.add_line "--#{batch_id}"
149
+ body.add_line "Content-Type: multipart/mixed; boundary=#{changeset_id}" unless is_get
150
+ body.add_line "" unless is_get
151
+
152
+ operations.each { |op|
153
+ uri = table_service.entities_uri(@table, @partition, op[:row_key])
154
+ body.add_line "--#{changeset_id}" unless is_get
155
+ body.add_line "Content-Type: application/http"
156
+ body.add_line "Content-Transfer-Encoding: binary"
157
+ body.add_line ""
158
+ body.add_line "#{op[:method].to_s.upcase} #{uri} HTTP/1.1"
159
+
160
+ if op[:headers]
161
+ op[:headers].each { |k, v|
162
+ body.add_line "#{k}: #{v}"
163
+ }
164
+ end
165
+
166
+ if op[:body]
167
+ body.add_line "Content-Length: #{op[:body].bytesize}"
168
+ body.add_line ""
169
+ body.add_line op[:body]
170
+ else
171
+ body.add_line ""
172
+ end
173
+
174
+ }
175
+ body.add_line "--#{changeset_id}--" unless is_get
176
+ body.add_line "--#{batch_id}--"
177
+ end
178
+
179
+ # Public: Inserts new entity to the table.
180
+ #
181
+ # ==== Attributes
182
+ #
183
+ # * +row_key+ - String. The row key
184
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
185
+ # * +options+ - Hash. Optional parameters.
186
+ #
187
+ # ==== Options
188
+ #
189
+ # Accepted key/value pairs in options parameter are:
190
+ # * +:accept+ - String. Specifies the accepted content-type of the response payload. Possible values are:
191
+ # :no_meta
192
+ # :min_meta
193
+ # :full_meta
194
+ # * +:prefer+ - String. Specifies whether the response should include the inserted entity in the payload. Possible values are:
195
+ # Azure::Storage::Common::HeaderConstants::PREFER_CONTENT
196
+ # Azure::Storage::Common::HeaderConstants::PREFER_NO_CONTENT
197
+ #
198
+ # See http://msdn.microsoft.com/en-us/library/azure/dd179433
199
+ public
200
+ def insert(row_key, entity_values, options = {})
201
+ check_entity_key(row_key)
202
+
203
+ headers = { Azure::Storage::Common::HeaderConstants::ACCEPT => Serialization.get_accept_string(options[:accept]) }
204
+ headers[Azure::Storage::Common::HeaderConstants::PREFER] = options[:prefer] unless options[:prefer].nil?
205
+
206
+ body = Serialization.hash_to_json({
207
+ "PartitionKey" => partition,
208
+ "RowKey" => row_key
209
+ }.merge(entity_values)
210
+ )
211
+
212
+ add_operation(:post, nil, body, headers)
213
+ self
214
+ end
215
+
216
+ # Public: Gets entity from the table.
217
+ #
218
+ # ==== Attributes
219
+ #
220
+ # * +row_key+ - String. The row key
221
+ # * +options+ - Hash. Optional parameters.
222
+ #
223
+ # ==== Options
224
+ #
225
+ # Accepted key/value pairs in options parameter are:
226
+ # * +:accept+ - String. Specifies the accepted content-type of the response payload. Possible values are:
227
+ # :no_meta
228
+ # :min_meta
229
+ # :full_meta
230
+ #
231
+ # See http://msdn.microsoft.com/en-us/library/azure/dd179433
232
+ public
233
+ def get(row_key, options = {})
234
+ check_entity_key(row_key)
235
+
236
+ headers = { Azure::Storage::Common::HeaderConstants::ACCEPT => Serialization.get_accept_string(options[:accept]) }
237
+
238
+ add_operation(:get, row_key, nil, headers)
239
+ self
240
+ end
241
+
242
+ # Public: Updates an existing entity in a table. The Update Entity operation replaces
243
+ # the entire entity and can be used to remove properties.
244
+ #
245
+ # ==== Attributes
246
+ #
247
+ # * +row_key+ - String. The row key
248
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
249
+ # * +options+ - Hash. Optional parameters.
250
+ #
251
+ # ==== Options
252
+ #
253
+ # Accepted key/value pairs in options parameter are:
254
+ # * :if_match - String. A matching condition which is required for update (optional, Default="*")
255
+ # * :create_if_not_exists - Boolean. If true, and partition_key and row_key do not reference and existing entity,
256
+ # that entity will be inserted. If false, the operation will fail. (optional, Default=false)
257
+ # * +:accept+ - String. Specifies the accepted content-type of the response payload. Possible values are:
258
+ # :no_meta
259
+ # :min_meta
260
+ # :full_meta
261
+ #
262
+ # See http://msdn.microsoft.com/en-us/library/azure/dd179427
263
+ public
264
+ def update(row_key, entity_values, options = {})
265
+ check_entity_key(row_key)
266
+
267
+ headers = { Azure::Storage::Common::HeaderConstants::ACCEPT => Serialization.get_accept_string(options[:accept]) }
268
+ headers["If-Match"] = options[:if_match] || "*" unless options[:create_if_not_exists]
269
+
270
+ body = Serialization.hash_to_json(entity_values)
271
+
272
+ add_operation(:put, row_key, body, headers)
273
+ self
274
+ end
275
+
276
+ # Public: Updates an existing entity by updating the entity's properties. This operation
277
+ # does not replace the existing entity, as the update_entity operation does.
278
+ #
279
+ # ==== Attributes
280
+ #
281
+ # * +row_key+ - String. The row key
282
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
283
+ # * +options+ - Hash. Optional parameters.
284
+ #
285
+ # ==== Options
286
+ #
287
+ # Accepted key/value pairs in options parameter are:
288
+ # * +if_match+ - String. A matching condition which is required for update (optional, Default="*")
289
+ # * +create_if_not_exists+ - Boolean. If true, and partition_key and row_key do not reference and existing entity,
290
+ # that entity will be inserted. If false, the operation will fail. (optional, Default=false)
291
+ # * +:accept+ - String. Specifies the accepted content-type of the response payload. Possible values are:
292
+ # :no_meta
293
+ # :min_meta
294
+ # :full_meta
295
+ #
296
+ # See http://msdn.microsoft.com/en-us/library/azure/dd179392
297
+ public
298
+ def merge(row_key, entity_values, options = {})
299
+ check_entity_key(row_key)
300
+
301
+ headers = { Azure::Storage::Common::HeaderConstants::ACCEPT => Serialization.get_accept_string(options[:accept]) }
302
+ headers["If-Match"] = options[:if_match] || "*" unless options[:create_if_not_exists]
303
+
304
+ body = Serialization.hash_to_json(entity_values)
305
+
306
+ add_operation(:merge, row_key, body, headers)
307
+ self
308
+ end
309
+
310
+ # Public: Inserts or updates an existing entity within a table by merging new property values into the entity.
311
+ #
312
+ # ==== Attributes
313
+ #
314
+ # * +row_key+ - String. The row key
315
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
316
+ #
317
+ # See http://msdn.microsoft.com/en-us/library/azure/hh452241
318
+ public
319
+ def insert_or_merge(row_key, entity_values)
320
+ merge(row_key, entity_values, create_if_not_exists: true)
321
+ self
322
+ end
323
+
324
+ # Public: Inserts or updates a new entity into a table.
325
+ #
326
+ # ==== Attributes
327
+ #
328
+ # * +row_key+ - String. The row key
329
+ # * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
330
+ #
331
+ # See http://msdn.microsoft.com/en-us/library/azure/hh452242
332
+ public
333
+ def insert_or_replace(row_key, entity_values)
334
+ update(row_key, entity_values, create_if_not_exists: true)
335
+ self
336
+ end
337
+
338
+ # Public: Deletes an existing entity in the table.
339
+ #
340
+ # ==== Attributes
341
+ #
342
+ # * +row_key+ - String. The row key
343
+ # * +options+ - Hash. Optional parameters.
344
+ #
345
+ # ==== Options
346
+ #
347
+ # Accepted key/value pairs in options parameter are:
348
+ # * +if_match+ - String. A matching condition which is required for update (optional, Default="*")
349
+ # * +:accept+ - String. Specifies the accepted content-type of the response payload. Possible values are:
350
+ # :no_meta
351
+ # :min_meta
352
+ # :full_meta
353
+ #
354
+ # See http://msdn.microsoft.com/en-us/library/azure/dd135727
355
+ public
356
+ def delete(row_key, options = {})
357
+ headers = {
358
+ Azure::Storage::Common::HeaderConstants::ACCEPT => Serialization.get_accept_string(options[:accept]),
359
+ "If-Match" => options[:if_match] || "*"
360
+ }
361
+ add_operation(:delete, row_key, nil, headers)
362
+ self
363
+ end
364
+ end
365
+ end
366
+ end