google-cloud-env 1.6.0 → 2.0.1

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.
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2023 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ module Google
19
+ module Cloud
20
+ class Env
21
+ ##
22
+ # Access to system environment variables.
23
+ #
24
+ # This is a hashlike object that controls access to environment variable
25
+ # data. It supports temporarily changing the data source (i.e. swapping
26
+ # ::ENV out for a different set of data) for mocking.
27
+ #
28
+ class Variables
29
+ ##
30
+ # Create an enviroment variables access object. This is initially
31
+ # backed by the actual environment variables (i.e. ENV).
32
+ #
33
+ def initialize
34
+ @backing_data = ::ENV
35
+ end
36
+
37
+ ##
38
+ # Fetch the given environment variable from the backing data.
39
+ #
40
+ # @param key [String]
41
+ # @return [String,nil]
42
+ #
43
+ def [] key
44
+ @backing_data[key.to_s]
45
+ end
46
+ alias get []
47
+
48
+ ##
49
+ # The backing data is a hash or hash-like object that represents the
50
+ # environment variable data. This can either be the actual environment
51
+ # variables object (i.e. ENV) or a substitute hash used for mocking.
52
+ #
53
+ # @return [Hash{String=>String}]
54
+ #
55
+ attr_accessor :backing_data
56
+
57
+ ##
58
+ # Run the given block with the backing data replaced with the given
59
+ # hash. The original backing data is restored afterward. This is used
60
+ # for debugging/testing/mocking.
61
+ #
62
+ # @param temp_backing_data [Hash{String=>String}]
63
+ #
64
+ def with_backing_data temp_backing_data
65
+ old_backing_data = @backing_data
66
+ begin
67
+ @backing_data = temp_backing_data
68
+ yield
69
+ ensure
70
+ @backing_data = old_backing_data
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -16,7 +16,11 @@
16
16
  module Google
17
17
  module Cloud
18
18
  class Env
19
- VERSION = "1.6.0".freeze
19
+ ##
20
+ # Library version
21
+ # @return [String]
22
+ #
23
+ VERSION = "2.0.1".freeze
20
24
  end
21
25
  end
22
26
  end
@@ -12,24 +12,32 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
-
16
- require "faraday"
17
15
  require "json"
18
16
 
17
+ require "google/cloud/env/compute_metadata"
18
+ require "google/cloud/env/compute_smbios"
19
+ require "google/cloud/env/file_system"
20
+ require "google/cloud/env/variables"
19
21
 
22
+ ##
23
+ # Namespace of Google products
24
+ #
20
25
  module Google
26
+ ##
27
+ # Namespace of Google Cloud products
28
+ #
21
29
  module Cloud
22
30
  ##
23
- # # Google Cloud hosting environment
31
+ # ## Google Cloud hosting environment
24
32
  #
25
33
  # This library provides access to information about the application's
26
- # hosting environment if it is running on Google Cloud Platform. You may
34
+ # hosting environment if it is running on Google Cloud Platform. You can
27
35
  # use this library to determine which Google Cloud product is hosting your
28
36
  # application (e.g. App Engine, Kubernetes Engine), information about the
29
37
  # Google Cloud project hosting the application, information about the
30
38
  # virtual machine instance, authentication information, and so forth.
31
39
  #
32
- # ## Usage
40
+ # ### Usage
33
41
  #
34
42
  # Obtain an instance of the environment info with:
35
43
  #
@@ -56,116 +64,180 @@ module Google
56
64
  # ```
57
65
  #
58
66
  class Env
59
- # @private Base (host) URL for the metadata server.
60
- METADATA_HOST = "http://169.254.169.254".freeze
67
+ ##
68
+ # Create a new instance of the environment information.
69
+ # Most clients should not need to call this directly. Obtain a singleton
70
+ # instance of the information from `Google::Cloud.env`.
71
+ #
72
+ def initialize
73
+ @variables = Variables.new
74
+ @file_system = FileSystem.new
75
+ @compute_smbios = ComputeSMBIOS.new
76
+ @compute_metadata = ComputeMetadata.new variables: @variables,
77
+ compute_smbios: @compute_smbios
78
+ end
61
79
 
