google-cloud-env 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 743c1259c72af3a3cd7872d88adfa2d4ba8d4850733dfba06403ad9014e510fb
4
- data.tar.gz: f1d426cd09a3591e4e60e95c0d47ada831ec498bdfc04ab709a90c6333cae560
3
+ metadata.gz: 86778304c7001d745acd20f90528b22a5e03c2c048f522cedd8e99ab1f50bf24
4
+ data.tar.gz: '05291246aa4fb33c473f2fa9bceefdc921460b4424174ef357707e07c2c832bc'
5
5
  SHA512:
6
- metadata.gz: f851d76b537d777a94973491da78ab454dbcbe23f1809ce981d86a654a28af8e1b22c7f2595ea3d4a5c64d0648d263790a61fa36e56a63eb70f83ff9a0862922
7
- data.tar.gz: 6b2160f8ab772f8af3bdbc8ee613cbc33e92310d99ac36dbf9a8962a8c75f5db6a6a7145c1560e2aa73e51d5e07acb04d3aa4638d222d2814de5288b043686b5
6
+ metadata.gz: 3900d323cdddef329f2edc4b17f7098dda5edac5378bfb11fc1311b23dc0680eb83d8f18bef86ad95baeb46315c7466551e7a0c5badf31924d3f6862ff05b1f5
7
+ data.tar.gz: 5ba1b0660ab4ee0e04f34cec0cee72ef3fda2fe7aa52e14dfb159db4c0a89d9cc38cf215d2606b900c1f0c25f9fc77d942b377ab678179859ac23be23dadfc5e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Release History
2
2
 
