azure-storage 0.13.0.preview → 0.14.0.preview
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.
- checksums.yaml +4 -4
- data/lib/azure/storage.rb +14 -13
- data/lib/azure/storage/autoload.rb +31 -31
- data/lib/azure/storage/blob/append.rb +43 -41
- data/lib/azure/storage/blob/blob.rb +150 -147
- data/lib/azure/storage/blob/blob_service.rb +186 -184
- data/lib/azure/storage/blob/block.rb +56 -56
- data/lib/azure/storage/blob/container.rb +93 -92
- data/lib/azure/storage/blob/page.rb +187 -104
- data/lib/azure/storage/blob/serialization.rb +32 -18
- data/lib/azure/storage/client.rb +18 -17
- data/lib/azure/storage/client_options.rb +192 -193
- data/lib/azure/storage/client_options_error.rb +5 -5
- data/lib/azure/storage/configurable.rb +39 -39
- data/lib/azure/storage/core.rb +6 -4
- data/lib/azure/storage/core/auth/shared_access_signature.rb +5 -3
- data/lib/azure/storage/core/auth/shared_access_signature_generator.rb +34 -33
- data/lib/azure/storage/core/auth/shared_access_signature_signer.rb +5 -5
- data/lib/azure/storage/core/auth/shared_key.rb +17 -15
- data/lib/azure/storage/core/autoload.rb +15 -13
- data/lib/azure/storage/core/error.rb +3 -1
- data/lib/azure/storage/core/filter/exponential_retry_filter.rb +13 -11
- data/lib/azure/storage/core/filter/linear_retry_filter.rb +10 -8
- data/lib/azure/storage/core/filter/retry_filter.rb +30 -29
- data/lib/azure/storage/core/http_client.rb +18 -16
- data/lib/azure/storage/core/sr.rb +50 -48
- data/lib/azure/storage/core/utility.rb +19 -17
- data/lib/azure/storage/default.rb +371 -361
- data/lib/azure/storage/file/directory.rb +36 -31
- data/lib/azure/storage/file/file.rb +103 -100
- data/lib/azure/storage/file/file_service.rb +42 -40
- data/lib/azure/storage/file/serialization.rb +9 -6
- data/lib/azure/storage/file/share.rb +48 -46
- data/lib/azure/storage/queue/message.rb +3 -1
- data/lib/azure/storage/queue/queue.rb +3 -2
- data/lib/azure/storage/queue/queue_service.rb +152 -151
- data/lib/azure/storage/queue/serialization.rb +7 -5
- data/lib/azure/storage/service/access_policy.rb +3 -1
- data/lib/azure/storage/service/cors.rb +4 -2
- data/lib/azure/storage/service/cors_rule.rb +3 -1
- data/lib/azure/storage/service/enumeration_results.rb +3 -1
- data/lib/azure/storage/service/logging.rb +5 -3
- data/lib/azure/storage/service/metrics.rb +5 -3
- data/lib/azure/storage/service/retention_policy.rb +3 -1
- data/lib/azure/storage/service/serialization.rb +31 -30
- data/lib/azure/storage/service/signed_identifier.rb +5 -4
- data/lib/azure/storage/service/storage_service.rb +33 -32
- data/lib/azure/storage/service/storage_service_properties.rb +6 -4
- data/lib/azure/storage/table/auth/shared_key.rb +9 -8
- data/lib/azure/storage/table/batch.rb +55 -55
- data/lib/azure/storage/table/batch_response.rb +17 -17
- data/lib/azure/storage/table/edmtype.rb +9 -7
- data/lib/azure/storage/table/entity.rb +4 -3
- data/lib/azure/storage/table/guid.rb +3 -1
- data/lib/azure/storage/table/query.rb +17 -19
- data/lib/azure/storage/table/serialization.rb +14 -12
- data/lib/azure/storage/table/table_service.rb +79 -80
- data/lib/azure/storage/version.rb +7 -5
- metadata +2 -2
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#-------------------------------------------------------------------------
|
2
4
|
# # Copyright (c) Microsoft and contributors. All rights reserved.
|
3
5
|
#
|
@@ -21,13 +23,13 @@
|
|
21
23
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
24
|
# THE SOFTWARE.
|
23
25
|
#--------------------------------------------------------------------------
|
24
|
-
require
|
26
|
+
require "azure/storage/service/serialization"
|
25
27
|
|
26
|
-
require
|
27
|
-
require
|
28
|
-
require
|
28
|
+
require "azure/storage/blob/container"
|
29
|
+
require "azure/storage/blob/blob"
|
30
|
+
require "azure/storage/blob/block"
|
29
31
|
|
30
|
-
require
|
32
|
+
require "base64"
|
31
33
|
|
32
34
|
module Azure::Storage
|
33
35
|
module Blob
|
@@ -39,7 +41,7 @@ module Azure::Storage
|
|
39
41
|
expect_node("EnumerationResults", xml)
|
40
42
|
|
41
43
|
results = enumeration_results_from_xml(xml, Azure::Service::EnumerationResults.new)
|
42
|
-
|
44
|
+
|
43
45
|
return results unless (xml > "Containers").any? && ((xml > "Containers") > "Container").any?
|
44
46
|
|
45
47
|
if xml.Containers.Container.count == 0
|
@@ -61,6 +63,7 @@ module Azure::Storage
|
|
61
63
|
container.name = xml.Name.text if (xml > "Name").any?
|
62
64
|
container.properties = container_properties_from_xml(xml.Properties) if (xml > "Properties").any?
|
63
65
|
container.metadata = metadata_from_xml(xml.Metadata) if (xml > "Metadata").any?
|
66
|
+
container.public_access_level = public_access_level_from_properties_xml(xml.Properties) if (xml > "Properties").any?
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
@@ -90,7 +93,7 @@ module Azure::Storage
|
|
90
93
|
def self.container_properties_from_headers(headers)
|
91
94
|
props = {}
|
92
95
|
|
93
|
-
props[:last_modified] = headers["Last-Modified"]
|
96
|
+
props[:last_modified] = headers["Last-Modified"]
|
94
97
|
props[:etag] = headers["Etag"]
|
95
98
|
props[:lease_status] = headers["x-ms-lease-status"]
|
96
99
|
props[:lease_state] = headers["x-ms-lease-state"]
|
@@ -103,8 +106,11 @@ module Azure::Storage
|
|
103
106
|
headers["x-ms-blob-public-access"]
|
104
107
|
end
|
105
108
|
|
109
|
+
def self.public_access_level_from_properties_xml(xml)
|
110
|
+
(xml > "PublicAccess").any? ? xml.PublicAccess.text : nil
|
111
|
+
end
|
112
|
+
|
106
113
|
def self.blob_enumeration_results_from_xml(xml)
|
107
|
-
|
108
114
|
xml = slopify(xml)
|
109
115
|
expect_node("EnumerationResults", xml)
|
110
116
|
|
@@ -142,7 +148,7 @@ module Azure::Storage
|
|
142
148
|
name = xml.Name.text if (xml > "Name").any?
|
143
149
|
name
|
144
150
|
end
|
145
|
-
|
151
|
+
|
146
152
|
def self.blob_from_xml(xml)
|
147
153
|
xml = slopify(xml)
|
148
154
|
expect_node("Blob", xml)
|
@@ -151,8 +157,11 @@ module Azure::Storage
|
|
151
157
|
blob.name = xml.Name.text if (xml > "Name").any?
|
152
158
|
blob.snapshot = xml.Snapshot.text if (xml > "Snapshot").any?
|
153
159
|
|
154
|
-
blob.properties = blob_properties_from_xml(xml.Properties) if (xml > "Properties").any?
|
155
160
|
blob.metadata = metadata_from_xml(xml.Metadata) if (xml > "Metadata").any?
|
161
|
+
if (xml > "Properties").any?
|
162
|
+
blob.properties = blob_properties_from_xml(xml.Properties)
|
163
|
+
blob.encrypted = xml.Properties.ServerEncrypted.text == "true" if (xml.Properties > "ServerEncrypted").any?
|
164
|
+
end
|
156
165
|
end
|
157
166
|
end
|
158
167
|
|
@@ -160,6 +169,8 @@ module Azure::Storage
|
|
160
169
|
Blob.new do |blob|
|
161
170
|
blob.properties = blob_properties_from_headers(headers)
|
162
171
|
blob.metadata = metadata_from_headers(headers)
|
172
|
+
blob.encrypted = headers[HeaderConstants::REQUEST_SERVER_ENCRYPTED] || headers[HeaderConstants::SERVER_ENCRYPTED]
|
173
|
+
blob.encrypted = blob.encrypted.to_s == "true" unless blob.encrypted.nil?
|
163
174
|
end
|
164
175
|
end
|
165
176
|
|
@@ -189,6 +200,7 @@ module Azure::Storage
|
|
189
200
|
props[:copy_progress] = xml.CopyProgress.text if (xml > "CopyProgress").any?
|
190
201
|
props[:copy_completion_time] = xml.CopyCompletionTime.text if (xml > "CopyCompletionTime").any?
|
191
202
|
props[:copy_status_description] = xml.CopyStatusDescription.text if (xml > "CopyStatusDescription").any?
|
203
|
+
props[:incremental_copy] = xml.IncrementalCopy.text == "true" if (xml > "IncrementalCopy").any?
|
192
204
|
|
193
205
|
props
|
194
206
|
end
|
@@ -204,12 +216,13 @@ module Azure::Storage
|
|
204
216
|
|
205
217
|
props[:content_length] = headers["x-ms-blob-content-length"] || headers["Content-Length"]
|
206
218
|
props[:content_length] = props[:content_length].to_i if props[:content_length]
|
207
|
-
|
219
|
+
|
208
220
|
props[:content_type] = headers["x-ms-blob-content-type"] || headers["Content-Type"]
|
209
221
|
props[:content_encoding] = headers["x-ms-blob-content-encoding"] || headers["Content-Encoding"]
|
210
222
|
props[:content_language] = headers["x-ms-blob-content-language"] || headers["Content-Language"]
|
211
223
|
props[:content_disposition] = headers["x-ms-blob-content-disposition"] || headers["Content-Disposition"]
|
212
224
|
props[:content_md5] = headers["x-ms-blob-content-md5"] || headers["Content-MD5"]
|
225
|
+
props[:range_md5] = headers["Content-MD5"] if headers["x-ms-blob-content-md5"] && headers["Content-MD5"]
|
213
226
|
|
214
227
|
props[:cache_control] = headers["x-ms-blob-cache-control"] || headers["Cache-Control"]
|
215
228
|
props[:sequence_number] = headers["x-ms-blob-sequence-number"].to_i if headers["x-ms-blob-sequence-number"]
|
@@ -223,15 +236,16 @@ module Azure::Storage
|
|
223
236
|
props[:copy_status_description] = headers["x-ms-copy-status-description"]
|
224
237
|
|
225
238
|
props[:accept_ranges] = headers["Accept-Ranges"].to_i if headers["Accept-Ranges"]
|
226
|
-
|
239
|
+
|
227
240
|
props[:append_offset] = headers["x-ms-blob-append-offset"].to_i if headers["x-ms-blob-append-offset"]
|
228
241
|
props[:committed_count] = headers["x-ms-blob-committed-block-count"].to_i if headers["x-ms-blob-committed-block-count"]
|
242
|
+
props[:incremental_copy] = headers["x-ms-incremental-copy"].to_s == "true" if headers["x-ms-incremental-copy"]
|
229
243
|
|
230
244
|
props
|
231
245
|
end
|
232
246
|
|
233
247
|
def self.block_list_to_xml(block_list)
|
234
|
-
builder = Nokogiri::XML::Builder.new(:
|
248
|
+
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
235
249
|
xml.BlockList {
|
236
250
|
block_list.each { |block|
|
237
251
|
encoded_id = Base64.strict_encode64(block[0])
|
@@ -253,9 +267,9 @@ module Azure::Storage
|
|
253
267
|
xml = slopify(xml)
|
254
268
|
expect_node("BlockList", xml)
|
255
269
|
|
256
|
-
block_list =
|
257
|
-
:
|
258
|
-
:
|
270
|
+
block_list = {
|
271
|
+
committed: [],
|
272
|
+
uncommitted: []
|
259
273
|
}
|
260
274
|
|
261
275
|
if ((xml > "CommittedBlocks") > "Block").any?
|
@@ -291,7 +305,7 @@ module Azure::Storage
|
|
291
305
|
end
|
292
306
|
block_list[type].push block
|
293
307
|
end
|
294
|
-
|
308
|
+
|
295
309
|
def self.page_list_from_xml(xml)
|
296
310
|
xml = slopify(xml)
|
297
311
|
expect_node("PageList", xml)
|
@@ -312,4 +326,4 @@ module Azure::Storage
|
|
312
326
|
end
|
313
327
|
end
|
314
328
|
end
|
315
|
-
end
|
329
|
+
end
|
data/lib/azure/storage/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#-------------------------------------------------------------------------
|
2
4
|
# # Copyright (c) Microsoft and contributors. All rights reserved.
|
3
5
|
#
|
@@ -22,16 +24,16 @@
|
|
22
24
|
# THE SOFTWARE.
|
23
25
|
#--------------------------------------------------------------------------
|
24
26
|
|
25
|
-
require
|
26
|
-
require
|
27
|
+
require "azure/storage/core"
|
28
|
+
require "azure/storage/core/http_client"
|
27
29
|
|
28
|
-
require
|
30
|
+
require "azure/storage/client_options"
|
29
31
|
|
30
|
-
require
|
31
|
-
require
|
32
|
-
require
|
33
|
-
require
|
34
|
-
require
|
32
|
+
require "azure/storage/service/storage_service"
|
33
|
+
require "azure/storage/blob/blob_service"
|
34
|
+
require "azure/storage/table/table_service"
|
35
|
+
require "azure/storage/queue/queue_service"
|
36
|
+
require "azure/storage/file/file_service"
|
35
37
|
|
36
38
|
module Azure::Storage
|
37
39
|
class Client
|
@@ -81,7 +83,7 @@ module Azure::Storage
|
|
81
83
|
#
|
82
84
|
# @return [Azure::Storage::Client]
|
83
85
|
def initialize(options = {}, &block)
|
84
|
-
if options.is_a?(Hash)
|
86
|
+
if options.is_a?(Hash) && options.has_key?(:user_agent_prefix)
|
85
87
|
Azure::Storage::Service::StorageService.user_agent_prefix = options[:user_agent_prefix]
|
86
88
|
options.delete :user_agent_prefix
|
87
89
|
end
|
@@ -154,7 +156,7 @@ module Azure::Storage
|
|
154
156
|
# When empty options are given, it will try to read settings from Environment Variables. Refer to [Azure::Storage::ClientOptions.env_vars_mapping] for the mapping relationship
|
155
157
|
#
|
156
158
|
# @return [Azure::Storage::Client]
|
157
|
-
def create(options={}, &block)
|
159
|
+
def create(options = {}, &block)
|
158
160
|
Client.new(options, &block)
|
159
161
|
end
|
160
162
|
|
@@ -165,9 +167,9 @@ module Azure::Storage
|
|
165
167
|
# * +proxy_uri+ - String. Used with +:use_development_storage+ if emulator is hosted other than localhost.
|
166
168
|
#
|
167
169
|
# @return [Azure::Storage::Client]
|
168
|
-
def create_development(proxy_uri=nil, &block)
|
170
|
+
def create_development(proxy_uri = nil, &block)
|
169
171
|
proxy_uri ||= StorageServiceClientConstants::DEV_STORE_URI
|
170
|
-
create(:
|
172
|
+
create(use_development_storage: true, development_storage_proxy_uri: proxy_uri, &block)
|
171
173
|
end
|
172
174
|
|
173
175
|
# Public: Creates an instance of [Azure::Storage::Client] from Environment Variables
|
@@ -191,9 +193,8 @@ module Azure::Storage
|
|
191
193
|
|
192
194
|
private
|
193
195
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
196
|
+
def default_client(opts)
|
197
|
+
!opts.empty? ? { client: Azure::Storage.client(opts) } : { client: self }
|
198
|
+
end
|
198
199
|
end
|
199
|
-
end
|
200
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#-------------------------------------------------------------------------
|
2
4
|
# # Copyright (c) Microsoft and contributors. All rights reserved.
|
3
5
|
#
|
@@ -22,12 +24,11 @@
|
|
22
24
|
# THE SOFTWARE.
|
23
25
|
#--------------------------------------------------------------------------
|
24
26
|
|
25
|
-
require
|
26
|
-
require
|
27
|
+
require "uri"
|
28
|
+
require "azure/storage/client_options_error"
|
27
29
|
|
28
30
|
module Azure::Storage
|
29
31
|
module ClientOptions
|
30
|
-
|
31
32
|
attr_accessor :ca_file
|
32
33
|
|
33
34
|
# Public: Reset options for [Azure::Storage::Client]
|
@@ -75,7 +76,7 @@ module Azure::Storage
|
|
75
76
|
elsif options.is_a? Hash
|
76
77
|
# When the options are provided via singlton setup: Azure::Storage.setup()
|
77
78
|
options = setup_options if options.length == 0
|
78
|
-
|
79
|
+
|
79
80
|
options = parse_connection_string(options[:storage_connection_string]) if options[:storage_connection_string]
|
80
81
|
end
|
81
82
|
|
@@ -90,7 +91,7 @@ module Azure::Storage
|
|
90
91
|
|
91
92
|
# Check if this client is configured with the same options
|
92
93
|
def same_options?(opts)
|
93
|
-
opts.length == 0 || opts.hash == options.hash
|
94
|
+
opts.length == 0 || opts.hash == options.hash
|
94
95
|
end
|
95
96
|
|
96
97
|
# The options after validated and normalized
|
@@ -126,16 +127,16 @@ module Azure::Storage
|
|
126
127
|
# @return [Hash]
|
127
128
|
def self.env_vars_mapping
|
128
129
|
@env_vars_mapping ||= {
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
130
|
+
"EMULATED" => :use_development_storage,
|
131
|
+
"AZURE_STORAGE_ACCOUNT" => :storage_account_name,
|
132
|
+
"AZURE_STORAGE_ACCESS_KEY" => :storage_access_key,
|
133
|
+
"AZURE_STORAGE_CONNECTION_STRING" => :storage_connection_string,
|
134
|
+
"AZURE_STORAGE_BLOB_HOST" => :storage_blob_host,
|
135
|
+
"AZURE_STORAGE_TABLE_HOST" => :storage_table_host,
|
136
|
+
"AZURE_STORAGE_QUEUE_HOST" => :storage_queue_host,
|
137
|
+
"AZURE_STORAGE_FILE_HOST" => :storage_file_host,
|
138
|
+
"AZURE_STORAGE_SAS_TOKEN" => :storage_sas_token,
|
139
|
+
"AZURE_STORAGE_DNS_SUFFIX" => :storage_dns_suffix
|
139
140
|
}
|
140
141
|
end
|
141
142
|
|
@@ -144,211 +145,209 @@ module Azure::Storage
|
|
144
145
|
# @return [Hash]
|
145
146
|
def self.connection_string_mapping
|
146
147
|
@connection_string_mapping ||= {
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
148
|
+
"UseDevelopmentStorage" => :use_development_storage,
|
149
|
+
"DevelopmentStorageProxyUri" => :development_storage_proxy_uri,
|
150
|
+
"DefaultEndpointsProtocol" => :default_endpoints_protocol,
|
151
|
+
"AccountName" => :storage_account_name,
|
152
|
+
"AccountKey" => :storage_access_key,
|
153
|
+
"BlobEndpoint" => :storage_blob_host,
|
154
|
+
"TableEndpoint" => :storage_table_host,
|
155
|
+
"QueueEndpoint" => :storage_queue_host,
|
156
|
+
"FileEndpoint" => :storage_file_host,
|
157
|
+
"SharedAccessSignature" => :storage_sas_token,
|
158
|
+
"EndpointSuffix" => :storage_dns_suffix
|
158
159
|
}
|
159
160
|
end
|
160
161
|
|
161
162
|
private
|
162
163
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
167
|
-
|
168
|
-
def filter(opts={})
|
169
|
-
results = {}
|
170
|
-
|
171
|
-
# P1 - develpoment storage
|
172
|
-
begin
|
173
|
-
results = validated_options(opts,
|
174
|
-
:required => [:use_development_storage],
|
175
|
-
:optional => [:development_storage_proxy_uri])
|
176
|
-
results[:use_development_storage] = true
|
177
|
-
proxy_uri = results[:development_storage_proxy_uri] ||= StorageServiceClientConstants::DEV_STORE_URI
|
178
|
-
results.merge!({:storage_account_name => StorageServiceClientConstants::DEVSTORE_STORAGE_ACCOUNT,
|
179
|
-
:storage_access_key => StorageServiceClientConstants::DEVSTORE_STORAGE_ACCESS_KEY,
|
180
|
-
:storage_blob_host => "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_BLOB_HOST_PORT}",
|
181
|
-
:storage_table_host => "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_TABLE_HOST_PORT}",
|
182
|
-
:storage_queue_host => "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_QUEUE_HOST_PORT}",
|
183
|
-
:storage_file_host => "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_FILE_HOST_PORT}",
|
184
|
-
:use_path_style_uri => true})
|
185
|
-
return results
|
186
|
-
rescue InvalidOptionsError => e
|
187
|
-
end
|
188
|
-
|
189
|
-
# P2 - explicit hosts with account connection string
|
190
|
-
begin
|
191
|
-
results = validated_options(opts,
|
192
|
-
:required => [:storage_connection_string],
|
193
|
-
:optional => [:use_path_style_uri])
|
194
|
-
results[:use_path_style_uri] = results.key?(:use_path_style_uri)
|
195
|
-
normalize_hosts(results)
|
196
|
-
return results
|
197
|
-
rescue InvalidOptionsError => e
|
164
|
+
def method_missing(method_name)
|
165
|
+
return super unless options.key? method_name
|
166
|
+
options[method_name]
|
198
167
|
end
|
199
168
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
169
|
+
def filter(opts = {})
|
170
|
+
results = {}
|
171
|
+
|
172
|
+
# P1 - develpoment storage
|
173
|
+
begin
|
174
|
+
results = validated_options(opts,
|
175
|
+
required: [:use_development_storage],
|
176
|
+
optional: [:development_storage_proxy_uri])
|
177
|
+
results[:use_development_storage] = true
|
178
|
+
proxy_uri = results[:development_storage_proxy_uri] ||= StorageServiceClientConstants::DEV_STORE_URI
|
179
|
+
results.merge!(storage_account_name: StorageServiceClientConstants::DEVSTORE_STORAGE_ACCOUNT,
|
180
|
+
storage_access_key: StorageServiceClientConstants::DEVSTORE_STORAGE_ACCESS_KEY,
|
181
|
+
storage_blob_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_BLOB_HOST_PORT}",
|
182
|
+
storage_table_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_TABLE_HOST_PORT}",
|
183
|
+
storage_queue_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_QUEUE_HOST_PORT}",
|
184
|
+
storage_file_host: "#{proxy_uri}:#{StorageServiceClientConstants::DEVSTORE_FILE_HOST_PORT}",
|
185
|
+
use_path_style_uri: true)
|
186
|
+
return results
|
187
|
+
rescue InvalidOptionsError => e
|
188
|
+
end
|
217
189
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
end
|
190
|
+
# P2 - explicit hosts with account connection string
|
191
|
+
begin
|
192
|
+
results = validated_options(opts,
|
193
|
+
required: [:storage_connection_string],
|
194
|
+
optional: [:use_path_style_uri])
|
195
|
+
results[:use_path_style_uri] = results.key?(:use_path_style_uri)
|
196
|
+
normalize_hosts(results)
|
197
|
+
return results
|
198
|
+
rescue InvalidOptionsError => e
|
199
|
+
end
|
229
200
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
201
|
+
# P3 - account name and key or sas with default hosts or an end suffix
|
202
|
+
begin
|
203
|
+
results = validated_options(opts,
|
204
|
+
required: [:storage_account_name],
|
205
|
+
only_one: [:storage_access_key, :storage_sas_token],
|
206
|
+
optional: [:default_endpoints_protocol, :storage_dns_suffix])
|
207
|
+
protocol = results[:default_endpoints_protocol] ||= StorageServiceClientConstants::DEFAULT_PROTOCOL
|
208
|
+
suffix = results[:storage_dns_suffix] ||= StorageServiceClientConstants::DEFAULT_ENDPOINT_SUFFIX
|
209
|
+
account = results[:storage_account_name]
|
210
|
+
results.merge!(storage_blob_host: "#{protocol}://#{account}.#{ServiceType::BLOB}.#{suffix}",
|
211
|
+
storage_table_host: "#{protocol}://#{account}.#{ServiceType::TABLE}.#{suffix}",
|
212
|
+
storage_queue_host: "#{protocol}://#{account}.#{ServiceType::QUEUE}.#{suffix}",
|
213
|
+
storage_file_host: "#{protocol}://#{account}.#{ServiceType::FILE}.#{suffix}",
|
214
|
+
use_path_style_uri: false)
|
215
|
+
return results
|
216
|
+
rescue InvalidOptionsError => e
|
217
|
+
end
|
240
218
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
219
|
+
# P4 - explicit hosts with account name and key
|
220
|
+
begin
|
221
|
+
results = validated_options(opts,
|
222
|
+
required: [:storage_account_name, :storage_access_key],
|
223
|
+
at_least_one: [:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host],
|
224
|
+
optional: [:use_path_style_uri, :default_endpoints_protocol])
|
225
|
+
results[:use_path_style_uri] = results.key?(:use_path_style_uri)
|
226
|
+
normalize_hosts(results)
|
227
|
+
return results
|
228
|
+
rescue InvalidOptionsError => e
|
229
|
+
end
|
252
230
|
|
253
|
-
|
254
|
-
|
231
|
+
# P5 - anonymous or sas only for one or more particular services, options with account name/key + hosts should be already validated in P4
|
232
|
+
begin
|
233
|
+
results = validated_options(opts,
|
234
|
+
at_least_one: [:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host],
|
235
|
+
optional: [:use_path_style_uri, :default_endpoints_protocol, :storage_sas_token])
|
236
|
+
results[:use_path_style_uri] = results.key?(:use_path_style_uri)
|
237
|
+
normalize_hosts(results)
|
238
|
+
return results
|
239
|
+
rescue InvalidOptionsError => e
|
240
|
+
end
|
255
241
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
242
|
+
# P6 - account name and key or sas with explicit hosts
|
243
|
+
begin
|
244
|
+
results = validated_options(opts,
|
245
|
+
required: [:storage_account_name],
|
246
|
+
only_one: [:storage_access_key, :storage_sas_token],
|
247
|
+
at_least_one: [:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host])
|
248
|
+
results[:use_path_style_uri] = results.key?(:use_path_style_uri)
|
249
|
+
normalize_hosts(results)
|
250
|
+
return results
|
251
|
+
rescue InvalidOptionsError => e
|
263
252
|
end
|
264
|
-
end
|
265
|
-
end
|
266
253
|
|
267
|
-
|
268
|
-
Proc.new do |i|
|
269
|
-
i.is_a?(String) && i =~ /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/
|
254
|
+
raise InvalidOptionsError, "options provided are not valid set: #{opts}" # wrong opts if move to this line
|
270
255
|
end
|
271
|
-
end
|
272
256
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
257
|
+
def normalize_hosts(options)
|
258
|
+
if options[:default_endpoints_protocol]
|
259
|
+
[:storage_blob_host, :storage_table_host, :storage_file_host, :storage_queue_host].each do |k|
|
260
|
+
if options[k]
|
261
|
+
raise InvalidOptionsError, "Explict host cannot contain scheme if default_endpoints_protocol is set." if options[k] =~ /^https?/
|
262
|
+
options[k] = "#{options[:default_endpoints_protocol]}://#{options[k]}"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
277
266
|
end
|
278
|
-
end
|
279
267
|
|
280
|
-
|
281
|
-
|
282
|
-
|
268
|
+
def is_base64_encoded
|
269
|
+
Proc.new do |i|
|
270
|
+
i.is_a?(String) && i =~ /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/
|
271
|
+
end
|
272
|
+
end
|
283
273
|
|
284
|
-
|
285
|
-
|
286
|
-
|
274
|
+
def is_url
|
275
|
+
Proc.new do |i|
|
276
|
+
i = "http://" + i unless i =~ /\Ahttps?:\/\//
|
277
|
+
i =~ URI.regexp(["http", "https"])
|
278
|
+
end
|
279
|
+
end
|
287
280
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
at_least_one = requirements[:at_least_one] || []
|
292
|
-
only_one = requirements[:only_one] || []
|
293
|
-
optional = requirements[:optional] || []
|
294
|
-
|
295
|
-
raise InvalidOptionsError,"Not all required keys are provided: #{required}" if required.any? { |k| !opts.key? k}
|
296
|
-
raise InvalidOptionsError,"Only one of #{only_one} is required" unless only_one.length == 0 || only_one.count { |k| opts.key? k} == 1
|
297
|
-
raise InvalidOptionsError,"At least one of #{at_least_one} is required" unless at_least_one.length == 0 || at_least_one.any? { |k| opts.key? k}
|
298
|
-
|
299
|
-
@@option_validators ||= {
|
300
|
-
:use_development_storage => is_true,
|
301
|
-
:development_storage_proxy_uri => is_url,
|
302
|
-
:storage_account_name => lambda { |i| i.is_a?(String) },
|
303
|
-
:storage_access_key => is_base64_encoded,
|
304
|
-
:storage_sas_token => lambda { |i| i.is_a?(String) },
|
305
|
-
:storage_blob_host => is_url,
|
306
|
-
:storage_table_host => is_url,
|
307
|
-
:storage_queue_host => is_url,
|
308
|
-
:storage_file_host => is_url,
|
309
|
-
:storage_dns_suffix => is_url,
|
310
|
-
:default_endpoints_protocol => lambda { |i| ['http', 'https'].include? i.downcase },
|
311
|
-
:use_path_style_uri => is_true
|
312
|
-
}
|
281
|
+
def is_true
|
282
|
+
Proc.new { |i| i == true || (i.is_a?(String) && i.downcase == "true") }
|
283
|
+
end
|
313
284
|
|
314
|
-
|
315
|
-
|
285
|
+
def is_non_empty_string
|
286
|
+
Proc.new { |i| i && i.is_a?(String) && i.strip.length }
|
287
|
+
end
|
316
288
|
|
317
|
-
opts
|
318
|
-
raise InvalidOptionsError,
|
319
|
-
|
320
|
-
|
289
|
+
def validated_options(opts, requirements = {})
|
290
|
+
raise InvalidOptionsError, 'nil is not allowed for option\'s value' if opts.values.any? { |v| v == nil }
|
291
|
+
required = requirements[:required] || []
|
292
|
+
at_least_one = requirements[:at_least_one] || []
|
293
|
+
only_one = requirements[:only_one] || []
|
294
|
+
optional = requirements[:optional] || []
|
295
|
+
|
296
|
+
raise InvalidOptionsError, "Not all required keys are provided: #{required}" if required.any? { |k| !opts.key? k }
|
297
|
+
raise InvalidOptionsError, "Only one of #{only_one} is required" unless only_one.length == 0 || only_one.count { |k| opts.key? k } == 1
|
298
|
+
raise InvalidOptionsError, "At least one of #{at_least_one} is required" unless at_least_one.length == 0 || at_least_one.any? { |k| opts.key? k }
|
299
|
+
|
300
|
+
@@option_validators ||= {
|
301
|
+
use_development_storage: is_true,
|
302
|
+
development_storage_proxy_uri: is_url,
|
303
|
+
storage_account_name: lambda { |i| i.is_a?(String) },
|
304
|
+
storage_access_key: is_base64_encoded,
|
305
|
+
storage_sas_token: lambda { |i| i.is_a?(String) },
|
306
|
+
storage_blob_host: is_url,
|
307
|
+
storage_table_host: is_url,
|
308
|
+
storage_queue_host: is_url,
|
309
|
+
storage_file_host: is_url,
|
310
|
+
storage_dns_suffix: is_url,
|
311
|
+
default_endpoints_protocol: lambda { |i| ["http", "https"].include? i.downcase },
|
312
|
+
use_path_style_uri: is_true
|
313
|
+
}
|
314
|
+
|
315
|
+
valid_options = required + at_least_one + only_one + optional
|
316
|
+
results = {}
|
317
|
+
|
318
|
+
opts.each do |k, v|
|
319
|
+
raise InvalidOptionsError, "#{k} is not included in valid options" unless valid_options.length == 0 || valid_options.include?(k)
|
320
|
+
unless @@option_validators.key?(k) && @@option_validators[k].call(v)
|
321
|
+
raise InvalidOptionsError, "#{k} is invalid"
|
322
|
+
end
|
323
|
+
results[k] = v
|
321
324
|
end
|
322
|
-
results
|
325
|
+
results
|
323
326
|
end
|
324
|
-
results
|
325
|
-
end
|
326
|
-
|
327
|
-
def load_env
|
328
|
-
cs = ENV['AZURE_STORAGE_CONNECTION_STRING']
|
329
|
-
return parse_connection_string(cs) if cs
|
330
327
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
end
|
328
|
+
def load_env
|
329
|
+
cs = ENV["AZURE_STORAGE_CONNECTION_STRING"]
|
330
|
+
return parse_connection_string(cs) if cs
|
335
331
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
e = i.index('=')
|
340
|
-
raise InvalidConnectionStringError,SR::INVALID_CONNECTION_STRING if e < 0 || e == i.length - 1
|
341
|
-
key,value = i[0..e-1],i[e+1..i.length-1]
|
342
|
-
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING_BAD_KEY % key unless ClientOptions.connection_string_mapping.key? key
|
343
|
-
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING_EMPTY_KEY % key if value.length == 0
|
344
|
-
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING_DUPLICATE_KEY % key if opts.key? key
|
345
|
-
opts[ClientOptions.connection_string_mapping[key]] = value
|
332
|
+
opts = {}
|
333
|
+
ClientOptions.env_vars_mapping.each { |k, v| opts[v] = ENV[k] if ENV[k] }
|
334
|
+
opts
|
346
335
|
end
|
347
|
-
raise InvalidConnectionStringError,SR::INVALID_CONNECTION_STRING if opts.length == 0
|
348
336
|
|
349
|
-
|
350
|
-
|
337
|
+
def parse_connection_string(connection_string)
|
338
|
+
opts = {}
|
339
|
+
connection_string.split(";").each do |i|
|
340
|
+
e = i.index("=")
|
341
|
+
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING if e < 0 || e == i.length - 1
|
342
|
+
key, value = i[0..e - 1], i[e + 1..i.length - 1]
|
343
|
+
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING_BAD_KEY % key unless ClientOptions.connection_string_mapping.key? key
|
344
|
+
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING_EMPTY_KEY % key if value.length == 0
|
345
|
+
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING_DUPLICATE_KEY % key if opts.key? key
|
346
|
+
opts[ClientOptions.connection_string_mapping[key]] = value
|
347
|
+
end
|
348
|
+
raise InvalidConnectionStringError, SR::INVALID_CONNECTION_STRING if opts.length == 0
|
351
349
|
|
350
|
+
opts
|
351
|
+
end
|
352
352
|
end
|
353
|
-
|
354
|
-
end
|
353
|
+
end
|