62
- # @private URL path for v1 of the metadata service.
63
- METADATA_PATH_BASE = "/computeMetadata/v1".freeze
80
+ ##
81
+ # The variables access object. Use this to make direct queries for
82
+ # environment variable information, or to mock out environment variables
83
+ # for testing.
84
+ #
85
+ # @return [Google::Cloud::Env::Variables]
86
+ #
87
+ attr_reader :variables
88
+
89
+ ##
90
+ # The variables access object. Use this to make direct queries for
91
+ # information from the file system, or to mock out the file system for
92
+ # testing.
93
+ #
94
+ # @return [Google::Cloud::Env::FileSystem]
95
+ #
96
+ attr_reader :file_system
64
97
 
65
- # @private URL path for metadata server root.
66
- METADATA_ROOT_PATH = "/".freeze
98
+ ##
99
+ # The compute SMBIOS access object. Use this to make direct queries for
100
+ # compute SMBIOS information, or to mock out the SMBIOS for testing.
101
+ #
102
+ # @return [Google::Cloud::Env::ComputeSMBIOS]
103
+ #
104
+ attr_reader :compute_smbios
67
105
 
68
- # @private
69
- METADATA_FAILURE_EXCEPTIONS = [
70
- Faraday::TimeoutError,
71
- Faraday::ConnectionFailed,
72
- Errno::EHOSTDOWN,
73
- Errno::ETIMEDOUT,
74
- Timeout::Error
75
- ].freeze
106
+ ##
107
+ # The compute metadata access object. Use this to make direct calls to
108
+ # compute metadata or configure how metadata server queries are done, or
109
+ # to mock out the metadata server for testing.
110
+ #
111
+ # @return [Google::Cloud::Env::ComputeMetadata]
112
+ #
113
+ attr_reader :compute_metadata
76
114
 
77
115
  ##