3
+ ### 2.1.0 (2023-12-12)
4
+
5
+ #### Features
6
+
7
+ * Provide retrieval_monotonic_time on compute metadata response objects ([#62](https://github.com/googleapis/ruby-cloud-env/issues/62))
8
+
9
+ ### 2.0.1 (2023-12-01)
10
+
11
+ #### Bug Fixes
12
+
13
+ * Bad response status or flavor headers no longer signal positive metadata existence ([#61](https://github.com/googleapis/ruby-cloud-env/issues/61))
14
+ * Increase token expiry buffer to three and a half minutes ([#59](https://github.com/googleapis/ruby-cloud-env/issues/59))
15
+
3
16
  ### 2.0.0 (2023-11-14)
4
17
 
5
18
  This is a major overhaul of the mechanisms underlying this gem, to improve reliability and provide better mocking interfaces. Environment interrogation calls are unchanged, but the mocking override parameters from 1.x have been removed in favor of the new interfaces, hence the semver-major version bump.
@@ -89,7 +89,8 @@ module Google
89
89
  # {ComputeMetadata#lookup_response}.
90
90
  #
91
91
  # This object duck-types the `status`, `body`, and `headers` fields of
92
- # `Faraday::Response`.
92
+ # `Faraday::Response`. It also includes the CLOCK_MONOTONIC time when
93
+ # the data was retrieved.
93
94
  #
94
95
  class Response
95
96
  ##
@@ -105,6 +106,7 @@ module Google
105
106
  @status = status
106
107
  @body = body
107
108
  @headers = headers
109
+ @retrieval_monotonic_time = Process.clock_gettime Process::CLOCK_MONOTONIC
108
110
  end
109
111
 
110
112
  ##
@@ -124,6 +126,19 @@ module Google
124
126
  # @return [Hash{String=>String}]
125
127
  #
126
128
  attr_reader :headers
129
+
130
+ # The CLOCK_MONOTONIC time at which this response was retrieved.
131
+ # @return [Numeric]
132
+ #
133
+ attr_reader :retrieval_monotonic_time
134
+
135
+ ##
136
+ # Returns true if the metadata-flavor is correct for Google Cloud
137
+ # @return [boolean]
138
+ #
139
+ def google_flavor?
140
+ headers["Metadata-Flavor"] == "Google"
141
+ end
127
142
  end
128
143
 
129
144
  ##
@@ -233,20 +248,10 @@ module Google
233
248
  compute_smbios: nil
234
249
  @variables = variables || Variables.new
235
250
  @compute_smbios = compute_smbios || ComputeSMBIOS.new
236
- self.host = nil
237
- @connection = Faraday.new url: host
238
- self.open_timeout = DEFAULT_OPEN_TIMEOUT
239
- self.request_timeout = DEFAULT_REQUEST_TIMEOUT
240
- self.retry_count = DEFAULT_RETRY_COUNT
241
- self.retry_timeout = DEFAULT_RETRY_TIMEOUT
242
- self.retry_interval = DEFAULT_RETRY_INTERVAL
243
- self.warmup_time = DEFAULT_WARMUP_TIME
244
- @cache = create_cache
245
251
  # This mutex protects the overrides and existence settings.
246
252
  # Those values won't change within a synchronize block.
247
253
  @mutex = Thread::Mutex.new
248
- reset_existence!
249
- @overrides = nil
254
+ reset!
250
255
  end
251
256
 
252
257
  ##
@@ -443,7 +448,7 @@ module Google
443
448
  request_timeout: request_timeout,
444
449
  retry_count: retry_count,
445
450
  retry_timeout: retry_timeout
446
- return nil unless response.status == 200 && response.headers["Metadata-Flavor"] == "Google"
451
+ return nil unless response.status == 200 && response.google_flavor?
447
452
  response.body
448
453
  end
449
454
 
@@ -618,6 +623,26 @@ module Google
618
623
  #
619
624
  attr_reader :compute_smbios
620
625
 
626
+ ##
627
+ # @private
628
+ # Reset the cache, overrides, and all settings to default, for testing.
629
+ #
630
+ def reset!
631
+ @mutex.synchronize do
632
+ self.host = nil
633
+ @connection = Faraday.new url: host
634
+ self.open_timeout = DEFAULT_OPEN_TIMEOUT
635
+ self.request_timeout = DEFAULT_REQUEST_TIMEOUT
636
+ self.retry_count = DEFAULT_RETRY_COUNT
637
+ self.retry_timeout = DEFAULT_RETRY_TIMEOUT
638
+ self.retry_interval = DEFAULT_RETRY_INTERVAL
639
+ self.warmup_time = DEFAULT_WARMUP_TIME
640
+ @cache = create_cache
641
+ @overrides = nil
642
+ end
643
+ reset_existence!
644
+ end
645
+
621
646
  ##
622
647
  # @private
623
648
  # Clear the existence cache, for testing.
@@ -627,6 +652,7 @@ module Google
627
652
  @existence = nil
628
653
  @startup_time = Process.clock_gettime Process::CLOCK_MONOTONIC
629
654
  end
655
+ self
630
656
  end
631
657
 
632
658
  private
@@ -645,6 +671,29 @@ module Google
645
671
  Timeout::Error
646
672
  ].freeze
647
673
 
674
+ ##
675
+ # @private
676
+ #
677
+ # A buffer in seconds for token expiry. Our cache for the token will
678
+ # expire approximately this many seconds before the declared expiry
679
+ # time of the token itself.
680
+ #
681
+ # We want this value to be positive so that we provide some buffer to
682
+ # offset any clock skew and Metadata Server latency that might affect
683
+ # our calculation of the expiry time, but more importantly so that a
684
+ # client has approximately this amount of time to use a token we give
685
+ # them before it expires.
686
+ #
687
+ # We don't want this to be much higher, however, to keep the load down
688
+ # on the Metadata Server. We've been advised by the compute/serverless
689
+ # engineering teams to set this value less than 4 minutes because the
690
+ # Metadata Server can refresh the token as late as 4 minutes before the
691
+ # actual expiry of the previous token. If our cache expires and we
692
+ # request a new token, we actually want to receive a new token rather
693
+ # than the previous old token. See internal issue b/311414224.
694
+ #
695
+ TOKEN_EXPIRY_BUFFER = 210
696
+
648
697
  ##
649
698
  # @private
650
699
  #
@@ -708,8 +757,12 @@ module Google
708
757
  req.options.timeout = request_timeout if request_timeout
709
758
  req.options.open_timeout = open_timeout if open_timeout
710
759
  end
711
- post_update_existence true
712
760
  response = Response.new http_response.status, http_response.body, http_response.headers
761
+ if path.nil?
762
+ post_update_existence(response.status == 200 && response.google_flavor?, response.retrieval_monotonic_time)
763
+ elsif response.google_flavor?
764
+ post_update_existence true, response.retrieval_monotonic_time
765
+ end
713
766
  lifetime = determine_data_lifetime path, response.body.strip
714
767
  LazyValue.expiring_value lifetime, response
715
768
  rescue *TRANSIENT_EXCEPTIONS
@@ -721,14 +774,14 @@ module Google
721
774
  # @private
722
775
  # Update existence based on a received result
723
776
  #
724
- def post_update_existence success
777
+ def post_update_existence success, current_time = nil
725
778
  return if @existence == :confirmed
726
779
  @mutex.synchronize do
727
780
  if success
728
781
  @existence = :confirmed
729
- elsif @existence != :confirmed &&
730
- Process.clock_gettime(Process::CLOCK_MONOTONIC) > @startup_time + warmup_time
731
- @existence = :no
782
+ elsif @existence != :confirmed
783
+ current_time ||= Process.clock_gettime Process::CLOCK_MONOTONIC
784
+ @existence = :no if current_time > @startup_time + warmup_time
732
785
  end
733
786
  end
734
787
  end
@@ -754,8 +807,7 @@ module Google
754
807
  def access_token_lifetime data
755
808
  json = JSON.parse data rescue nil
756
809
  return 0 unless json&.key? "expires_in"
757
- # Buffer of 10 seconds to account for MDS latency
758
- lifetime = json["expires_in"].to_i - 10
810
+ lifetime = json["expires_in"].to_i - TOKEN_EXPIRY_BUFFER
759
811
  lifetime = 0 if lifetime.negative?
760
812
  lifetime
761
813
  end
@@ -769,8 +821,7 @@ module Google
769
821
  base64 = Base64.decode64 Regexp.last_match[1]
770
822
  json = JSON.parse base64 rescue nil
771
823
  return 0 unless json&.key? "exp"
772
- # Buffer of 10 seconds in case of clock skew
773
- lifetime = json["exp"].to_i - Time.now.to_i - 10
824
+ lifetime = json["exp"].to_i - Time.now.to_i - TOKEN_EXPIRY_BUFFER
774
825
  lifetime = 0 if lifetime.negative?
775
826
  lifetime
776
827
  end
@@ -20,7 +20,7 @@ module Google
20
20
  # Library version
21
21
  # @return [String]
22
22
  #
23
- VERSION = "2.0.0".freeze
23
+ VERSION = "2.1.0".freeze
24
24
  end
25
25
  end
26
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-env
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-15 00:00:00.000000000 Z
11
+ date: 2023-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -59,10 +59,10 @@ homepage: https://github.com/googleapis/ruby-cloud-env
59
59
  licenses:
60
60
  - Apache-2.0
61
61
  metadata:
62
- changelog_uri: https://rubydoc.info/gems/google-cloud-env/2.0.0/CHANGELOG.md
62
+ changelog_uri: https://rubydoc.info/gems/google-cloud-env/2.1.0/CHANGELOG.md
63
63
  source_code_uri: https://github.com/googleapis/ruby-cloud-env
64
64
  bug_tracker_uri: https://github.com/googleapis/ruby-cloud-env/issues
65
- documentation_uri: https://rubydoc.info/gems/google-cloud-env/2.0.0
65
+ documentation_uri: https://rubydoc.info/gems/google-cloud-env/2.1.0
66
66
  post_install_message:
67
67
  rdoc_options: []
68
68
  require_paths: