From 0af46f872bb6748c1cbcb80f6385216000051770 Mon Sep 17 00:00:00 2001 From: Baha Aiman Date: Tue, 22 Oct 2024 19:36:38 +0000 Subject: [PATCH 1/6] feat: Add async refresh dry run --- transport/grpc/dial.go | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/transport/grpc/dial.go b/transport/grpc/dial.go index ff3539d898..e7acf75d3c 100644 --- a/transport/grpc/dial.go +++ b/transport/grpc/dial.go @@ -10,9 +10,11 @@ package grpc import ( "context" "errors" + "fmt" "log" "net" "os" + "strconv" "strings" "sync" "time" @@ -38,6 +40,8 @@ import ( _ "google.golang.org/grpc/balancer/grpclb" ) +const dryRunAsyncRefresh = "GOOGLE_API_GO_EXPERIMENTAL_ASYNC_REFRESH_DRY_RUN" + // Check env to disable DirectPath traffic. const disableDirectPath = "GOOGLE_CLOUD_DISABLE_DIRECT_PATH" @@ -261,6 +265,32 @@ func prepareDialOptsNewAuth(ds *internal.DialSettings) []grpc.DialOption { return append(opts, ds.GRPCDialOpts...) } +// dryRunAsync is a wrapper for oauth2.TokenSource that performs a sync refresh +// after an async refresh. Token generated by async refresh is not used +// +// This is an experimental feature and may be removed or changed in the future. +// It is a temporary struct to determine if the async refresh +// is working properly. +type dryRunAsync struct { + asyncTokenSource oauth2.TokenSource + syncTokenSource oauth2.TokenSource +} + +func newDryRunAsync(ts oauth2.TokenSource) dryRunAsync { + tp := auth.NewCachedTokenProvider(oauth2adapt.TokenProviderFromTokenSource(ts), nil) + asyncTs := oauth2adapt.TokenSourceFromTokenProvider(tp) + return dryRunAsync{syncTokenSource: ts, asyncTokenSource: asyncTs} +} + +// Token returns a token or an error. +func (async dryRunAsync) Token() (*oauth2.Token, error) { + _, err := async.asyncTokenSource.Token() + if err != nil { + fmt.Printf("Error during async refresh of token: %+v", err) + } + return async.syncTokenSource.Token() +} + func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.ClientConn, error) { if o.HTTPClient != nil { return nil, errors.New("unsupported HTTP client specified") @@ -297,8 +327,13 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C if err != nil { return nil, err } + + ts := creds.TokenSource + if b, err := strconv.ParseBool(os.Getenv(dryRunAsyncRefresh)); err == nil && b { + ts = newDryRunAsync(ts) + } grpcOpts = append(grpcOpts, grpc.WithPerRPCCredentials(grpcTokenSource{ - TokenSource: oauth.TokenSource{TokenSource: creds.TokenSource}, + TokenSource: oauth.TokenSource{TokenSource: ts}, quotaProject: internal.GetQuotaProject(creds, o.QuotaProject), requestReason: o.RequestReason, })) From 25ffb46a28b04110b47d2202897961221f05e9ae Mon Sep 17 00:00:00 2001 From: Baha Aiman Date: Thu, 31 Oct 2024 00:14:14 +0000 Subject: [PATCH 2/6] add meter provider and attributes --- go.mod | 4 ++-- internal/settings.go | 8 ++++++-- option/internaloption/internaloption.go | 22 ++++++++++++++++++++++ transport/grpc/dial.go | 24 ++++++++++++++++-------- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 925de4b973..8dd05b7762 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,8 @@ require ( go.opencensus.io v0.24.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 + go.opentelemetry.io/otel v1.29.0 + go.opentelemetry.io/otel/metric v1.29.0 golang.org/x/net v0.30.0 golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.8.0 @@ -31,8 +33,6 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - go.opentelemetry.io/otel v1.29.0 // indirect - go.opentelemetry.io/otel/metric v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect golang.org/x/crypto v0.28.0 // indirect golang.org/x/sys v0.26.0 // indirect diff --git a/internal/settings.go b/internal/settings.go index 32949cccbd..a8dde44be1 100644 --- a/internal/settings.go +++ b/internal/settings.go @@ -14,6 +14,8 @@ import ( "time" "cloud.google.com/go/auth" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" "golang.org/x/oauth2" "golang.org/x/oauth2/google" "google.golang.org/api/internal/impersonate" @@ -68,8 +70,10 @@ type DialSettings struct { RequestReason string // New Auth library Options - AuthCredentials *auth.Credentials - EnableNewAuthLibrary bool + AuthCredentials *auth.Credentials + EnableNewAuthLibrary bool + EnableAsyncRefreshDryRun metric.Int64Counter + ClientAttributes []attribute.KeyValue } // GetScopes returns the user-provided scopes, if set, or else falls back to the diff --git a/option/internaloption/internaloption.go b/option/internaloption/internaloption.go index e6b5c10255..dd9699b61d 100644 --- a/option/internaloption/internaloption.go +++ b/option/internaloption/internaloption.go @@ -6,6 +6,8 @@ package internaloption import ( + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" "golang.org/x/oauth2/google" "google.golang.org/api/internal" "google.golang.org/api/option" @@ -206,6 +208,26 @@ func (w enableNewAuthLibrary) Apply(o *internal.DialSettings) { o.EnableNewAuthLibrary = bool(w) } +// EnableAsyncRefreshDryRun returns a ClientOption that specifies if libraries in this +// module should asynchronously refresh auth token in parallel to sync refresh +// This is an experimental option and will be removed in the future +func EnableAsyncRefreshDryRun(errCounter metric.Int64Counter, clientAttributes []attribute.KeyValue) option.ClientOption { + return enableAsyncRefreshDryRun{ + errCounter: errCounter, + clientAttributes: clientAttributes, + } +} + +type enableAsyncRefreshDryRun struct { + errCounter metric.Int64Counter + clientAttributes []attribute.KeyValue +} + +func (w enableAsyncRefreshDryRun) Apply(o *internal.DialSettings) { + o.EnableAsyncRefreshDryRun = w.errCounter + o.ClientAttributes = w.clientAttributes +} + // EmbeddableAdapter is a no-op option.ClientOption that allow libraries to // create their own client options by embedding this type into their own // client-specific option wrapper. See example for usage. diff --git a/transport/grpc/dial.go b/transport/grpc/dial.go index e7acf75d3c..9994e0d013 100644 --- a/transport/grpc/dial.go +++ b/transport/grpc/dial.go @@ -14,7 +14,6 @@ import ( "log" "net" "os" - "strconv" "strings" "sync" "time" @@ -26,6 +25,8 @@ import ( "cloud.google.com/go/compute/metadata" "go.opencensus.io/plugin/ocgrpc" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" "golang.org/x/oauth2" "golang.org/x/time/rate" "google.golang.org/api/internal" @@ -40,8 +41,6 @@ import ( _ "google.golang.org/grpc/balancer/grpclb" ) -const dryRunAsyncRefresh = "GOOGLE_API_GO_EXPERIMENTAL_ASYNC_REFRESH_DRY_RUN" - // Check env to disable DirectPath traffic. const disableDirectPath = "GOOGLE_CLOUD_DISABLE_DIRECT_PATH" @@ -274,20 +273,29 @@ func prepareDialOptsNewAuth(ds *internal.DialSettings) []grpc.DialOption { type dryRunAsync struct { asyncTokenSource oauth2.TokenSource syncTokenSource oauth2.TokenSource + errCounter metric.Int64Counter + clientAttributes []attribute.KeyValue } -func newDryRunAsync(ts oauth2.TokenSource) dryRunAsync { +func newDryRunAsync(ts oauth2.TokenSource, errCounter metric.Int64Counter, clientAttributes []attribute.KeyValue) dryRunAsync { tp := auth.NewCachedTokenProvider(oauth2adapt.TokenProviderFromTokenSource(ts), nil) asyncTs := oauth2adapt.TokenSourceFromTokenProvider(tp) - return dryRunAsync{syncTokenSource: ts, asyncTokenSource: asyncTs} + return dryRunAsync{syncTokenSource: ts, + asyncTokenSource: asyncTs, + errCounter: errCounter, + clientAttributes: clientAttributes, + } } // Token returns a token or an error. func (async dryRunAsync) Token() (*oauth2.Token, error) { + fmt.Println("Asynchronously refreshing token") _, err := async.asyncTokenSource.Token() - if err != nil { + if err == nil { //TODO: Change this + async.errCounter.Add(context.Background(), 1, metric.WithAttributes(async.clientAttributes...)) fmt.Printf("Error during async refresh of token: %+v", err) } + fmt.Println("Synchronously refreshing token") return async.syncTokenSource.Token() } @@ -329,8 +337,8 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C } ts := creds.TokenSource - if b, err := strconv.ParseBool(os.Getenv(dryRunAsyncRefresh)); err == nil && b { - ts = newDryRunAsync(ts) + if o.EnableAsyncRefreshDryRun != nil { + ts = newDryRunAsync(ts, o.EnableAsyncRefreshDryRun, o.ClientAttributes) } grpcOpts = append(grpcOpts, grpc.WithPerRPCCredentials(grpcTokenSource{ TokenSource: oauth.TokenSource{TokenSource: ts}, From 657cc657f992eecc33ebe0d6bfa8366525959865 Mon Sep 17 00:00:00 2001 From: Baha Aiman Date: Mon, 4 Nov 2024 19:23:44 +0000 Subject: [PATCH 3/6] adding error handler instead of metrics --- go.mod | 4 ++-- internal/settings.go | 5 +---- option/internaloption/internaloption.go | 13 ++++--------- transport/grpc/dial.go | 23 ++++++++--------------- 4 files changed, 15 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 8dd05b7762..925de4b973 100644 --- a/go.mod +++ b/go.mod @@ -15,8 +15,6 @@ require ( go.opencensus.io v0.24.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 - go.opentelemetry.io/otel v1.29.0 - go.opentelemetry.io/otel/metric v1.29.0 golang.org/x/net v0.30.0 golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.8.0 @@ -33,6 +31,8 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect golang.org/x/crypto v0.28.0 // indirect golang.org/x/sys v0.26.0 // indirect diff --git a/internal/settings.go b/internal/settings.go index a8dde44be1..c0e73ea3ad 100644 --- a/internal/settings.go +++ b/internal/settings.go @@ -14,8 +14,6 @@ import ( "time" "cloud.google.com/go/auth" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" "golang.org/x/oauth2" "golang.org/x/oauth2/google" "google.golang.org/api/internal/impersonate" @@ -72,8 +70,7 @@ type DialSettings struct { // New Auth library Options AuthCredentials *auth.Credentials EnableNewAuthLibrary bool - EnableAsyncRefreshDryRun metric.Int64Counter - ClientAttributes []attribute.KeyValue + EnableAsyncRefreshDryRun func() } // GetScopes returns the user-provided scopes, if set, or else falls back to the diff --git a/option/internaloption/internaloption.go b/option/internaloption/internaloption.go index dd9699b61d..e3b4d6142f 100644 --- a/option/internaloption/internaloption.go +++ b/option/internaloption/internaloption.go @@ -6,8 +6,6 @@ package internaloption import ( - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" "golang.org/x/oauth2/google" "google.golang.org/api/internal" "google.golang.org/api/option" @@ -211,21 +209,18 @@ func (w enableNewAuthLibrary) Apply(o *internal.DialSettings) { // EnableAsyncRefreshDryRun returns a ClientOption that specifies if libraries in this // module should asynchronously refresh auth token in parallel to sync refresh // This is an experimental option and will be removed in the future -func EnableAsyncRefreshDryRun(errCounter metric.Int64Counter, clientAttributes []attribute.KeyValue) option.ClientOption { +func EnableAsyncRefreshDryRun(callback func()) option.ClientOption { return enableAsyncRefreshDryRun{ - errCounter: errCounter, - clientAttributes: clientAttributes, + callback: callback, } } type enableAsyncRefreshDryRun struct { - errCounter metric.Int64Counter - clientAttributes []attribute.KeyValue + callback func() } func (w enableAsyncRefreshDryRun) Apply(o *internal.DialSettings) { - o.EnableAsyncRefreshDryRun = w.errCounter - o.ClientAttributes = w.clientAttributes + o.EnableAsyncRefreshDryRun = w.callback } // EmbeddableAdapter is a no-op option.ClientOption that allow libraries to diff --git a/transport/grpc/dial.go b/transport/grpc/dial.go index 9994e0d013..7057a33c99 100644 --- a/transport/grpc/dial.go +++ b/transport/grpc/dial.go @@ -10,7 +10,6 @@ package grpc import ( "context" "errors" - "fmt" "log" "net" "os" @@ -25,8 +24,6 @@ import ( "cloud.google.com/go/compute/metadata" "go.opencensus.io/plugin/ocgrpc" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" "golang.org/x/oauth2" "golang.org/x/time/rate" "google.golang.org/api/internal" @@ -273,29 +270,25 @@ func prepareDialOptsNewAuth(ds *internal.DialSettings) []grpc.DialOption { type dryRunAsync struct { asyncTokenSource oauth2.TokenSource syncTokenSource oauth2.TokenSource - errCounter metric.Int64Counter - clientAttributes []attribute.KeyValue + errHandler func() } -func newDryRunAsync(ts oauth2.TokenSource, errCounter metric.Int64Counter, clientAttributes []attribute.KeyValue) dryRunAsync { +func newDryRunAsync(ts oauth2.TokenSource, errHandler func()) dryRunAsync { tp := auth.NewCachedTokenProvider(oauth2adapt.TokenProviderFromTokenSource(ts), nil) asyncTs := oauth2adapt.TokenSourceFromTokenProvider(tp) - return dryRunAsync{syncTokenSource: ts, + return dryRunAsync{ + syncTokenSource: ts, asyncTokenSource: asyncTs, - errCounter: errCounter, - clientAttributes: clientAttributes, + errHandler: errHandler, } } // Token returns a token or an error. func (async dryRunAsync) Token() (*oauth2.Token, error) { - fmt.Println("Asynchronously refreshing token") _, err := async.asyncTokenSource.Token() - if err == nil { //TODO: Change this - async.errCounter.Add(context.Background(), 1, metric.WithAttributes(async.clientAttributes...)) - fmt.Printf("Error during async refresh of token: %+v", err) + if err != nil { + async.errHandler() } - fmt.Println("Synchronously refreshing token") return async.syncTokenSource.Token() } @@ -338,7 +331,7 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C ts := creds.TokenSource if o.EnableAsyncRefreshDryRun != nil { - ts = newDryRunAsync(ts, o.EnableAsyncRefreshDryRun, o.ClientAttributes) + ts = newDryRunAsync(ts, o.EnableAsyncRefreshDryRun) } grpcOpts = append(grpcOpts, grpc.WithPerRPCCredentials(grpcTokenSource{ TokenSource: oauth.TokenSource{TokenSource: ts}, From e27d6f42f37ca25c28244165b295db83ec1a881b Mon Sep 17 00:00:00 2001 From: Baha Aiman Date: Mon, 4 Nov 2024 19:29:30 +0000 Subject: [PATCH 4/6] Rename variable and add comment --- option/internaloption/internaloption.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/option/internaloption/internaloption.go b/option/internaloption/internaloption.go index e3b4d6142f..cb70339b04 100644 --- a/option/internaloption/internaloption.go +++ b/option/internaloption/internaloption.go @@ -208,19 +208,23 @@ func (w enableNewAuthLibrary) Apply(o *internal.DialSettings) { // EnableAsyncRefreshDryRun returns a ClientOption that specifies if libraries in this // module should asynchronously refresh auth token in parallel to sync refresh +// +// errHandler function will be called when there is an error while refreshing +// the token asynchronously +// // This is an experimental option and will be removed in the future -func EnableAsyncRefreshDryRun(callback func()) option.ClientOption { +func EnableAsyncRefreshDryRun(errHandler func()) option.ClientOption { return enableAsyncRefreshDryRun{ - callback: callback, + errHandler: errHandler, } } type enableAsyncRefreshDryRun struct { - callback func() + errHandler func() } func (w enableAsyncRefreshDryRun) Apply(o *internal.DialSettings) { - o.EnableAsyncRefreshDryRun = w.callback + o.EnableAsyncRefreshDryRun = w.errHandler } // EmbeddableAdapter is a no-op option.ClientOption that allow libraries to From 8579b8b2a64dd5da7c3d8542bcca1c339759f606 Mon Sep 17 00:00:00 2001 From: Baha Aiman Date: Tue, 26 Nov 2024 19:04:27 +0000 Subject: [PATCH 5/6] adding more comments --- internal/settings.go | 6 ++++-- option/internaloption/internaloption.go | 14 ++++++++++---- transport/grpc/dial.go | 8 ++++++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/internal/settings.go b/internal/settings.go index 44cfdb5fa4..4f5b1a0ebe 100644 --- a/internal/settings.go +++ b/internal/settings.go @@ -70,8 +70,10 @@ type DialSettings struct { RequestReason string // New Auth library Options - AuthCredentials *auth.Credentials - EnableNewAuthLibrary bool + AuthCredentials *auth.Credentials + EnableNewAuthLibrary bool + + // TODO(b/372244283): Remove after b/358175516 has been fixed EnableAsyncRefreshDryRun func() } diff --git a/option/internaloption/internaloption.go b/option/internaloption/internaloption.go index 32a0c72719..647ea4cca9 100644 --- a/option/internaloption/internaloption.go +++ b/option/internaloption/internaloption.go @@ -209,23 +209,29 @@ func (w enableNewAuthLibrary) Apply(o *internal.DialSettings) { o.EnableNewAuthLibrary = bool(w) } -// EnableAsyncRefreshDryRun returns a ClientOption that specifies if libraries in this -// module should asynchronously refresh auth token in parallel to sync refresh +// EnableAsyncRefreshDryRun returns a ClientOption that specifies if libraries in this +// module should asynchronously refresh auth token in parallel to sync refresh. +// +// This option can be used to determine whether refreshing the token asymnchronously +// prior to its actual expiry works without any issues in a particular environment. // // errHandler function will be called when there is an error while refreshing -// the token asynchronously +// the token asynchronously. // -// This is an experimental option and will be removed in the future +// This is an EXPERIMENTAL option and will be removed in the future. +// TODO(b/372244283): Remove after b/358175516 has been fixed func EnableAsyncRefreshDryRun(errHandler func()) option.ClientOption { return enableAsyncRefreshDryRun{ errHandler: errHandler, } } +// TODO(b/372244283): Remove after b/358175516 has been fixed type enableAsyncRefreshDryRun struct { errHandler func() } +// TODO(b/372244283): Remove after b/358175516 has been fixed func (w enableAsyncRefreshDryRun) Apply(o *internal.DialSettings) { o.EnableAsyncRefreshDryRun = w.errHandler } diff --git a/transport/grpc/dial.go b/transport/grpc/dial.go index ef38d91ec5..4015df6303 100644 --- a/transport/grpc/dial.go +++ b/transport/grpc/dial.go @@ -263,17 +263,19 @@ func prepareDialOptsNewAuth(ds *internal.DialSettings) []grpc.DialOption { } // dryRunAsync is a wrapper for oauth2.TokenSource that performs a sync refresh -// after an async refresh. Token generated by async refresh is not used +// after an async refresh. Token generated by async refresh is not used. // -// This is an experimental feature and may be removed or changed in the future. +// This is an EXPERIMENTAL feature and may be removed or changed in the future. // It is a temporary struct to determine if the async refresh // is working properly. +// TODO(b/372244283): Remove after b/358175516 has been fixed type dryRunAsync struct { asyncTokenSource oauth2.TokenSource syncTokenSource oauth2.TokenSource errHandler func() } +// TODO(b/372244283): Remove after b/358175516 has been fixed func newDryRunAsync(ts oauth2.TokenSource, errHandler func()) dryRunAsync { tp := auth.NewCachedTokenProvider(oauth2adapt.TokenProviderFromTokenSource(ts), nil) asyncTs := oauth2adapt.TokenSourceFromTokenProvider(tp) @@ -285,6 +287,7 @@ func newDryRunAsync(ts oauth2.TokenSource, errHandler func()) dryRunAsync { } // Token returns a token or an error. +// TODO(b/372244283): Remove after b/358175516 has been fixed func (async dryRunAsync) Token() (*oauth2.Token, error) { _, err := async.asyncTokenSource.Token() if err != nil { @@ -331,6 +334,7 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C } ts := creds.TokenSource + // TODO(b/372244283): Remove after b/358175516 has been fixed if o.EnableAsyncRefreshDryRun != nil { ts = newDryRunAsync(ts, o.EnableAsyncRefreshDryRun) } From a33ff5d54473a7bb9b89030ca60c0ec5cb0cd90a Mon Sep 17 00:00:00 2001 From: Baha Aiman Date: Wed, 27 Nov 2024 20:20:42 +0000 Subject: [PATCH 6/6] Updating oauth2adapt --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 702d756041..5814f4b252 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( cloud.google.com/go v0.116.0 cloud.google.com/go/auth v0.10.2 - cloud.google.com/go/auth/oauth2adapt v0.2.5 + cloud.google.com/go/auth/oauth2adapt v0.2.6 cloud.google.com/go/compute/metadata v0.5.2 github.com/google/go-cmp v0.6.0 github.com/google/s2a-go v0.1.8 diff --git a/go.sum b/go.sum index 95c5efc4db..8b1f0f95cb 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.10.2 h1:oKF7rgBfSHdp/kuhXtqU/tNDr0mZqhYbEh+6SiqzkKo= cloud.google.com/go/auth v0.10.2/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= -cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= -cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=