diff --git a/go.mod b/go.mod index f550efaac1f82..3980e4790c122 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.23.1 require ( cloud.google.com/go/bigtable v1.33.0 cloud.google.com/go/pubsub v1.45.1 - cloud.google.com/go/storage v1.46.0 + cloud.google.com/go/storage v1.47.0 github.com/Azure/azure-pipeline-go v0.2.3 github.com/Azure/azure-storage-blob-go v0.15.0 github.com/Azure/go-autorest/autorest/adal v0.9.24 @@ -158,7 +158,7 @@ require ( require ( cel.dev/expr v0.16.1 // indirect - cloud.google.com/go/auth v0.10.0 // indirect + cloud.google.com/go/auth v0.10.2 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect cloud.google.com/go/monitoring v1.21.1 // indirect dario.cat/mergo v1.0.1 // indirect diff --git a/go.sum b/go.sum index 4d7297b503eee..a1c5a845e3bec 100644 --- a/go.sum +++ b/go.sum @@ -117,8 +117,8 @@ cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEar cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/auth v0.10.0 h1:tWlkvFAh+wwTOzXIjrwM64karR1iTBZ/GRr0S/DULYo= -cloud.google.com/go/auth v0.10.0/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +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/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= @@ -661,8 +661,8 @@ cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= -cloud.google.com/go/storage v1.46.0 h1:OTXISBpFd8KaA2ClT3K3oRk8UGOcTHtrZ1bW88xKiic= -cloud.google.com/go/storage v1.46.0/go.mod h1:lM+gMAW91EfXIeMTBmixRsKL/XCxysytoAgduVikjMk= +cloud.google.com/go/storage v1.47.0 h1:ajqgt30fnOMmLfWfu1PWcb+V9Dxz6n+9WKjdNg5R4HM= +cloud.google.com/go/storage v1.47.0/go.mod h1:Ks0vP374w0PW6jOUameJbapbQKXqkjGd/OJRp2fb9IQ= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= @@ -2751,6 +2751,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9RO go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= diff --git a/vendor/cloud.google.com/go/auth/CHANGES.md b/vendor/cloud.google.com/go/auth/CHANGES.md index ecdc47daba4f9..a754df909f6d3 100644 --- a/vendor/cloud.google.com/go/auth/CHANGES.md +++ b/vendor/cloud.google.com/go/auth/CHANGES.md @@ -1,5 +1,20 @@ # Changelog +## [0.10.2](https://github.com/googleapis/google-cloud-go/compare/auth/v0.10.1...auth/v0.10.2) (2024-11-12) + + +### Bug Fixes + +* **auth:** Restore use of grpc.Dial ([#11118](https://github.com/googleapis/google-cloud-go/issues/11118)) ([2456b94](https://github.com/googleapis/google-cloud-go/commit/2456b943b7b8aaabd4d8bfb7572c0f477ae0db45)), refs [#7556](https://github.com/googleapis/google-cloud-go/issues/7556) + +## [0.10.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.10.0...auth/v0.10.1) (2024-11-06) + + +### Bug Fixes + +* **auth:** Restore Application Default Credentials support to idtoken ([#11083](https://github.com/googleapis/google-cloud-go/issues/11083)) ([8771f2e](https://github.com/googleapis/google-cloud-go/commit/8771f2ea9807ab822083808e0678392edff3b4f2)) +* **auth:** Skip impersonate universe domain check if empty ([#11086](https://github.com/googleapis/google-cloud-go/issues/11086)) ([87159c1](https://github.com/googleapis/google-cloud-go/commit/87159c1059d4a18d1367ce62746a838a94964ab6)) + ## [0.10.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.9.9...auth/v0.10.0) (2024-10-30) diff --git a/vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go b/vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go index 42d4cbe3062ed..38212ed0f82a0 100644 --- a/vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go +++ b/vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go @@ -322,7 +322,7 @@ func dial(ctx context.Context, secure bool, opts *Options) (*grpc.ClientConn, er grpcOpts = addOpenTelemetryStatsHandler(grpcOpts, opts) grpcOpts = append(grpcOpts, opts.GRPCDialOpts...) - return grpc.NewClient(endpoint, grpcOpts...) + return grpc.Dial(endpoint, grpcOpts...) } // grpcKeyProvider satisfies https://pkg.go.dev/google.golang.org/grpc/credentials#PerRPCCredentials. diff --git a/vendor/cloud.google.com/go/auth/httptransport/httptransport.go b/vendor/cloud.google.com/go/auth/httptransport/httptransport.go index 38e8c99399bb3..cbe5a7a40a77a 100644 --- a/vendor/cloud.google.com/go/auth/httptransport/httptransport.go +++ b/vendor/cloud.google.com/go/auth/httptransport/httptransport.go @@ -147,8 +147,13 @@ type InternalOptions struct { // service. DefaultScopes []string // SkipValidation bypasses validation on Options. It should only be used - // internally for clients that needs more control over their transport. + // internally for clients that need more control over their transport. SkipValidation bool + // SkipUniverseDomainValidation skips the verification that the universe + // domain configured for the client matches the universe domain configured + // for the credentials. It should only be used internally for clients that + // need more control over their transport. The default is false. + SkipUniverseDomainValidation bool } // AddAuthorizationMiddleware adds a middleware to the provided client's diff --git a/vendor/cloud.google.com/go/auth/httptransport/transport.go b/vendor/cloud.google.com/go/auth/httptransport/transport.go index 63498ee792be9..1d139b9dc49eb 100644 --- a/vendor/cloud.google.com/go/auth/httptransport/transport.go +++ b/vendor/cloud.google.com/go/auth/httptransport/transport.go @@ -86,11 +86,16 @@ func newTransport(base http.RoundTripper, opts *Options) (http.RoundTripper, err headers.Set(quotaProjectHeaderKey, qp) } } + var skipUD bool + if iOpts := opts.InternalOptions; iOpts != nil { + skipUD = iOpts.SkipUniverseDomainValidation + } creds.TokenProvider = auth.NewCachedTokenProvider(creds.TokenProvider, nil) trans = &authTransport{ - base: trans, - creds: creds, - clientUniverseDomain: opts.UniverseDomain, + base: trans, + creds: creds, + clientUniverseDomain: opts.UniverseDomain, + skipUniverseDomainValidation: skipUD, } } return trans, nil @@ -185,9 +190,10 @@ func addOCTransport(trans http.RoundTripper, opts *Options) http.RoundTripper { } type authTransport struct { - creds *auth.Credentials - base http.RoundTripper - clientUniverseDomain string + creds *auth.Credentials + base http.RoundTripper + clientUniverseDomain string + skipUniverseDomainValidation bool } // getClientUniverseDomain returns the default service domain for a given Cloud @@ -226,7 +232,7 @@ func (t *authTransport) RoundTrip(req *http.Request) (*http.Response, error) { if err != nil { return nil, err } - if token.MetadataString("auth.google.tokenSource") != "compute-metadata" { + if !t.skipUniverseDomainValidation && token.MetadataString("auth.google.tokenSource") != "compute-metadata" { credentialsUniverseDomain, err := t.creds.UniverseDomain(req.Context()) if err != nil { return nil, err diff --git a/vendor/cloud.google.com/go/storage/CHANGES.md b/vendor/cloud.google.com/go/storage/CHANGES.md index 7b1b063367345..b06751bc81790 100644 --- a/vendor/cloud.google.com/go/storage/CHANGES.md +++ b/vendor/cloud.google.com/go/storage/CHANGES.md @@ -1,6 +1,18 @@ # Changes +## [1.47.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.46.0...storage/v1.47.0) (2024-11-14) + + +### Features + +* **storage:** Introduce dp detector based on grpc metrics ([#11100](https://github.com/googleapis/google-cloud-go/issues/11100)) ([60c2323](https://github.com/googleapis/google-cloud-go/commit/60c2323102b623e042fc508e2b1bb830a03f9577)) + + +### Bug Fixes + +* **storage:** Bump auth dep ([#11135](https://github.com/googleapis/google-cloud-go/issues/11135)) ([9620a51](https://github.com/googleapis/google-cloud-go/commit/9620a51b2c6904d8d93e124494bc297fb98553d2)) + ## [1.46.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.45.0...storage/v1.46.0) (2024-10-31) ### Features diff --git a/vendor/cloud.google.com/go/storage/http_client.go b/vendor/cloud.google.com/go/storage/http_client.go index 6baf905473569..221078f3e2622 100644 --- a/vendor/cloud.google.com/go/storage/http_client.go +++ b/vendor/cloud.google.com/go/storage/http_client.go @@ -901,11 +901,12 @@ func (c *httpStorageClient) newRangeReaderXML(ctx context.Context, params *newRa done <- true }() - // Wait until timeout or request is successful. - timer := time.After(c.dynamicReadReqStallTimeout.getValue(params.bucket)) + // Wait until stall timeout or request is successful. + stallTimeout := c.dynamicReadReqStallTimeout.getValue(params.bucket) + timer := time.After(stallTimeout) select { case <-timer: - log.Printf("stalled read-req cancelled after %fs", c.dynamicReadReqStallTimeout.getValue(params.bucket).Seconds()) + log.Printf("stalled read-req (%p) cancelled after %fs", req, stallTimeout.Seconds()) cancel() err = context.DeadlineExceeded if res != nil && res.Body != nil { diff --git a/vendor/cloud.google.com/go/storage/internal/apiv2/auxiliary.go b/vendor/cloud.google.com/go/storage/internal/apiv2/auxiliary.go index fc3e783bdc49e..f6af3452d3126 100644 --- a/vendor/cloud.google.com/go/storage/internal/apiv2/auxiliary.go +++ b/vendor/cloud.google.com/go/storage/internal/apiv2/auxiliary.go @@ -41,7 +41,7 @@ type BucketIterator struct { InternalFetch func(pageSize int, pageToken string) (results []*storagepb.Bucket, nextPageToken string, err error) } -// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. +// PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } @@ -88,7 +88,7 @@ type ObjectIterator struct { InternalFetch func(pageSize int, pageToken string) (results []*storagepb.Object, nextPageToken string, err error) } -// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. +// PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *ObjectIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } diff --git a/vendor/cloud.google.com/go/storage/internal/apiv2/doc.go b/vendor/cloud.google.com/go/storage/internal/apiv2/doc.go index 869f3b1fbcd73..4640d5bdfd2a1 100644 --- a/vendor/cloud.google.com/go/storage/internal/apiv2/doc.go +++ b/vendor/cloud.google.com/go/storage/internal/apiv2/doc.go @@ -43,6 +43,7 @@ // // To get started with this package, create a client. // +// // go get cloud.google.com/go/storage/internal/apiv2@latest // ctx := context.Background() // // This snippet has been automatically generated and should be regarded as a code template only. // // It will require modifications to work: @@ -61,19 +62,8 @@ // // # Using the Client // -// The following is an example of making an API call with the newly created client. +// The following is an example of making an API call with the newly created client, mentioned above. // -// ctx := context.Background() -// // This snippet has been automatically generated and should be regarded as a code template only. -// // It will require modifications to work: -// // - It may require correct/in-range values for request initialization. -// // - It may require specifying regional endpoints when creating the service client as shown in: -// // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options -// c, err := storage.NewClient(ctx) -// if err != nil { -// // TODO: Handle error. -// } -// defer c.Close() // stream, err := c.BidiWriteObject(ctx) // if err != nil { // // TODO: Handle error. @@ -115,34 +105,3 @@ // [Debugging Client Libraries]: https://pkg.go.dev/cloud.google.com/go#hdr-Debugging // [Inspecting errors]: https://pkg.go.dev/cloud.google.com/go#hdr-Inspecting_errors package storage // import "cloud.google.com/go/storage/internal/apiv2" - -import ( - "context" - - "google.golang.org/api/option" -) - -// For more information on implementing a client constructor hook, see -// https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors. -type clientHookParams struct{} -type clientHook func(context.Context, clientHookParams) ([]option.ClientOption, error) - -var versionClient string - -func getVersionClient() string { - if versionClient == "" { - return "UNKNOWN" - } - return versionClient -} - -// DefaultAuthScopes reports the default set of authentication scopes to use with this package. -func DefaultAuthScopes() []string { - return []string{ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/devstorage.full_control", - "https://www.googleapis.com/auth/devstorage.read_only", - "https://www.googleapis.com/auth/devstorage.read_write", - } -} diff --git a/vendor/cloud.google.com/go/storage/internal/apiv2/helpers.go b/vendor/cloud.google.com/go/storage/internal/apiv2/helpers.go new file mode 100644 index 0000000000000..762882d1d9e7a --- /dev/null +++ b/vendor/cloud.google.com/go/storage/internal/apiv2/helpers.go @@ -0,0 +1,48 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go_gapic. DO NOT EDIT. + +package storage + +import ( + "context" + + "google.golang.org/api/option" +) + +// For more information on implementing a client constructor hook, see +// https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors. +type clientHookParams struct{} +type clientHook func(context.Context, clientHookParams) ([]option.ClientOption, error) + +var versionClient string + +func getVersionClient() string { + if versionClient == "" { + return "UNKNOWN" + } + return versionClient +} + +// DefaultAuthScopes reports the default set of authentication scopes to use with this package. +func DefaultAuthScopes() []string { + return []string{ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-platform.read-only", + "https://www.googleapis.com/auth/devstorage.full_control", + "https://www.googleapis.com/auth/devstorage.read_only", + "https://www.googleapis.com/auth/devstorage.read_write", + } +} diff --git a/vendor/cloud.google.com/go/storage/internal/version.go b/vendor/cloud.google.com/go/storage/internal/version.go index fc6b11e22267c..f2754293858ec 100644 --- a/vendor/cloud.google.com/go/storage/internal/version.go +++ b/vendor/cloud.google.com/go/storage/internal/version.go @@ -15,4 +15,4 @@ package internal // Version is the current tagged release of the library. -const Version = "1.46.0" +const Version = "1.47.0" diff --git a/vendor/cloud.google.com/go/storage/storage.go b/vendor/cloud.google.com/go/storage/storage.go index 0c11eb82adc22..cc91f8fe9fa4e 100644 --- a/vendor/cloud.google.com/go/storage/storage.go +++ b/vendor/cloud.google.com/go/storage/storage.go @@ -43,6 +43,9 @@ import ( "cloud.google.com/go/storage/internal" "cloud.google.com/go/storage/internal/apiv2/storagepb" "github.com/googleapis/gax-go/v2" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" "golang.org/x/oauth2/google" "google.golang.org/api/googleapi" "google.golang.org/api/option" @@ -50,6 +53,8 @@ import ( raw "google.golang.org/api/storage/v1" "google.golang.org/api/transport" htransport "google.golang.org/api/transport/http" + "google.golang.org/grpc/experimental/stats" + "google.golang.org/grpc/stats/opentelemetry" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/fieldmaskpb" @@ -233,6 +238,60 @@ func NewGRPCClient(ctx context.Context, opts ...option.ClientOption) (*Client, e return &Client{tc: tc}, nil } +// CheckDirectConnectivitySupported checks if gRPC direct connectivity +// is available for a specific bucket from the environment where the client +// is running. A `nil` error represents Direct Connectivity was detected. +// Direct connectivity is expected to be available when running from inside +// GCP and connecting to a bucket in the same region. +// +// You can pass in [option.ClientOption] you plan on passing to [NewGRPCClient] +func CheckDirectConnectivitySupported(ctx context.Context, bucket string, opts ...option.ClientOption) error { + view := metric.NewView( + metric.Instrument{ + Name: "grpc.client.attempt.duration", + Kind: metric.InstrumentKindHistogram, + }, + metric.Stream{AttributeFilter: attribute.NewAllowKeysFilter("grpc.lb.locality")}, + ) + mr := metric.NewManualReader() + provider := metric.NewMeterProvider(metric.WithReader(mr), metric.WithView(view)) + // Provider handles shutting down ManualReader + defer provider.Shutdown(ctx) + mo := opentelemetry.MetricsOptions{ + MeterProvider: provider, + Metrics: stats.NewMetrics("grpc.client.attempt.duration"), + OptionalLabels: []string{"grpc.lb.locality"}, + } + combinedOpts := append(opts, WithDisabledClientMetrics(), option.WithGRPCDialOption(opentelemetry.DialOption(opentelemetry.Options{MetricsOptions: mo}))) + client, err := NewGRPCClient(ctx, combinedOpts...) + if err != nil { + return fmt.Errorf("storage.NewGRPCClient: %w", err) + } + defer client.Close() + if _, err = client.Bucket(bucket).Attrs(ctx); err != nil { + return fmt.Errorf("Bucket.Attrs: %w", err) + } + // Call manual reader to collect metric + rm := metricdata.ResourceMetrics{} + if err = mr.Collect(context.Background(), &rm); err != nil { + return fmt.Errorf("ManualReader.Collect: %w", err) + } + for _, sm := range rm.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == "grpc.client.attempt.duration" { + hist := m.Data.(metricdata.Histogram[float64]) + for _, d := range hist.DataPoints { + v, present := d.Attributes.Value("grpc.lb.locality") + if present && v.AsString() != "" { + return nil + } + } + } + } + } + return errors.New("storage: direct connectivity not detected") +} + // Close closes the Client. // // Close need not be called at program exit. diff --git a/vendor/modules.txt b/vendor/modules.txt index b688db14dac25..216c325c60c67 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,7 +10,7 @@ cloud.google.com/go/internal/optional cloud.google.com/go/internal/pubsub cloud.google.com/go/internal/trace cloud.google.com/go/internal/version -# cloud.google.com/go/auth v0.10.0 +# cloud.google.com/go/auth v0.10.2 ## explicit; go 1.21 cloud.google.com/go/auth cloud.google.com/go/auth/credentials @@ -63,7 +63,7 @@ cloud.google.com/go/pubsub/apiv1/pubsubpb cloud.google.com/go/pubsub/internal cloud.google.com/go/pubsub/internal/distribution cloud.google.com/go/pubsub/internal/scheduler -# cloud.google.com/go/storage v1.46.0 +# cloud.google.com/go/storage v1.47.0 ## explicit; go 1.21 cloud.google.com/go/storage cloud.google.com/go/storage/experimental