azure-storage-common 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/common/lib/azure/storage/common.rb +26 -0
  3. data/common/lib/azure/storage/common/autoload.rb +61 -0
  4. data/common/lib/azure/storage/common/client.rb +159 -0
  5. data/common/lib/azure/storage/common/client_options.rb +356 -0
  6. data/common/lib/azure/storage/common/client_options_error.rb +41 -0
  7. data/common/lib/azure/storage/common/configurable.rb +212 -0
  8. data/common/lib/azure/storage/common/core.rb +35 -0
  9. data/common/lib/azure/storage/common/core/auth/anonymous_signer.rb +43 -0
  10. data/common/lib/azure/storage/common/core/auth/shared_access_signature.rb +30 -0
  11. data/common/lib/azure/storage/common/core/auth/shared_access_signature_generator.rb +352 -0
  12. data/common/lib/azure/storage/common/core/auth/shared_access_signature_signer.rb +57 -0
  13. data/common/lib/azure/storage/common/core/auth/shared_key.rb +60 -0
  14. data/common/lib/azure/storage/common/core/autoload.rb +50 -0
  15. data/common/lib/azure/storage/common/core/error.rb +43 -0
  16. data/common/lib/azure/storage/common/core/filter/exponential_retry_filter.rb +64 -0
  17. data/common/lib/azure/storage/common/core/filter/linear_retry_filter.rb +55 -0
  18. data/common/lib/azure/storage/common/core/filter/retry_filter.rb +302 -0
  19. data/common/lib/azure/storage/common/core/http_client.rb +65 -0
  20. data/common/lib/azure/storage/common/core/sr.rb +85 -0
  21. data/common/lib/azure/storage/common/core/utility.rb +255 -0
  22. data/common/lib/azure/storage/common/default.rb +868 -0
  23. data/common/lib/azure/storage/common/service/access_policy.rb +37 -0
  24. data/common/lib/azure/storage/common/service/cors.rb +38 -0
  25. data/common/lib/azure/storage/common/service/cors_rule.rb +48 -0
  26. data/common/lib/azure/storage/common/service/enumeration_results.rb +32 -0
  27. data/common/lib/azure/storage/common/service/geo_replication.rb +40 -0
  28. data/common/lib/azure/storage/common/service/logging.rb +47 -0
  29. data/common/lib/azure/storage/common/service/metrics.rb +45 -0
  30. data/common/lib/azure/storage/common/service/retention_policy.rb +37 -0
  31. data/common/lib/azure/storage/common/service/serialization.rb +335 -0
  32. data/common/lib/azure/storage/common/service/signed_identifier.rb +40 -0
  33. data/common/lib/azure/storage/common/service/storage_service.rb +322 -0
  34. data/common/lib/azure/storage/common/service/storage_service_properties.rb +48 -0
  35. data/common/lib/azure/storage/common/service/storage_service_stats.rb +39 -0
  36. data/common/lib/azure/storage/common/version.rb +49 -0
  37. metadata +216 -0