78
- # Create a new instance of the environment information.
79
- # Most client should not need to call this directly. Obtain a singleton
80
- # instance of the information from `Google::Cloud.env`. This constructor
81
- # is provided to allow customization of the timeout/retry settings, as
82
- # well as mocking for testing.
83
- #
84
- # @param [Hash] env Mock environment variables.
85
- # @param [String] host The hostname or IP address of the metadata server.
86
- # Optional. If not specified, uses the `GCE_METADATA_HOST`,
87
- # environment variable or falls back to `169.254.167.254`.
88
- # @param [Hash,false] metadata_cache The metadata cache. You may pass
89
- # a prepopuated cache, an empty cache (the default) or `false` to
90
- # disable the cache completely.
91
- # @param [Numeric] open_timeout Timeout for opening http connections.
92
- # Defaults to 0.1.
93
- # @param [Numeric] request_timeout Timeout for entire http requests.
94
- # Defaults to 1.0.
95
- # @param [Integer] retry_count Number of times to retry http requests.
96
- # Defaults to 1. Note that retry remains in effect even if a custom
97
- # `connection` is provided.
98
- # @param [Numeric] retry_interval Time between retries in seconds.
99
- # Defaults to 0.1.
100
- # @param [Numeric] retry_backoff_factor Multiplier applied to the retry
101
- # interval on each retry. Defaults to 1.5.
102
- # @param [Numeric] retry_max_interval Maximum time between retries in
103
- # seconds. Defaults to 0.5.
104
- # @param [Faraday::Connection] connection Faraday connection to use.
105
- # If specified, overrides the `request_timeout` and `open_timeout`
106
- # settings.
107
- #
108
- def initialize env: nil, host: nil, connection: nil, metadata_cache: nil,
109
- open_timeout: 0.1, request_timeout: 1.0,
110
- retry_count: 2, retry_interval: 0.1,
111
- retry_backoff_factor: 1.5, retry_max_interval: 0.5
112
- @disable_metadata_cache = metadata_cache == false
113
- @metadata_cache = metadata_cache || {}
114
- @env = env || ::ENV
115
- @retry_count = retry_count
116
- @retry_interval = retry_interval
117
- @retry_backoff_factor = retry_backoff_factor
118
- @retry_max_interval = retry_max_interval
119
- request_opts = { timeout: request_timeout, open_timeout: open_timeout }
120
- host ||= @env["GCE_METADATA_HOST"] || METADATA_HOST
121
- host = "http://#{host}" unless host.start_with? "http://"
122
- @connection = connection || ::Faraday.new(url: host, request: request_opts)
116
+ # Determine whether the Google Compute Engine Metadata Service is running.
117
+ #
118
+ # This method is conservative. It may block for a short period (up to
119
+ # about 1.5 seconds) while attempting to contact the server, but if this
120
+ # fails, this method will return false, even though it is possible that a
121
+ # future call could succeed. In particular, this might happen in
122
+ # environments where there is a warmup time for the Metadata Server.
123
+ # Early calls before the Server has warmed up may return false, while
124
+ # later calls return true.
125
+ #
126
+ # @return [boolean]
127
+ #
128
+ def metadata?
129
+ compute_metadata.check_existence == :confirmed
130
+ end
131
+
132
+ ##
133
+ # Assert that the Metadata Server should be present, and wait for a
134
+ # confirmed connection to ensure it is up. In general, this will run at
135
+ # most {ComputeMetadata::DEFAULT_WARMUP_TIME} seconds to wait out the
136
+ # expected maximum warmup time, but a shorter timeout can be provided.
137
+ #
138
+ # This method is useful call during application initialization to wait
139
+ # for the Metadata Server to warm up and ensure that subsequent lookups
140
+ # should succeed.
141
+ #
142
+ # @param timeout [Numeric,nil] a timeout in seconds, or nil to wait
143
+ # until we have conclusively decided one way or the other.
144
+ # @return [:confirmed] if we were able to confirm connection.
145
+ # @raise [MetadataServerNotResponding] if we were unable to confirm
146
+ # connection with the Metadata Server, either because the timeout
147
+ # expired or because the server seems to be down
148
+ #
149
+ def ensure_metadata timeout: nil
150
+ compute_metadata.ensure_existence timeout: timeout
151
+ end
152
+
153
+ ##
154
+ # Retrieve info from the Google Compute Engine Metadata Service.
155
+ # Returns `nil` if the given data is not present.
156
+ #
157
+ # @param [String] type Type of metadata to look up. Currently supported
158
+ # values are "project" and "instance".
159
+ # @param [String] entry Metadata entry path to look up.
160
+ # @param query [Hash{String => String}] Any additional query parameters
161
+ # to send with the request.
162
+ #
163
+ # @return [String] the data
164
+ # @return [nil] if there is no data for the specified type and entry
165
+ # @raise [MetadataServerNotResponding] if the Metadata Server is not
166
+ # responding. This could either be because the metadata service is
167
+ # not present in the current environment, or if it is expected to be
168
+ # present but is overloaded or has not finished initializing.
169
+ #
170
+ def lookup_metadata type, entry, query: nil
171
+ compute_metadata.lookup "#{type}/#{entry}", query: query
172
+ end
173
+
174
+ ##
175
+ # Retrieve an HTTP response from the Google Compute Engine Metadata
176
+ # Service. Returns a {ComputeMetadata::Response} with a status code,
177
+ # data, and headers. The response could be 200 for success, 404 if the
178
+ # given entry is not present, or other HTTP result code for authorization
179
+ # or other errors.
180
+ #
181
+ # @param [String] type Type of metadata to look up. Currently supported
182
+ # values are "project" and "instance".
183
+ # @param [String] entry Metadata entry path to look up.
184
+ # @param query [Hash{String => String}] Any additional query parameters
185
+ # to send with the request.
186
+ #
187
+ # @return [Google::Cloud::Env::ComputeMetadata::Response] the response
188
+ # @raise [MetadataServerNotResponding] if the Metadata Server is not
189
+ # responding. This could either be because the metadata service is
190
+ # not present in the current environment, or if it is expected to be
191
+ # present but is overloaded or has not finished initializing.
192
+ #
193
+ def lookup_metadata_response type, entry, query: nil
194
+ compute_metadata.lookup_response "#{type}/#{entry}", query: query
123
195
  end
124
196
 
125
197
  ##
126
198
  # Determine whether the application is running on a Knative-based
127
199
  # hosting platform, such as Cloud Run or Cloud Functions.
128
200
  #
