azure-storage-table 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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