@@ -0,0 +1,57 @@
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
+
27
+ require "azure/core/auth/signer"
28
+
29
+ module Azure::Storage::Common::Core
30
+ module Auth
31
+ class SharedAccessSignatureSigner < Azure::Core::Auth::Signer
32
+ attr :account_name, :sas_token
33
+ attr_accessor :api_ver
34
+
35
+ # Public: Initialize the Signer with a SharedAccessSignature
36
+ #
37
+ # @param api_ver [String] The api version of the service.
38
+ # @param account_name [String] The account name. Defaults to the one in the global configuration.
39
+ # @param sas_token [String] The sas token to be used for signing
40
+ def initialize(api_ver, account_name = "", sas_token = "")
41
+ if account_name.empty? || sas_token.empty?
42
+ client = Azure::Storage::Common::Client.create_from_env
43
+ account_name = client.storage_account_name if account_name.empty?
44
+ sas_token = client.storage_sas_token if sas_token.empty?
45
+ end
46
+ @api_ver = api_ver
47
+ @account_name = account_name
48
+ @sas_token = sas_token
49
+ end
50
+
51
+ def sign_request(req)
52
+ req.uri = URI.parse(req.uri.to_s + (req.uri.query.nil? ? "?" : "&") + sas_token.sub(/^\?/, "") + "&api-version=" + @api_ver)
53
+ req
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,60 @@
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/core/auth/signer"
28
+ require "azure/core/auth/shared_key"
29
+
30
+ module Azure::Storage::Common::Core
31
+ module Auth
32
+ class SharedKey < Azure::Core::Auth::SharedKey
33
+ # Generate the string to sign.
34
+ #
35
+ # @param method [Symbol] HTTP request method.
36
+ # @param uri [URI] URI of the request we're signing.
37
+ # @param headers [Hash] HTTP request headers.
38
+ #
39
+ # @return [String]
40
+ def signable_string(method, uri, headers)
41
+ [
42
+ method.to_s.upcase,
43
+ headers.fetch("Content-Encoding", ""),
44
+ headers.fetch("Content-Language", ""),
45
+ headers.fetch("Content-Length", "").sub(/^0+/, ""), # from 2015-02-21, if Content-Length == 0, it won't be signed
46
+ headers.fetch("Content-MD5", ""),
47
+ headers.fetch("Content-Type", ""),
48
+ headers.fetch("Date", ""),
49
+ headers.fetch("If-Modified-Since", ""),
50
+ headers.fetch("If-Match", ""),
51
+ headers.fetch("If-None-Match", ""),
52
+ headers.fetch("If-Unmodified-Since", ""),
53
+ headers.fetch("Range", ""),
54
+ canonicalized_headers(headers),
55
+ canonicalized_resource(uri)
56
+ ].join("\n")
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,50 @@
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
+
27
+ module Azure
28
+ module Storage
29
+ module Common
30
+ module Core
31
+ autoload :HttpClient, "azure/storage/common/core/http_client"
32
+ autoload :Utility, "azure/storage/common/core/utility"
33
+ autoload :Logger, "azure/storage/common/core/utility"
34
+ autoload :Error, "azure/storage/common/core/error"
35
+
36
+ module Auth
37
+ autoload :SharedKey, "azure/storage/common/core/auth/shared_key.rb"
38
+ autoload :SharedAccessSignature, "azure/storage/common/core/auth/shared_access_signature_generator.rb"
39
+ autoload :SharedAccessSignatureSigner, "azure/storage/common/core/auth/shared_access_signature_signer.rb"
40
+ end
41
+
42
+ module Filter
43
+ autoload :RetryPolicyFilter, "azure/storage/common/core/filter/retry_filter"
44
+ autoload :LinearRetryPolicyFilter, "azure/storage/common/core/filter/linear_retry_filter"
45
+ autoload :ExponentialRetryPolicyFilter, "azure/storage/common/core/filter/exponential_retry_filter"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,43 @@
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/core"
27
+
28
+ module Azure::Storage::Common::Core
29
+ # Superclass for errors generated from this library, so people can
30
+ # just rescue this for generic error handling
31
+ class StorageError < StandardError
32
+ # attr_reader :description
33
+ # attr_reader :status_code
34
+ # attr_reader :type
35
+
36
+ # def initialize(description, type, status)
37
+ # @type = type
38
+ # @status_code = status
39
+ # @description = description
40
+ # super("#{type} (#{status_code}): #{description}")
41
+ # end
42
+ end
43
+ end
@@ -0,0 +1,64 @@
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/core"
27
+ require "azure/core/http/retry_policy"
28
+
29
+ module Azure::Storage::Common::Core::Filter
30
+ class ExponentialRetryPolicyFilter < RetryPolicyFilter
31
+ def initialize(retry_count = nil, min_retry_interval = nil, max_retry_interval = nil)
32
+ @retry_count = retry_count || ExponentialRetryPolicyFilter::DEFAULT_RETRY_COUNT
33
+ @min_retry_interval = min_retry_interval || ExponentialRetryPolicyFilter::DEFAULT_MIN_RETRY_INTERVAL
34
+ @max_retry_interval = max_retry_interval || ExponentialRetryPolicyFilter::DEFAULT_MAX_RETRY_INTERVAL
35
+
36
+ super @retry_count, @min_retry_interval
37
+ end
38
+
39
+ attr_reader :min_retry_interval,
40
+ :max_retry_interval
41
+
42
+ DEFAULT_RETRY_COUNT = 3
43
+ DEFAULT_MIN_RETRY_INTERVAL = 10
44
+ DEFAULT_MAX_RETRY_INTERVAL = 90
45
+
46
+ # Overrides the base class implementation of call to determine
47
+ # how the HTTP request should continue retrying
48
+ #
49
+ # retry_data - Hash. Stores stateful retry data
50
+ #
51
+ # The retry_data is a Hash which can be used to store
52
+ # stateful data about the request execution context (such as an
53
+ # incrementing counter, timestamp, etc). The retry_data object
54
+ # will be the same instance throughout the lifetime of the request
55
+ def apply_retry_policy(retry_data)
56
+ # Adjust retry count
57
+ retry_data[:count] = retry_data[:count] === nil ? 1 : retry_data[:count] + 1
58
+
59
+ # Adjust retry interval
60
+ increment_delta = (@max_retry_interval - @min_retry_interval).fdiv(2**(@retry_count - 1)) * (2**(retry_data[:count] - 1));
61
+ retry_data[:interval] = retry_data[:interval] === nil ? @min_retry_interval : [@min_retry_interval + increment_delta, @max_retry_interval].min;
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,55 @@
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/core"
27
+ require "azure/core/http/retry_policy"
28
+
29
+ module Azure::Storage::Common::Core::Filter
30
+ class LinearRetryPolicyFilter < RetryPolicyFilter
31
+ def initialize(retry_count = nil, retry_interval = nil)
32
+ @retry_count = retry_count || LinearRetryPolicyFilter::DEFAULT_RETRY_COUNT
33
+ @retry_interval = retry_interval || LinearRetryPolicyFilter::DEFAULT_RETRY_INTERVAL
34
+
35
+ super @retry_count, @retry_interval
36
+ end
37
+
38
+ DEFAULT_RETRY_COUNT = 3
39
+ DEFAULT_RETRY_INTERVAL = 30
40
+
41
+ # Overrides the base class implementation of call to determine
42
+ # how the HTTP request should continue retrying
43
+ #
44
+ # retry_data - Hash. Stores stateful retry data
45
+ #
46
+ # The retry_data is a Hash which can be used to store
47
+ # stateful data about the request execution context (such as an
48
+ # incrementing counter, timestamp, etc). The retry_data object
49
+ # will be the same instance throughout the lifetime of the request
50
+ def apply_retry_policy(retry_data)
51
+ retry_data[:count] = retry_data[:count] == nil ? 1 : retry_data[:count] + 1
52
+ retry_data[:interval] = @retry_interval
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,302 @@
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/core"
27
+ require "azure/core/http/retry_policy"
28
+
29
+ module Azure::Storage::Common::Core::Filter
30
+ class RetryPolicyFilter < Azure::Core::Http::RetryPolicy
31
+ def initialize(retry_count = nil, retry_interval = nil)
32
+ @retry_count = retry_count
33
+ @retry_interval = retry_interval
34
+ @request_options = {}
35
+
36
+ super &:should_retry?
37
+ end
38
+
39
+ attr_reader :retry_count,
40
+ :retry_interval
41
+
42
+ # Overrides the base class implementation of call to determine
43
+ # whether to retry the operation
44
+ #
45
+ # response - HttpResponse. The response from the active request
46
+ # retry_data - Hash. Stores stateful retry data
47
+ def should_retry?(response, retry_data)
48
+ # Fill necessary information
49
+ init_retry_data retry_data
50
+
51
+ # Applies the logic when there is subclass overrides it
52
+ apply_retry_policy retry_data
53
+
54
+ # Checks the result and count limit
55
+ if retry_data[:retryable].nil?
56
+ retry_data[:retryable] = true
57
+ else
58
+ retry_data[:retryable] &&= retry_data[:count] <= @retry_count
59
+ end
60
+ return false unless retry_data[:retryable]
61
+
62
+ # Checks whether there is a local error
63
+ # Cannot retry immediately when it returns true, as it need check other errors
64
+ should_retry_on_local_error? retry_data
65
+ return false unless should_retry_on_error? response, retry_data
66
+
67
+ # Determined that it needs to retry.
68
+ adjust_retry_request retry_data
69
+
70
+ wait_for_retry
71
+
72
+ retry_data[:retryable]
73
+ end
74
+
75
+ # Apply the retry policy to determine how the HTTP request should continue retrying
76
+ #
77
+ # retry_data - Hash. Stores stateful retry data
78
+ #
79
+ # The retry_data is a Hash which can be used to store
80
+ # stateful data about the request execution context (such as an
81
+ # incrementing counter, timestamp, etc). The retry_data object
82
+ # will be the same instance throughout the lifetime of the request
83
+ #
84
+ # Alternatively, a subclass could override this method.
85
+ def apply_retry_policy(retry_data)
86
+ end
87
+
88
+ # Determines if the HTTP request should continue retrying
89
+ #
90
+ # retry_data - Hash. Stores stateful retry data
91
+ #
92
+ # The retry_data is a Hash which can be used to store
93
+ # stateful data about the request execution context (such as an
94
+ # incrementing counter, timestamp, etc). The retry_data object
95
+ # will be the same instance throughout the lifetime of the request.
96
+ def should_retry_on_local_error?(retry_data)
97
+ unless retry_data[:error]
98
+ retry_data[:retryable] = true;
99
+ return true
100
+ end
101
+
102
+ error_message = retry_data[:error].inspect
103
+
104
+ if error_message.include?("SocketError: Hostname not known")
105
+ # Retry on local DNS resolving
106
+ # When uses resolv-replace.rb to replace the libc resolver
107
+ # Reference:
108
+ # https://makandracards.com/ninjaconcept/30815-fixing-socketerror-getaddrinfo-name-or-service-not-known-with-ruby-s-resolv-replace-rb
109
+ # http://www.subelsky.com/2014/05/fixing-socketerror-getaddrinfo-name-or.html
110
+ retry_data[:retryable] = true;
111
+ elsif error_message.include?("getaddrinfo: Name or service not known")
112
+ # When uses the default resolver
113
+ retry_data[:retryable] = true;
114
+ elsif error_message.downcase.include?("timeout")
115
+ retry_data[:retryable] = true;
116
+ elsif error_message.include?("Errno::ECONNRESET")
117
+ retry_data[:retryable] = true;
118
+ elsif error_message.include?("Errno::EACCES")
119
+ retry_data[:retryable] = false;
120
+ elsif error_message.include?("NOSUPPORT")
121
+ retry_data[:retryable] = false;
122
+ end
123
+
124
+ retry_data[:retryable]
125
+ end
126
+
127
+ # Determines if the HTTP request should continue retrying
128
+ #
129
+ # response - Azure::Core::Http::HttpResponse. The response from the active request
130
+ # retry_data - Hash. Stores stateful retry data
131
+ #
132
+ # The retry_data is a Hash which can be used to store
133
+ # stateful data about the request execution context (such as an
134
+ # incrementing counter, timestamp, etc). The retry_data object
135
+ # will be the same instance throughout the lifetime of the request.
136
+ def should_retry_on_error?(response, retry_data)
137
+ response = response || retry_data[:error].http_response if retry_data[:error] && retry_data[:error].respond_to?("http_response")
138
+ unless response
139
+ retry_data[:retryable] = false unless retry_data[:error]
140
+ return retry_data[:retryable]
141
+ end
142
+
143
+ check_location(response, retry_data)
144
+
145
+ check_status_code(retry_data)
146
+
147
+ retry_data[:retryable]
148
+ end
149
+
150
+ # Adjust the retry parameter and wait for retry
151
+ def wait_for_retry
152
+ sleep @retry_interval
153
+ end
154
+
155
+ # Adjust the retry request
156
+ #
157
+ # retry_data - Hash. Stores stateful retry data
158
+ def adjust_retry_request(retry_data)
159
+ # Adjust the location first
160
+ next_location = @request_options[:target_location].nil? ? get_next_location(retry_data) : @request_options[:target_location]
161
+ retry_data[:current_location] = next_location
162
+
163
+ retry_data[:uri] =
164
+ if next_location == Azure::Storage::Common::StorageLocation::PRIMARY
165
+ @request_options[:primary_uri]
166
+ else
167
+ @request_options[:secondary_uri]
168
+ end
169
+
170
+ # Now is the time to calculate the exact retry interval. ShouldRetry call above already
171
+ # returned back how long two requests to the same location should be apart from each other.
172
+ # However, for the reasons explained above, the time spent between the last attempt to
173
+ # the target location and current time must be subtracted from the total retry interval
174
+ # that ShouldRetry returned.
175
+ lastAttemptTime =
176
+ if retry_data[:current_location] == Azure::Storage::Common::StorageLocation::PRIMARY
177
+ retry_data[:last_primary_attempt]
178
+ else
179
+ retry_data[:last_secondary_attempt]
180
+ end
181
+
182
+ @retry_interval =
183
+ if lastAttemptTime.nil?
184
+ 0
185
+ else
186
+ since_last_attempt = Time.now - lastAttemptTime
187
+ retry_data[:interval] - since_last_attempt
188
+ end
189
+ end
190
+
191
+ # Initialize the retry data
192
+ #
193
+ # retry_data - Hash. Stores stateful retry data
194
+ def init_retry_data(retry_data)
195
+ @request_options = retry_data[:request_options] unless retry_data[:request_options].nil?
196
+
197
+ if retry_data[:current_location].nil?
198
+ retry_data[:current_location] = Azure::Storage::Common::Service::StorageService.get_location(@request_options[:location_mode], @request_options[:request_location_mode])
199
+ end
200
+
201
+ if retry_data[:current_location] == Azure::Storage::Common::StorageLocation::PRIMARY
202
+ retry_data[:last_primary_attempt] = Time.now
203
+ else
204
+ retry_data[:last_secondary_attempt] = Time.now
205
+ end
206
+ end
207
+
208
+ # Check the location
209
+ #
210
+ # retry_data - Hash. Stores stateful retry data
211
+ def check_location(response, retry_data)
212
+ # If a request sent to the secondary location fails with 404 (Not Found), it is possible
213
+ # that the resource replication is not finished yet. So, in case of 404 only in the secondary
214
+ # location, the failure should still be retryable.
215
+ retry_data[:secondary_not_found] = (retry_data[:current_location] === Azure::Storage::Common::StorageLocation::SECONDARY) && response.status_code === 404;
216
+
217
+ if retry_data[:secondary_not_found]
218
+ retry_data[:status_code] = 500
219
+ else
220
+ if (response.status_code)
221
+ retry_data[:status_code] = response.status_code
222
+ else
223
+ retry_data[:status_code] = nil
224
+ end
225
+ end
226
+ end
227
+
228
+ # Check the status code
229
+ #
230
+ # retry_data - Hash. Stores stateful retry data
231
+ def check_status_code(retry_data)
232
+ if (retry_data[:status_code] < 400)
233
+ retry_data[:retryable] = false;
234
+ # Non-timeout Cases
235
+ elsif (retry_data[:status_code] != 408)
236
+ # Always no retry on "not implemented" and "version not supported"
237
+ if (retry_data[:status_code] == 501 || retry_data[:status_code] == 505)
238
+ retry_data[:retryable] = false;
239
+ end
240
+
241
+ if (retry_data[:status_code] == 404)
242
+ retry_data[:retryable] = true;
243
+ return true;
244
+ end
245
+
246
+ # When absorb_conditional_errors_on_retry is set (for append blob)
247
+ if (@request_options[:absorb_conditional_errors_on_retry])
248
+ if (retry_data[:status_code] == 412)
249
+ # When appending block with precondition failure and their was a server error before, we ignore the error.
250
+ if (retry_data[:last_server_error])
251
+ retry_data[:error] = nil;
252
+ retry_data[:retryable] = true;
253
+ else
254
+ retry_data[:retryable] = false;
255
+ end
256
+ elsif (retry_data[:retryable] && retry_data[:status_code] >= 500 && retry_data[:status_code] < 600)
257
+ # Retry on the server error
258
+ retry_data[:retryable] = true;
259
+ retry_data[:last_server_error] = true;
260
+ end
261
+ elsif (retry_data[:status_code] < 500)
262
+ # No retry on the client error
263
+ retry_data[:retryable] = false;
264
+ end
265
+ end
266
+ end
267
+
268
+ # Get retry request destination
269
+ #
270
+ # retry_data - Hash. Stores stateful retry data
271
+ def get_next_location(retry_data)
272
+ # In case of 404 when trying the secondary location, instead of retrying on the
273
+ # secondary, further requests should be sent only to the primary location, as it most
274
+ # probably has a higher chance of succeeding there.
275
+ if retry_data[:secondary_not_found] && @request_options[:location_mode] != Azure::Storage::Common::LocationMode::SECONDARY_ONLY
276
+ @request_options[:location_mode] = Azure::Storage::Common::LocationMode::PRIMARY_ONLY;
277
+ return Azure::Storage::Common::StorageLocation::PRIMARY
278
+ end
279
+
280
+ case @request_options[:location_mode]
281
+ when Azure::Storage::Common::LocationMode::PRIMARY_ONLY
282
+ Azure::Storage::Common::StorageLocation::PRIMARY
283
+ when Azure::Storage::Common::LocationMode::SECONDARY_ONLY
284
+ Azure::Storage::Common::StorageLocation::SECONDARY
285
+ else
286
+ # request_location_mode cannot be SECONDARY_ONLY because it will be blocked at the first time
287
+ if @request_options[:request_location_mode] == Azure::Storage::Common::RequestLocationMode::PRIMARY_ONLY
288
+ Azure::Storage::Common::StorageLocation::PRIMARY
289
+ elsif @request_options[:request_location_mode] == Azure::Storage::Common::RequestLocationMode::SECONDARY_ONLY
290
+ Azure::Storage::Common::StorageLocation::SECONDARY
291
+ else
292
+ if retry_data[:current_location] === Azure::Storage::Common::StorageLocation::PRIMARY
293
+ Azure::Storage::Common::StorageLocation::SECONDARY
294
+ else
295
+ Azure::Storage::Common::StorageLocation::PRIMARY
296
+ end
297
+ end
298
+ end
299
+ end
300
+
301
+ end
302
+ end