129
- # @return [Boolean]
201
+ # @return [boolean]
130
202
  #
131
203
  def knative?
132
- env["K_SERVICE"] ? true : false
204
+ variables["K_SERVICE"] ? true : false
133
205
  end
134
206
 
135
207
  ##
136
208
  # Determine whether the application is running on Google App Engine.
137
209
  #
138
- # @return [Boolean]
210
+ # @return [boolean]
139
211
  #
140
212
  def app_engine?
141
- env["GAE_INSTANCE"] ? true : false
213
+ variables["GAE_INSTANCE"] ? true : false
142
214
  end
143
215
 
144
216
  ##
145
217
  # Determine whether the application is running on Google App Engine
146
218
  # Flexible Environment.
147
219
  #
148
- # @return [Boolean]
220
+ # @return [boolean]
149
221
  #
150
222
  def app_engine_flexible?
151
- app_engine? && env["GAE_ENV"] != "standard"
223
+ app_engine? && variables["GAE_ENV"] != "standard"
152
224
  end
153
225
 
154
226
  ##
155
227
  # Determine whether the application is running on Google App Engine
156
228
  # Standard Environment.
157
229
  #
158
- # @return [Boolean]
230
+ # @return [boolean]
159
231
  #
160
232
  def app_engine_standard?
161
- app_engine? && env["GAE_ENV"] == "standard"
233
+ app_engine? && variables["GAE_ENV"] == "standard"
162
234
  end
163
235
 
164
236
  ##
165
237
  # Determine whether the application is running on Google Kubernetes
166
238
  # Engine (GKE).
167
239
  #
168
- # @return [Boolean]
240
+ # @return [boolean]
169
241
  #
170
242
  def kubernetes_engine?
171
243
  kubernetes_engine_cluster_name ? true : false
@@ -175,10 +247,10 @@ module Google
175
247
  ##
176
248
  # Determine whether the application is running on Google Cloud Shell.
177
249
  #
178
- # @return [Boolean]
250
+ # @return [boolean]
179
251
  #
180
252
  def cloud_shell?
181
- env["DEVSHELL_GCLOUD_CONFIG"] ? true : false
253
+ variables["GOOGLE_CLOUD_SHELL"] ? true : false
182
254
  end
183
255
 
184
256
  ##
@@ -191,10 +263,10 @@ module Google
191
263
  # VM without using a higher level hosting product, use
192
264
  # {Env#raw_compute_engine?}.
193
265
  #
194
- # @return [Boolean]
266
+ # @return [boolean]
195
267
  #
196
268
  def compute_engine?
197
- metadata?
269
+ compute_smbios.google_compute?
198
270
  end
199
271
 
200
272
  ##
@@ -202,10 +274,10 @@ module Google
202
274
  # Engine without using a higher level hosting product such as App
203
275
  # Engine or Kubernetes Engine.
204
276
  #
205
- # @return [Boolean]
277
+ # @return [boolean]
206
278
  #
207
279
  def raw_compute_engine?
208
- !knative? && !app_engine? && !cloud_shell? && metadata? && !kubernetes_engine?
280
+ compute_engine? && !knative? && !app_engine? && !cloud_shell? && !kubernetes_engine?
209
281
  end
210
282
 
211
283
  ##
@@ -215,10 +287,12 @@ module Google
215
287
  # @return [String,nil]
216
288
  #
217
289
  def project_id
218
- env["GOOGLE_CLOUD_PROJECT"] ||
219
- env["GCLOUD_PROJECT"] ||
220
- env["DEVSHELL_PROJECT_ID"] ||
221
- lookup_metadata("project", "project-id")
290
+ variables["GOOGLE_CLOUD_PROJECT"] ||
291
+ variables["GCLOUD_PROJECT"] ||
292
+ variables["DEVSHELL_PROJECT_ID"] ||
293
+ compute_metadata.lookup("project/project-id")
294
+ rescue MetadataServerNotResponding
295
+ nil
222
296
  end
223
297
 
224
298
  ##
@@ -236,8 +310,12 @@ module Google
236
310
  # disable this for CloudShell to avoid confusion.
237
311
  return nil if cloud_shell?
238
312
 
