azure-storage 0.10.0.preview
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/azure/storage.rb +58 -0
- data/lib/azure/storage/autoload.rb +71 -0
- data/lib/azure/storage/blob/append.rb +154 -0
- data/lib/azure/storage/blob/blob.rb +821 -0
- data/lib/azure/storage/blob/blob_service.rb +510 -0
- data/lib/azure/storage/blob/block.rb +264 -0
- data/lib/azure/storage/blob/container.rb +552 -0
- data/lib/azure/storage/blob/page.rb +380 -0
- data/lib/azure/storage/blob/serialization.rb +297 -0
- data/lib/azure/storage/client.rb +185 -0
- data/lib/azure/storage/configurable.rb +137 -0
- data/lib/azure/storage/core.rb +33 -0
- data/lib/azure/storage/core/auth/shared_access_signature.rb +27 -0
- data/lib/azure/storage/core/auth/shared_access_signature_generator.rb +194 -0
- data/lib/azure/storage/core/auth/shared_access_signature_signer.rb +49 -0
- data/lib/azure/storage/core/auth/shared_key.rb +125 -0
- data/lib/azure/storage/core/auth/shared_key_lite.rb +55 -0
- data/lib/azure/storage/core/auth/signer.rb +60 -0
- data/lib/azure/storage/core/autoload.rb +35 -0
- data/lib/azure/storage/core/client_options.rb +334 -0
- data/lib/azure/storage/core/client_options_error.rb +39 -0
- data/lib/azure/storage/core/constants.rb +1077 -0
- data/lib/azure/storage/core/error.rb +47 -0
- data/lib/azure/storage/core/filtered_service.rb +54 -0
- data/lib/azure/storage/core/http/debug_filter.rb +45 -0
- data/lib/azure/storage/core/http/http_error.rb +95 -0
- data/lib/azure/storage/core/http/http_filter.rb +62 -0
- data/lib/azure/storage/core/http/http_request.rb +182 -0
- data/lib/azure/storage/core/http/http_response.rb +105 -0
- data/lib/azure/storage/core/http/retry_policy.rb +83 -0
- data/lib/azure/storage/core/http/signer_filter.rb +42 -0
- data/lib/azure/storage/core/http_client.rb +63 -0
- data/lib/azure/storage/core/service.rb +55 -0
- data/lib/azure/storage/core/signed_service.rb +54 -0
- data/lib/azure/storage/core/sr.rb +83 -0
- data/lib/azure/storage/core/utility.rb +254 -0
- data/lib/azure/storage/queue/message.rb +39 -0
- data/lib/azure/storage/queue/queue.rb +37 -0
- data/lib/azure/storage/queue/queue_service.rb +580 -0
- data/lib/azure/storage/queue/serialization.rb +113 -0
- data/lib/azure/storage/service/access_policy.rb +35 -0
- data/lib/azure/storage/service/cors.rb +36 -0
- data/lib/azure/storage/service/cors_rule.rb +46 -0
- data/lib/azure/storage/service/enumeration_results.rb +30 -0
- data/lib/azure/storage/service/logging.rb +45 -0
- data/lib/azure/storage/service/metrics.rb +43 -0
- data/lib/azure/storage/service/retention_policy.rb +35 -0
- data/lib/azure/storage/service/serialization.rb +308 -0
- data/lib/azure/storage/service/signed_identifier.rb +39 -0
- data/lib/azure/storage/service/storage_service.rb +131 -0
- data/lib/azure/storage/service/storage_service_properties.rb +46 -0
- data/lib/azure/storage/table/auth/shared_key.rb +68 -0
- data/lib/azure/storage/table/auth/shared_key_lite.rb +53 -0
- data/lib/azure/storage/table/batch.rb +339 -0
- data/lib/azure/storage/table/batch_response.rb +127 -0
- data/lib/azure/storage/table/edmtype.rb +136 -0
- data/lib/azure/storage/table/entity.rb +40 -0
- data/lib/azure/storage/table/guid.rb +33 -0
- data/lib/azure/storage/table/query.rb +121 -0
- data/lib/azure/storage/table/serialization.rb +117 -0
- data/lib/azure/storage/table/table_service.rb +571 -0
- data/lib/azure/storage/version.rb +46 -0
- metadata +329 -0
@@ -0,0 +1,39 @@
|
|
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 'azure/storage/service/access_policy'
|
25
|
+
|
26
|
+
module Azure::Storage
|
27
|
+
module Service
|
28
|
+
class SignedIdentifier
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@access_policy = AccessPolicy.new
|
32
|
+
yield self if block_given?
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :id
|
36
|
+
attr_accessor :access_policy
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,131 @@
|
|
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
|
+
|
25
|
+
require 'azure/storage/core/signed_service'
|
26
|
+
require 'azure/storage/core'
|
27
|
+
require 'azure/storage/service/storage_service_properties'
|
28
|
+
|
29
|
+
module Azure::Storage
|
30
|
+
module Service
|
31
|
+
# A base class for StorageService implementations
|
32
|
+
class StorageService < Azure::Core::SignedService
|
33
|
+
# Create a new instance of the StorageService
|
34
|
+
#
|
35
|
+
# @param signer [Azure::Core::Auth::Signer] An implementation of Signer used for signing requests.
|
36
|
+
# (optional, Default=Azure::Storage::Auth::SharedKey.new)
|
37
|
+
# @param account_name [String] The account name (optional, Default=Azure.config.storage_account_name)
|
38
|
+
# @param options [Azure::Storage::Configurable] the client configuration context
|
39
|
+
def initialize(signer=Auth::SharedKey.new, account_name=nil, options = {})
|
40
|
+
super(signer, account_name, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def call(method, uri, body=nil, headers={})
|
44
|
+
super(method, uri, body, StorageService.service_properties_headers.merge(headers))
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: Get Storage Service properties
|
48
|
+
#
|
49
|
+
# See http://msdn.microsoft.com/en-us/library/azure/hh452239
|
50
|
+
# See http://msdn.microsoft.com/en-us/library/azure/hh452243
|
51
|
+
#
|
52
|
+
# Returns a Hash with the service properties or nil if the operation failed
|
53
|
+
def get_service_properties
|
54
|
+
uri = service_properties_uri
|
55
|
+
response = call(:get, uri)
|
56
|
+
Serialization.service_properties_from_xml response.body
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: Set Storage Service properties
|
60
|
+
#
|
61
|
+
# service_properties - An instance of Azure::Storage::Service::StorageServiceProperties
|
62
|
+
#
|
63
|
+
# See http://msdn.microsoft.com/en-us/library/azure/hh452235
|
64
|
+
# See http://msdn.microsoft.com/en-us/library/azure/hh452232
|
65
|
+
#
|
66
|
+
# Returns boolean indicating success.
|
67
|
+
def set_service_properties(service_properties)
|
68
|
+
body = Serialization.service_properties_to_xml service_properties
|
69
|
+
uri = service_properties_uri
|
70
|
+
call(:put, uri, body)
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# Public: Generate the URI for the service properties
|
75
|
+
#
|
76
|
+
# query - see Azure::Storage::Services::GetServiceProperties#call documentation.
|
77
|
+
#
|
78
|
+
# Returns a URI.
|
79
|
+
def service_properties_uri(query={})
|
80
|
+
query.update(restype: 'service', comp: 'properties')
|
81
|
+
generate_uri('', query)
|
82
|
+
end
|
83
|
+
|
84
|
+
class << self
|
85
|
+
# Adds metadata properties to header hash with required prefix
|
86
|
+
#
|
87
|
+
# metadata - A Hash of metadata name/value pairs
|
88
|
+
# headers - A Hash of HTTP headers
|
89
|
+
def add_metadata_to_headers(metadata, headers)
|
90
|
+
if metadata
|
91
|
+
metadata.each do |key, value|
|
92
|
+
headers["x-ms-meta-#{key}"] = value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Adds a value to the Hash object
|
98
|
+
#
|
99
|
+
# object - A Hash object
|
100
|
+
# key - The key name
|
101
|
+
# value - The value
|
102
|
+
def with_value(object, key, value)
|
103
|
+
object[key] = value if value
|
104
|
+
end
|
105
|
+
|
106
|
+
# Adds a header with the value
|
107
|
+
#
|
108
|
+
# headers - A Hash of HTTP headers
|
109
|
+
# name - The header name
|
110
|
+
# value - The value
|
111
|
+
alias with_header with_value
|
112
|
+
|
113
|
+
# Adds a query parameter
|
114
|
+
#
|
115
|
+
# query - A Hash of HTTP query
|
116
|
+
# name - The parameter name
|
117
|
+
# value - The value
|
118
|
+
alias with_query with_value
|
119
|
+
|
120
|
+
# Declares a default hash object for request headers
|
121
|
+
def service_properties_headers
|
122
|
+
{
|
123
|
+
'x-ms-version' => Azure::Storage::Default::STG_VERSION,
|
124
|
+
'User-Agent' => Azure::Storage::Default::USER_AGENT
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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 'azure/storage/service/logging'
|
25
|
+
require 'azure/storage/service/metrics'
|
26
|
+
require 'azure/storage/service/cors'
|
27
|
+
|
28
|
+
module Azure::Storage
|
29
|
+
module Service
|
30
|
+
class StorageServiceProperties
|
31
|
+
def initialize
|
32
|
+
@logging = Logging.new
|
33
|
+
@hour_metrics = Metrics.new
|
34
|
+
@minute_metrics = Metrics.new
|
35
|
+
@cors = Cors.new
|
36
|
+
yield self if block_given?
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_accessor :logging
|
40
|
+
attr_accessor :hour_metrics
|
41
|
+
attr_accessor :minute_metrics
|
42
|
+
attr_accessor :cors
|
43
|
+
attr_accessor :default_service_version
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,68 @@
|
|
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 'cgi'
|
25
|
+
require 'azure/storage/core/auth/signer'
|
26
|
+
|
27
|
+
module Azure::Storage
|
28
|
+
module Table
|
29
|
+
module Auth
|
30
|
+
class SharedKey < Azure::Storage::Auth::SharedKey
|
31
|
+
# The account name
|
32
|
+
attr :account_name
|
33
|
+
|
34
|
+
# Generate the string to sign.
|
35
|
+
#
|
36
|
+
# @param method [Symbol] The HTTP request method.
|
37
|
+
# @param uri [URI] The URI of the request we're signing.
|
38
|
+
# @param headers [Hash] The HTTP request headers.
|
39
|
+
#
|
40
|
+
# Returns a plain text string.
|
41
|
+
def signable_string(method, uri, headers)
|
42
|
+
[
|
43
|
+
method.to_s.upcase,
|
44
|
+
headers.fetch('Content-MD5', ''),
|
45
|
+
headers.fetch('Content-Type', ''),
|
46
|
+
headers.fetch('Date') { headers.fetch('x-ms-date') },
|
47
|
+
canonicalized_resource(uri)
|
48
|
+
].join("\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
# Calculate the Canonicalized Resource string for a request.
|
52
|
+
#
|
53
|
+
# @param uri [URI] The request's URI.
|
54
|
+
#
|
55
|
+
# @return [String] with the canonicalized resource.
|
56
|
+
def canonicalized_resource(uri)
|
57
|
+
resource = "/#{account_name}#{uri.path}"
|
58
|
+
|
59
|
+
comp = CGI.parse(uri.query.to_s).fetch('comp', nil)
|
60
|
+
resource = [resource, 'comp=' + comp[0]].join('?') if comp
|
61
|
+
|
62
|
+
resource
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,53 @@
|
|
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 'azure/storage/table/auth/shared_key'
|
25
|
+
|
26
|
+
module Azure::Storage
|
27
|
+
module Table
|
28
|
+
module Auth
|
29
|
+
class SharedKeyLite < SharedKey
|
30
|
+
# Public: The name of the strategy.
|
31
|
+
#
|
32
|
+
# Returns a String.
|
33
|
+
def name
|
34
|
+
'SharedKeyLite'
|
35
|
+
end
|
36
|
+
|
37
|
+
# Generate the string to sign.
|
38
|
+
#
|
39
|
+
# verb - The HTTP request method.
|
40
|
+
# uri - The URI of the request we're signing.
|
41
|
+
# headers - A Hash of HTTP request headers.
|
42
|
+
#
|
43
|
+
# Returns a plain text string.
|
44
|
+
def signable_string(method, uri, headers)
|
45
|
+
[
|
46
|
+
headers.fetch('Date') { headers.fetch('x-ms-date') },
|
47
|
+
canonicalized_resource(uri)
|
48
|
+
].join("\n")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,339 @@
|
|
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 'uuid'
|
25
|
+
|
26
|
+
require 'azure/storage/table/serialization'
|
27
|
+
require 'azure/storage/table/table_service'
|
28
|
+
require 'azure/storage/table/batch_response'
|
29
|
+
require 'azure/storage/core/http/http_error'
|
30
|
+
|
31
|
+
module Azure::Storage
|
32
|
+
module Table
|
33
|
+
# Represents a batch of table operations.
|
34
|
+
#
|
35
|
+
# Example usage (block syntax):
|
36
|
+
#
|
37
|
+
# results = Batch.new "table", "partition" do
|
38
|
+
# insert "row1", {"meta"=>"data"}
|
39
|
+
# insert "row2", {"meta"=>"data"}
|
40
|
+
# end.execute
|
41
|
+
#
|
42
|
+
# which is equivalent to (fluent syntax):
|
43
|
+
#
|
44
|
+
# results = Batch.new("table", "partition")
|
45
|
+
# .insert("row1", {"meta"=>"data"})
|
46
|
+
# .insert("row2", {"meta"=>"data"})
|
47
|
+
# .execute
|
48
|
+
#
|
49
|
+
# which is equivalent to (as class):
|
50
|
+
#
|
51
|
+
# svc = TableSerice.new
|
52
|
+
#
|
53
|
+
# batch = Batch.new "table", "partition"
|
54
|
+
# batch.insert "row1", {"meta"=>"data"}
|
55
|
+
# batch.insert "row2", {"meta"=>"data"}
|
56
|
+
#
|
57
|
+
# results = svc.execute_batch batch
|
58
|
+
#
|
59
|
+
class Batch
|
60
|
+
def initialize(table, partition, &block)
|
61
|
+
@table = table
|
62
|
+
@partition = partition
|
63
|
+
@operations = []
|
64
|
+
@entity_keys = []
|
65
|
+
@table_service = Azure::Storage::Table::TableService.new
|
66
|
+
uuid = UUID.new
|
67
|
+
@batch_id = "batch_" + uuid.generate
|
68
|
+
@changeset_id = "changeset_" + uuid.generate
|
69
|
+
|
70
|
+
self.instance_eval(&block) if block_given?
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
attr_reader :table
|
75
|
+
attr_reader :partition
|
76
|
+
attr_reader :table_service
|
77
|
+
|
78
|
+
attr_accessor :operations
|
79
|
+
attr_accessor :entity_keys
|
80
|
+
attr_accessor :changeset_id
|
81
|
+
|
82
|
+
public
|
83
|
+
attr_accessor :batch_id
|
84
|
+
|
85
|
+
protected
|
86
|
+
def execute
|
87
|
+
@table_service.execute_batch(self)
|
88
|
+
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
class ResponseWrapper
|
92
|
+
def initialize(hash)
|
93
|
+
@hash = hash
|
94
|
+
end
|
95
|
+
|
96
|
+
def uri
|
97
|
+
@hash[:uri]
|
98
|
+
end
|
99
|
+
|
100
|
+
def status_code
|
101
|
+
@hash[:status_code].to_i
|
102
|
+
end
|
103
|
+
|
104
|
+
def body
|
105
|
+
@hash[:body]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
def add_operation(method, uri, body=nil, headers=nil)
|
111
|
+
op = {
|
112
|
+
:method => method,
|
113
|
+
:uri => uri,
|
114
|
+
:body => body,
|
115
|
+
:headers => headers
|
116
|
+
}
|
117
|
+
operations.push op
|
118
|
+
end
|
119
|
+
|
120
|
+
protected
|
121
|
+
def check_entity_key(key)
|
122
|
+
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
|
123
|
+
entity_keys.push key
|
124
|
+
end
|
125
|
+
|
126
|
+
public
|
127
|
+
def parse_response(response)
|
128
|
+
responses = BatchResponse.parse response.body
|
129
|
+
new_responses = []
|
130
|
+
|
131
|
+
(0..responses.length-1).each { |index|
|
132
|
+
operation = operations[index]
|
133
|
+
response = responses[index]
|
134
|
+
|
135
|
+
if response[:status_code].to_i > 299
|
136
|
+
# failed
|
137
|
+
error = Azure::Core::Http::HTTPError.new(ResponseWrapper.new(response.merge({:uri=>operation[:uri]})))
|
138
|
+
error.description = response[:message] if (error.description || '').strip == ''
|
139
|
+
raise error
|
140
|
+
else
|
141
|
+
# success
|
142
|
+
case operation[:method]
|
143
|
+
when :post
|
144
|
+
# entity from body
|
145
|
+
result = Azure::Storage::Table::Serialization.hash_from_entry_xml(response[:body])
|
146
|
+
|
147
|
+
entity = Azure::Storage::Table::Entity.new
|
148
|
+
entity.table = table
|
149
|
+
entity.updated = result[:updated]
|
150
|
+
entity.etag = response[:headers]["etag"] || result[:etag]
|
151
|
+
entity.properties = result[:properties]
|
152
|
+
|
153
|
+
new_responses.push entity
|
154
|
+
when :put, :merge
|
155
|
+
# etag from headers
|
156
|
+
new_responses.push response[:headers]["etag"]
|
157
|
+
when :delete
|
158
|
+
# true
|
159
|
+
new_responses.push nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
}
|
163
|
+
|
164
|
+
new_responses
|
165
|
+
end
|
166
|
+
|
167
|
+
public
|
168
|
+
def to_body
|
169
|
+
body = ""
|
170
|
+
body.define_singleton_method(:add_line) do |a| self << (a||nil) + "\n" end
|
171
|
+
|
172
|
+
body.add_line "--#{batch_id}"
|
173
|
+
body.add_line "Content-Type: multipart/mixed; boundary=#{changeset_id}"
|
174
|
+
body.add_line ""
|
175
|
+
|
176
|
+
content_id = 1
|
177
|
+
operations.each { |op|
|
178
|
+
body.add_line "--#{changeset_id}"
|
179
|
+
body.add_line "Content-Type: application/http"
|
180
|
+
body.add_line "Content-Transfer-Encoding: binary"
|
181
|
+
body.add_line ""
|
182
|
+
body.add_line "#{op[:method].to_s.upcase} #{op[:uri]} HTTP/1.1"
|
183
|
+
body.add_line "Content-ID: #{content_id}"
|
184
|
+
|
185
|
+
if op[:headers]
|
186
|
+
op[:headers].each { |k,v|
|
187
|
+
body.add_line "#{k}: #{v}"
|
188
|
+
}
|
189
|
+
end
|
190
|
+
|
191
|
+
if op[:body]
|
192
|
+
body.add_line "Content-Type: application/atom+xml;type=entry"
|
193
|
+
body.add_line "Content-Length: #{op[:body].bytesize.to_s}"
|
194
|
+
body.add_line ""
|
195
|
+
body.add_line op[:body]
|
196
|
+
else
|
197
|
+
body.add_line ""
|
198
|
+
end
|
199
|
+
|
200
|
+
content_id += 1
|
201
|
+
}
|
202
|
+
body.add_line "--#{changeset_id}--"
|
203
|
+
body.add_line "--#{batch_id}--"
|
204
|
+
end
|
205
|
+
|
206
|
+
# Public: Inserts new entity to the table.
|
207
|
+
#
|
208
|
+
# ==== Attributes
|
209
|
+
#
|
210
|
+
# * +row_key+ - String. The row key
|
211
|
+
# * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
|
212
|
+
#
|
213
|
+
# See http://msdn.microsoft.com/en-us/library/azure/dd179433
|
214
|
+
public
|
215
|
+
def insert(row_key, entity_values)
|
216
|
+
check_entity_key(row_key)
|
217
|
+
|
218
|
+
body = Azure::Storage::Table::Serialization.hash_to_entry_xml({
|
219
|
+
"PartitionKey" => partition,
|
220
|
+
"RowKey" => row_key
|
221
|
+
}.merge(entity_values) ).to_xml
|
222
|
+
|
223
|
+
add_operation(:post, @table_service.entities_uri(table), body)
|
224
|
+
self
|
225
|
+
end
|
226
|
+
|
227
|
+
# Public: Updates an existing entity in a table. The Update Entity operation replaces
|
228
|
+
# the entire entity and can be used to remove properties.
|
229
|
+
#
|
230
|
+
# ==== Attributes
|
231
|
+
#
|
232
|
+
# * +row_key+ - String. The row key
|
233
|
+
# * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
|
234
|
+
# * +options+ - Hash. Optional parameters.
|
235
|
+
#
|
236
|
+
# ==== Options
|
237
|
+
#
|
238
|
+
# Accepted key/value pairs in options parameter are:
|
239
|
+
# * :if_match - String. A matching condition which is required for update (optional, Default="*")
|
240
|
+
# * :create_if_not_exists - Boolean. If true, and partition_key and row_key do not reference and existing entity,
|
241
|
+
# that entity will be inserted. If false, the operation will fail. (optional, Default=false)
|
242
|
+
#
|
243
|
+
# See http://msdn.microsoft.com/en-us/library/azure/dd179427
|
244
|
+
public
|
245
|
+
def update(row_key, entity_values, options={})
|
246
|
+
check_entity_key(row_key)
|
247
|
+
|
248
|
+
uri = @table_service.entities_uri(table, partition, row_key)
|
249
|
+
|
250
|
+
headers = {}
|
251
|
+
headers["If-Match"] = options[:if_match] || "*" unless options[:create_if_not_exists]
|
252
|
+
|
253
|
+
body = Azure::Storage::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
|
254
|
+
|
255
|
+
add_operation(:put, uri, body, headers)
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
# Public: Updates an existing entity by updating the entity's properties. This operation
|
260
|
+
# does not replace the existing entity, as the update_entity operation does.
|
261
|
+
#
|
262
|
+
# ==== Attributes
|
263
|
+
#
|
264
|
+
# * +row_key+ - String. The row key
|
265
|
+
# * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
|
266
|
+
# * +options+ - Hash. Optional parameters.
|
267
|
+
#
|
268
|
+
# ==== Options
|
269
|
+
#
|
270
|
+
# Accepted key/value pairs in options parameter are:
|
271
|
+
# * +if_match+ - String. A matching condition which is required for update (optional, Default="*")
|
272
|
+
# * +create_if_not_exists+ - Boolean. If true, and partition_key and row_key do not reference and existing entity,
|
273
|
+
# that entity will be inserted. If false, the operation will fail. (optional, Default=false)
|
274
|
+
#
|
275
|
+
# See http://msdn.microsoft.com/en-us/library/azure/dd179392
|
276
|
+
public
|
277
|
+
def merge(row_key, entity_values, options={})
|
278
|
+
check_entity_key(row_key)
|
279
|
+
|
280
|
+
uri = @table_service.entities_uri(table, partition, row_key)
|
281
|
+
|
282
|
+
headers = {}
|
283
|
+
headers["If-Match"] = options[:if_match] || "*" unless options[:create_if_not_exists]
|
284
|
+
|
285
|
+
body = Azure::Storage::Table::Serialization.hash_to_entry_xml(entity_values).to_xml
|
286
|
+
|
287
|
+
add_operation(:merge, uri, body, headers)
|
288
|
+
self
|
289
|
+
end
|
290
|
+
|
291
|
+
# Public: Inserts or updates an existing entity within a table by merging new property values into the entity.
|
292
|
+
#
|
293
|
+
# ==== Attributes
|
294
|
+
#
|
295
|
+
# * +row_key+ - String. The row key
|
296
|
+
# * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
|
297
|
+
#
|
298
|
+
# See http://msdn.microsoft.com/en-us/library/azure/hh452241
|
299
|
+
public
|
300
|
+
def insert_or_merge(row_key, entity_values)
|
301
|
+
merge(row_key, entity_values, { :create_if_not_exists => true })
|
302
|
+
self
|
303
|
+
end
|
304
|
+
|
305
|
+
# Public: Inserts or updates a new entity into a table.
|
306
|
+
#
|
307
|
+
# ==== Attributes
|
308
|
+
#
|
309
|
+
# * +row_key+ - String. The row key
|
310
|
+
# * +entity_values+ - Hash. A hash of the name/value pairs for the entity.
|
311
|
+
#
|
312
|
+
# See http://msdn.microsoft.com/en-us/library/azure/hh452242
|
313
|
+
public
|
314
|
+
def insert_or_replace(row_key, entity_values)
|
315
|
+
update(row_key, entity_values, { :create_if_not_exists => true })
|
316
|
+
self
|
317
|
+
end
|
318
|
+
|
319
|
+
# Public: Deletes an existing entity in the table.
|
320
|
+
#
|
321
|
+
# ==== Attributes
|
322
|
+
#
|
323
|
+
# * +row_key+ - String. The row key
|
324
|
+
# * +options+ - Hash. Optional parameters.
|
325
|
+
#
|
326
|
+
# ==== Options
|
327
|
+
#
|
328
|
+
# Accepted key/value pairs in options parameter are:
|
329
|
+
# * +if_match+ - String. A matching condition which is required for update (optional, Default="*")
|
330
|
+
#
|
331
|
+
# See http://msdn.microsoft.com/en-us/library/azure/dd135727
|
332
|
+
public
|
333
|
+
def delete(row_key, options={})
|
334
|
+
add_operation(:delete, @table_service.entities_uri(table, partition, row_key), nil, {"If-Match"=> options[:if_match] || "*"})
|
335
|
+
self
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|