azure-storage-common 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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