239
- result = lookup_metadata "project", "numeric-project-id"
240
- result.nil? ? nil : result.to_i
313
+ result = begin
314
+ compute_metadata.lookup "project/numeric-project-id"
315
+ rescue MetadataServerNotResponding
316
+ nil
317
+ end
318
+ result&.to_i
241
319
  end
242
320
 
243
321
  ##
@@ -247,7 +325,9 @@ module Google
247
325
  # @return [String,nil]
248
326
  #
249
327
  def instance_name
250
- env["GAE_INSTANCE"] || lookup_metadata("instance", "name")
328
+ variables["GAE_INSTANCE"] || compute_metadata.lookup("instance/name")
329
+ rescue MetadataServerNotResponding
330
+ nil
251
331
  end
252
332
 
253
333
  ##
@@ -258,7 +338,9 @@ module Google
258
338
  # @return [String,nil]
259
339
  #
260
340
  def instance_description
261
- lookup_metadata "instance", "description"
341
+ compute_metadata.lookup "instance/description"
342
+ rescue MetadataServerNotResponding
343
+ nil
262
344
  end
263
345
 
264
346
  ##
@@ -269,8 +351,10 @@ module Google
269
351
  # @return [String,nil]
270
352
  #
271
353
  def instance_zone
272
- result = lookup_metadata "instance", "zone"
273
- result.nil? ? nil : result.split("/").last
354
+ result = compute_metadata.lookup "instance/zone"
355
+ result&.split("/")&.last
356
+ rescue MetadataServerNotResponding
357
+ nil
274
358
  end
275
359
 
276
360
  ##
@@ -280,8 +364,10 @@ module Google
280
364
  # @return [String,nil]
281
365
  #
282
366
  def instance_machine_type
283
- result = lookup_metadata "instance", "machine-type"
284
- result.nil? ? nil : result.split("/").last
367
+ result = compute_metadata.lookup "instance/machine-type"
368
+ result&.split("/")&.last
369
+ rescue MetadataServerNotResponding
370
+ nil
285
371
  end
286
372
 
287
373
  ##
@@ -292,8 +378,10 @@ module Google
292
378
  # @return [Array<String>,nil]
293
379
  #
294
380
  def instance_tags
295
- result = lookup_metadata "instance", "tags"
381
+ result = compute_metadata.lookup "instance/tags"
296
382
  result.nil? ? nil : JSON.parse(result)
383
+ rescue MetadataServerNotResponding
384
+ nil
297
385
  end
298
386
 
299
387
  ##
@@ -304,8 +392,10 @@ module Google
304
392
  # @return [Array<String>,nil]
305
393
  #
306
394
  def instance_attribute_keys
307
- result = lookup_metadata "instance", "attributes/"
308
- result.nil? ? nil : result.split
395
+ result = compute_metadata.lookup "instance/attributes/"
396
+ result&.split
397
+ rescue MetadataServerNotResponding
398
+ nil
309
399
  end
310
400
 
311
401
  ##
@@ -317,7 +407,9 @@ module Google
317
407
  # @return [String,nil]
318
408
  #
319
409
  def instance_attribute key
320
- lookup_metadata "instance", "attributes/#{key}"
410
+ compute_metadata.lookup "instance/attributes/#{key}"
411
+ rescue MetadataServerNotResponding
412
+ nil
321
413
  end
322
414
 
323
415
  ##
@@ -327,7 +419,7 @@ module Google
327
419
  # @return [String,nil]
328
420
  #
329
421
  def knative_service_id
330
- env["K_SERVICE"]
422
+ variables["K_SERVICE"]
331
423
  end
332
424
  alias knative_service_name knative_service_id
333
425
 
@@ -338,7 +430,7 @@ module Google
338
430
  # @return [String,nil]
339
431
  #
340
432
  def knative_service_revision
341
- env["K_REVISION"]
433
+ variables["K_REVISION"]
342
434
  end
343
435
 
344
436
  ##
@@ -348,7 +440,7 @@ module Google
348
440
  # @return [String,nil]
349
441
  #
350
442
  def app_engine_service_id
351
- env["GAE_SERVICE"]
443
+ variables["GAE_SERVICE"]
352
444
  end
353
445
  alias app_engine_service_name app_engine_service_id
354
446
 
@@ -359,7 +451,7 @@ module Google
359
451
  # @return [String,nil]
360
452
  #
361
453
  def app_engine_service_version
362
- env["GAE_VERSION"]
454
+ variables["GAE_VERSION"]
363
455
  end
364
456
 
365
457
  ##
@@ -369,8 +461,8 @@ module Google
369
461
  # @return [Integer,nil]
370
462
  #
371
463
  def app_engine_memory_mb
372
- result = env["GAE_MEMORY_MB"]
373
- result.nil? ? nil : result.to_i
464
+ result = variables["GAE_MEMORY_MB"]
465
+ result&.to_i
374
466
  end
375
467
 
376
468
  ##
@@ -382,6 +474,8 @@ module Google
382
474
  #
383
475
  def kubernetes_engine_cluster_name
384
476
  instance_attribute "cluster-name"
477
+ rescue MetadataServerNotResponding
478
+ nil
385
479
  end
386
480
  alias container_engine_cluster_name kubernetes_engine_cluster_name
387
481
 
@@ -398,55 +492,11 @@ module Google
398
492
  # below is set in some older versions of GKE, and the file below is
399
493
  # present in Kubernetes as of version 1.9, but it is possible that
400
494
  # alternatives will need to be found in the future.
401
- env["GKE_NAMESPACE_ID"] || ::IO.read("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
402
- rescue SystemCallError
403
- nil
495
+ variables["GKE_NAMESPACE_ID"] ||
496
+ file_system.read("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
404
497
  end
405
498
  alias container_engine_namespace_id kubernetes_engine_namespace_id
406
499
 
407
- ##
408
- # Determine whether the Google Compute Engine Metadata Service is running.
409
- #
410
- # @return [Boolean]
411
- #
412
- def metadata?
413
- path = METADATA_ROOT_PATH
414
- if @disable_metadata_cache || !metadata_cache.include?(path)
415
- metadata_cache[path] = retry_or_fail_with false do
416
- resp = connection.get path do |req|
417
- req.headers = { "Metadata-Flavor" => "Google" }
418
- end
419
- resp.status == 200 && resp.headers["Metadata-Flavor"] == "Google"
420
- end
421
- end
422
- metadata_cache[path]
423
- end
424
-
425
- ##
426
- # Retrieve info from the Google Compute Engine Metadata Service.
427
- # Returns `nil` if the Metadata Service is not running or the given
428
- # data is not present.
429
- #
430
- # @param [String] type Type of metadata to look up. Currently supported
431
- # values are "project" and "instance".
432
- # @param [String] entry Metadata entry path to look up.
433
- # @return [String,nil]
434
- #
435
- def lookup_metadata type, entry
436
- return nil unless metadata?
437
-
438
- path = "#{METADATA_PATH_BASE}/#{type}/#{entry}"
439
- if @disable_metadata_cache || !metadata_cache.include?(path)
440
- metadata_cache[path] = retry_or_fail_with nil do
441
- resp = connection.get path do |req|
442
- req.headers = { "Metadata-Flavor" => "Google" }
443
- end
444
- resp.status == 200 ? resp.body.strip : nil
445
- end
446
- end
447
- metadata_cache[path]
448
- end
449
-
450
500
  ##
451
501
  # Returns the global instance of {Google::Cloud::Env}.
452
502
  #
@@ -455,29 +505,6 @@ module Google
455
505
  def self.get
456
506
  ::Google::Cloud.env
457
507
  end
458
-
459
- private
460
-
461
- attr_reader :connection
462
- attr_reader :env
463
- attr_reader :metadata_cache
464
-
465
- def retry_or_fail_with error_result
466
- retries_remaining = @retry_count
467
- retry_interval = @retry_interval
468
- begin
469
- yield
470
- rescue *METADATA_FAILURE_EXCEPTIONS
471
- retries_remaining -= 1
472
- if retries_remaining >= 0
473
- sleep retry_interval
474
- retry_interval *= @retry_backoff_factor
475
- retry_interval = @retry_max_interval if retry_interval > @retry_max_interval
476
- retry
477
- end
478
- error_result
479
- end
480
- end
481
508
  end
482
509
 
483
510
  @env = Env.new