pax_global_header00006660000000000000000000000064147311376730014526gustar00rootroot0000000000000052 comment=643488bae32330e5197dedf8fad95d2159cef676 gax-go-2.14.1/000077500000000000000000000000001473113767300127755ustar00rootroot00000000000000gax-go-2.14.1/.github/000077500000000000000000000000001473113767300143355ustar00rootroot00000000000000gax-go-2.14.1/.github/CODEOWNERS000066400000000000000000000000651473113767300157310ustar00rootroot00000000000000* @googleapis/yoshi-go-admins @googleapis/actools-go gax-go-2.14.1/.github/release-please.yml000066400000000000000000000002301473113767300177420ustar00rootroot00000000000000handleGHRelease: true manifest: true manifestFile: v2/.release-please-manifest.json manifestConfig: v2/release-please-config.json releaseType: go-yoshi gax-go-2.14.1/.github/release-trigger.yml000066400000000000000000000000421473113767300201350ustar00rootroot00000000000000enabled: true multiScmName: gax-gogax-go-2.14.1/.github/renovate.json000066400000000000000000000007501473113767300170550ustar00rootroot00000000000000{ "extends": [ "config:base", "schedule:weekly", ":disableDependencyDashboard" ], "ignoreDeps": [ "google.golang.org/grpc" ], "semanticCommits": false, "postUpdateOptions": [ "gomodTidy" ], "commitMessagePrefix": "chore(all): ", "commitMessageAction": "update", "labels": [ "automerge" ], "groupName": "all", "force": { "constraints": { "go": "1.21" } } } gax-go-2.14.1/.gitignore000066400000000000000000000000101473113767300147540ustar00rootroot00000000000000*.cover gax-go-2.14.1/CODE_OF_CONDUCT.md000066400000000000000000000036751473113767300156070ustar00rootroot00000000000000# Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) gax-go-2.14.1/CONTRIBUTING.md000066400000000000000000000032231473113767300152260ustar00rootroot00000000000000Want to contribute? Great! First, read this page (including the small print at the end). ### Before you contribute Before we can use your code, you must sign the [Google Individual Contributor License Agreement] (https://cla.developers.google.com/about/google-individual) (CLA), which you can do online. The CLA is necessary mainly because you own the copyright to your changes, even after your contribution becomes part of our codebase, so we need your permission to use and distribute your code. We also need to be sure of various other things—for instance that you'll tell us if you know that your code infringes on other people's patents. You don't have to sign the CLA until after you've submitted your code for review and a member has approved it, but you must do it before we can put your code into our codebase. Before you start working on a larger contribution, you should get in touch with us first through the issue tracker with your idea so that we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on. ### Code reviews All submissions, including submissions by project members, require review. We use Github pull requests for this purpose. ### Breaking code changes When a breaking change is added, CI/CD will fail. If the change is expected, add a BREAKING_CHANGE_ACCEPTABLE= line to the CL description. This will cause CI/CD to skip checking breaking changes. ### The small print Contributions made by corporations are covered by a different agreement than the one above, the [Software Grant and Corporate Contributor License Agreement] (https://cla.developers.google.com/about/google-corporate). gax-go-2.14.1/LICENSE000066400000000000000000000026771473113767300140160ustar00rootroot00000000000000Copyright 2016, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. gax-go-2.14.1/README.md000066400000000000000000000015201473113767300142520ustar00rootroot00000000000000Google API Extensions for Go ============================ [![GoDoc](https://godoc.org/github.com/googleapis/gax-go?status.svg)](https://godoc.org/github.com/googleapis/gax-go) Google API Extensions for Go (gax-go) is a set of modules which aids the development of APIs for clients and servers based on `gRPC` and Google API conventions. To install the API extensions, use: ``` go get -u github.com/googleapis/gax-go/v2 ``` **Note:** Application code will rarely need to use this library directly, but the code generated automatically from API definition files can use it to simplify code generation and to provide more convenient and idiomatic API surface. Go Versions =========== This library requires Go 1.6 or above. License ======= BSD - please see [LICENSE](https://github.com/googleapis/gax-go/blob/main/LICENSE) for more information. gax-go-2.14.1/RELEASING.md000066400000000000000000000023171473113767300146330ustar00rootroot00000000000000# How to release v1 1. Determine the current release version with `git tag -l`. It should look something like `vX.Y.Z`. We'll call the current version `$CV` and the new version `$NV`. 1. On main, run `git log $CV..` to list all the changes since the last release. a. NOTE: Some commits may pertain to only v1 or v2. Manually introspect each commit to figure which occurred in v1. 1. Edit `CHANGES.md` to include a summary of the changes. 1. Mail the CL containing the `CHANGES.md` changes. When the CL is approved, submit it. 1. Without submitting any other CLs: a. Switch to main. b. `git pull` c. Tag the repo with the next version: `git tag $NV`. It should be of the form `v1.Y.Z`. d. Push the tag: `git push origin $NV`. 1. Update [the releases page](https://github.com/googleapis/google-cloud-go/releases) with the new release, copying the contents of the CHANGES.md. # How to release v2 Same process as v1, once again noting that the commit list may include v1 commits (which should be pruned out). Note also whilst v1 tags are `v1.Y.Z`, v2 tags are `v2.Y.Z`. # On releasing multiple major versions Please see https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher. gax-go-2.14.1/SECURITY.md000066400000000000000000000005111473113767300145630ustar00rootroot00000000000000# Security Policy To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). The Google Security Team will respond within 5 working days of your report on g.co/vulnz. We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. gax-go-2.14.1/call_option.go000066400000000000000000000056041473113767300156340ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( v2 "github.com/googleapis/gax-go/v2" "google.golang.org/grpc" "google.golang.org/grpc/codes" ) // CallOption is an option used by Invoke to control behaviors of RPC calls. // CallOption works by modifying relevant fields of CallSettings. type CallOption = v2.CallOption // Retryer is used by Invoke to determine retry behavior. type Retryer = v2.Retryer // WithRetry sets CallSettings.Retry to fn. func WithRetry(fn func() Retryer) CallOption { return v2.WithRetry(fn) } // OnCodes returns a Retryer that retries if and only if // the previous attempt returns a GRPC error whose error code is stored in cc. // Pause times between retries are specified by bo. // // bo is only used for its parameters; each Retryer has its own copy. func OnCodes(cc []codes.Code, bo Backoff) Retryer { return v2.OnCodes(cc, bo) } // Backoff implements exponential backoff. // The wait time between retries is a random value between 0 and the "retry envelope". // The envelope starts at Initial and increases by the factor of Multiplier every retry, // but is capped at Max. type Backoff = v2.Backoff // WithGRPCOptions allows passing gRPC call options during client creation. func WithGRPCOptions(opt ...grpc.CallOption) CallOption { return v2.WithGRPCOptions(opt...) } // CallSettings allow fine-grained control over how calls are made. type CallSettings = v2.CallSettings gax-go-2.14.1/gax.go000066400000000000000000000037361473113767300141140ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package gax contains a set of modules which aid the development of APIs // for clients and servers based on gRPC and Google API conventions. // // Application code will rarely need to use this library directly. // However, code generated automatically from API definition files can use it // to simplify code generation and to provide more convenient and idiomatic API surfaces. package gax // Version specifies the gax version. const Version = "1.0.1" gax-go-2.14.1/go.mod000066400000000000000000000006711473113767300141070ustar00rootroot00000000000000module github.com/googleapis/gax-go go 1.21 require ( github.com/googleapis/gax-go/v2 v2.14.0 google.golang.org/grpc v1.67.1 ) require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/api v0.205.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/protobuf v1.35.1 // indirect ) gax-go-2.14.1/go.sum000066400000000000000000000036221473113767300141330ustar00rootroot00000000000000github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= google.golang.org/api v0.205.0 h1:LFaxkAIpDb/GsrWV20dMMo5MR0h8UARTbn24LmD+0Pg= google.golang.org/api v0.205.0/go.mod h1:NrK1EMqO8Xk6l6QwRAmrXXg2v6dzukhlOyvkYtnvUuc= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gax-go-2.14.1/go.work000066400000000000000000000000321473113767300143010ustar00rootroot00000000000000go 1.21 use ( . ./v2 ) gax-go-2.14.1/go.work.sum000066400000000000000000002107061473113767300151170ustar00rootroot00000000000000cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go v0.113.0/go.mod h1:glEqlogERKYeePz6ZdkcLJ28Q2I6aERgDDErBg9GzO8= cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= cloud.google.com/go/accessapproval v1.7.7/go.mod h1:10ZDPYiTm8tgxuMPid8s2DL93BfCt6xBh/Vg0Xd8pU0= cloud.google.com/go/accessapproval v1.7.11/go.mod h1:KGK3+CLDWm4BvjN0wFtZqdFUGhxlTvTF6PhAwQJGL4M= cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= cloud.google.com/go/accesscontextmanager v1.8.7/go.mod h1:jSvChL1NBQ+uLY9zUBdPy9VIlozPoHptdBnRYeWuQoM= cloud.google.com/go/accesscontextmanager v1.8.11/go.mod h1:nwPysISS3KR5qXipAU6cW/UbDavDdTBBgPohbkhGSok= cloud.google.com/go/aiplatform v1.45.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA= cloud.google.com/go/aiplatform v1.68.0/go.mod h1:105MFA3svHjC3Oazl7yjXAmIR89LKhRAeNdnDKJczME= cloud.google.com/go/analytics v0.21.2/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= cloud.google.com/go/analytics v0.23.2/go.mod h1:vtE3olAXZ6edJYk1UOndEs6EfaEc9T2B28Y4G5/a7Fo= cloud.google.com/go/analytics v0.23.6/go.mod h1:cFz5GwWHrWQi8OHKP9ep3Z4pvHgGcG9lPnFQ+8kXsNo= cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= cloud.google.com/go/apigateway v1.6.7/go.mod h1:7wAMb/33Rzln+PrGK16GbGOfA1zAO5Pq6wp19jtIt7c= cloud.google.com/go/apigateway v1.6.11/go.mod h1:4KsrYHn/kSWx8SNUgizvaz+lBZ4uZfU7mUDsGhmkWfM= cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= cloud.google.com/go/apigeeconnect v1.6.7/go.mod h1:hZxCKvAvDdKX8+eT0g5eEAbRSS9Gkzi+MPWbgAMAy5U= cloud.google.com/go/apigeeconnect v1.6.11/go.mod h1:iMQLTeKxtKL+sb0D+pFlS/TO6za2IUOh/cwMEtn/4g0= cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= cloud.google.com/go/apigeeregistry v0.8.5/go.mod h1:ZMg60hq2K35tlqZ1VVywb9yjFzk9AJ7zqxrysOxLi3o= cloud.google.com/go/apigeeregistry v0.8.9/go.mod h1:4XivwtSdfSO16XZdMEQDBCMCWDp3jkCBRhVgamQfLSA= cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= cloud.google.com/go/appengine v1.8.7/go.mod h1:1Fwg2+QTgkmN6Y+ALGwV8INLbdkI7+vIvhcKPZCML0g= cloud.google.com/go/appengine v1.8.11/go.mod h1:xET3coaDUj+OP4TgnZlgQ+rG2R9fG2nblya13czP56Q= cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= cloud.google.com/go/area120 v0.8.7/go.mod h1:L/xTq4NLP9mmxiGdcsVz7y1JLc9DI8pfaXRXbnjkR6w= cloud.google.com/go/area120 v0.8.11/go.mod h1:VBxJejRAJqeuzXQBbh5iHBYUkIjZk5UzFZLCXmzap2o= cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= cloud.google.com/go/artifactregistry v1.14.9/go.mod h1:n2OsUqbYoUI2KxpzQZumm6TtBgtRf++QulEohdnlsvI= cloud.google.com/go/artifactregistry v1.14.13/go.mod h1:zQ/T4xoAFPtcxshl+Q4TJBgsy7APYR/BLd2z3xEAqRA= cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= cloud.google.com/go/asset v1.19.1/go.mod h1:kGOS8DiCXv6wU/JWmHWCgaErtSZ6uN5noCy0YwVaGfs= cloud.google.com/go/asset v1.19.5/go.mod h1:sqyLOYaLLfc4ACcn3YxqHno+J7lRt9NJTdO50zCUcY0= cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= cloud.google.com/go/assuredworkloads v1.11.7/go.mod h1:CqXcRH9N0KCDtHhFisv7kk+cl//lyV+pYXGi1h8rCEU= cloud.google.com/go/assuredworkloads v1.11.11/go.mod h1:vaYs6+MHqJvLKYgZBOsuuOhBgNNIguhRU0Kt7JTGcnI= cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= cloud.google.com/go/auth v0.7.0/go.mod h1:D+WqdrpcjmiCgWrXmLLxOVq1GACoE36chW6KXoEvuIw= cloud.google.com/go/auth v0.7.3/go.mod h1:HJtWUx1P5eqjy/f6Iq5KeytNpbAcGolPhOgyop2LlzA= cloud.google.com/go/auth v0.8.1/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc= cloud.google.com/go/auth v0.10.1/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= cloud.google.com/go/automl v1.13.7/go.mod h1:E+s0VOsYXUdXpq0y4gNZpi0A/s6y9+lAarmV5Eqlg40= cloud.google.com/go/automl v1.13.11/go.mod h1:oMJdXRDOVC+Eq3PnGhhxSut5Hm9TSyVx1aLEOgerOw8= cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= cloud.google.com/go/baremetalsolution v1.1.1/go.mod h1:D1AV6xwOksJMV4OSlWHtWuFNZZYujJknMAP4Qa27QIA= cloud.google.com/go/baremetalsolution v1.2.6/go.mod h1:KkS2BtYXC7YGbr42067nzFr+ABFMs6cxEcA1F+cedIw= cloud.google.com/go/baremetalsolution v1.2.10/go.mod h1:eO2c2NMRy5ytcNPhG78KPsWGNsX5W/tUsCOWmYihx6I= cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= cloud.google.com/go/batch v1.3.1/go.mod h1:VguXeQKXIYaeeIYbuozUmBR13AfL4SJP7IltNPS+A4A= cloud.google.com/go/batch v1.8.7/go.mod h1:O5/u2z8Wc7E90Bh4yQVLQIr800/0PM5Qzvjac3Jxt4k= cloud.google.com/go/batch v1.9.2/go.mod h1:smqwS4sleDJVAEzBt/TzFfXLktmWjFNugGDWl8coKX4= cloud.google.com/go/beyondcorp v0.6.1/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= cloud.google.com/go/beyondcorp v1.0.6/go.mod h1:wRkenqrVRtnGFfnyvIg0zBFUdN2jIfeojFF9JJDwVIA= cloud.google.com/go/beyondcorp v1.0.10/go.mod h1:G09WxvxJASbxbrzaJUMVvNsB1ZiaKxpbtkjiFtpDtbo= cloud.google.com/go/bigquery v1.52.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4= cloud.google.com/go/bigquery v1.61.0/go.mod h1:PjZUje0IocbuTOdq4DBOJLNYB0WF3pAKBHzAYyxCwFo= cloud.google.com/go/bigquery v1.62.0/go.mod h1:5ee+ZkF1x/ntgCsFQJAQTM3QkAZOecfCmvxhkJsWRSA= cloud.google.com/go/bigtable v1.27.2-0.20240730134218-123c88616251/go.mod h1:avmXcmxVbLJAo9moICRYMgDyTTPoV0MA0lHKnyqV4fQ= cloud.google.com/go/billing v1.16.0/go.mod h1:y8vx09JSSJG02k5QxbycNRrN7FGZB6F3CAcgum7jvGA= cloud.google.com/go/billing v1.18.5/go.mod h1:lHw7fxS6p7hLWEPzdIolMtOd0ahLwlokW06BzbleKP8= cloud.google.com/go/billing v1.18.9/go.mod h1:bKTnh8MBfCMUT1fzZ936CPN9rZG7ZEiHB2J3SjIjByc= cloud.google.com/go/binaryauthorization v1.6.1/go.mod h1:TKt4pa8xhowwffiBmbrbcxijJRZED4zrqnwZ1lKH51U= cloud.google.com/go/binaryauthorization v1.8.3/go.mod h1:Cul4SsGlbzEsWPOz2sH8m+g2Xergb6ikspUyQ7iOThE= cloud.google.com/go/binaryauthorization v1.8.7/go.mod h1:cRj4teQhOme5SbWQa96vTDATQdMftdT5324BznxANtg= cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= cloud.google.com/go/certificatemanager v1.8.1/go.mod h1:hDQzr50Vx2gDB+dOfmDSsQzJy/UPrYRdzBdJ5gAVFIc= cloud.google.com/go/certificatemanager v1.8.5/go.mod h1:r2xINtJ/4xSz85VsqvjY53qdlrdCjyniib9Jp98ZKKM= cloud.google.com/go/channel v1.16.0/go.mod h1:eN/q1PFSl5gyu0dYdmxNXscY/4Fi7ABmeHCJNf/oHmc= cloud.google.com/go/channel v1.17.7/go.mod h1:b+FkgBrhMKM3GOqKUvqHFY/vwgp+rwsAuaMd54wCdN4= cloud.google.com/go/channel v1.17.11/go.mod h1:gjWCDBcTGQce/BSMoe2lAqhlq0dIRiZuktvBKXUawp0= cloud.google.com/go/cloudbuild v1.10.1/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= cloud.google.com/go/cloudbuild v1.16.1/go.mod h1:c2KUANTtCBD8AsRavpPout6Vx8W+fsn5zTsWxCpWgq4= cloud.google.com/go/cloudbuild v1.16.5/go.mod h1:HXLpZ8QeYZgmDIWpbl9Gs22p6o6uScgQ/cV9HF9cIZU= cloud.google.com/go/clouddms v1.6.1/go.mod h1:Ygo1vL52Ov4TBZQquhz5fiw2CQ58gvu+PlS6PVXCpZI= cloud.google.com/go/clouddms v1.7.6/go.mod h1:8HWZ2tznZ0mNAtTpfnRNT0QOThqn9MBUqTj0Lx8npIs= cloud.google.com/go/clouddms v1.7.10/go.mod h1:PzHELq0QDyA7VaD9z6mzh2mxeBz4kM6oDe8YxMxd4RA= cloud.google.com/go/cloudtasks v1.11.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= cloud.google.com/go/cloudtasks v1.12.8/go.mod h1:aX8qWCtmVf4H4SDYUbeZth9C0n9dBj4dwiTYi4Or/P4= cloud.google.com/go/cloudtasks v1.12.12/go.mod h1:8UmM+duMrQpzzRREo0i3x3TrFjsgI/3FQw3664/JblA= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute v1.27.0/go.mod h1:LG5HwRmWFKM2C5XxHRiNzkLLXW48WwvyVC0mfWsYPOM= cloud.google.com/go/compute v1.27.4/go.mod h1:7JZS+h21ERAGHOy5qb7+EPyXlQwzshzrx1x6L9JhTqU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/contactcenterinsights v1.9.1/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= cloud.google.com/go/contactcenterinsights v1.13.2/go.mod h1:AfkSB8t7mt2sIY6WpfO61nD9J9fcidIchtxm9FqJVXk= cloud.google.com/go/contactcenterinsights v1.13.6/go.mod h1:mL+DbN3pMQGaAbDC4wZhryLciwSwHf5Tfk4Itr72Zyk= cloud.google.com/go/container v1.22.1/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4= cloud.google.com/go/container v1.37.0/go.mod h1:AFsgViXsfLvZHsgHrWQqPqfAPjCwXrZmLjKJ64uhLIw= cloud.google.com/go/container v1.38.0/go.mod h1:U0uPBvkVWOJGY/0qTVuPS7NeafFEUsHSPqT5pB8+fCY= cloud.google.com/go/containeranalysis v0.10.1/go.mod h1:Ya2jiILITMY68ZLPaogjmOMNkwsDrWBSTyBubGXO7j0= cloud.google.com/go/containeranalysis v0.11.6/go.mod h1:YRf7nxcTcN63/Kz9f86efzvrV33g/UV8JDdudRbYEUI= cloud.google.com/go/containeranalysis v0.12.1/go.mod h1:+/lcJIQSFt45TC0N9Nq7/dPbl0isk6hnC4EvBBqyXsM= cloud.google.com/go/datacatalog v1.14.1/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4= cloud.google.com/go/datacatalog v1.20.1/go.mod h1:Jzc2CoHudhuZhpv78UBAjMEg3w7I9jHA11SbRshWUjk= cloud.google.com/go/datacatalog v1.20.5/go.mod h1:DB0QWF9nelpsbB0eR/tA0xbHZZMvpoFD1XFy3Qv/McI= cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= cloud.google.com/go/dataflow v0.9.7/go.mod h1:3BjkOxANrm1G3+/EBnEsTEEgJu1f79mFqoOOZfz3v+E= cloud.google.com/go/dataflow v0.9.11/go.mod h1:CCLufd7I4pPfyp54qMgil/volrL2ZKYjXeYLfQmBGJs= cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= cloud.google.com/go/dataform v0.9.4/go.mod h1:jjo4XY+56UrNE0wsEQsfAw4caUs4DLJVSyFBDelRDtQ= cloud.google.com/go/dataform v0.9.8/go.mod h1:cGJdyVdunN7tkeXHPNosuMzmryx55mp6cInYBgxN3oA= cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= cloud.google.com/go/datafusion v1.7.7/go.mod h1:qGTtQcUs8l51lFA9ywuxmZJhS4ozxsBSus6ItqCUWMU= cloud.google.com/go/datafusion v1.7.11/go.mod h1:aU9zoBHgYmoPp4dzccgm/Gi4xWDMXodSZlNZ4WNeptw= cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= cloud.google.com/go/datalabeling v0.8.7/go.mod h1:/PPncW5gxrU15UzJEGQoOT3IobeudHGvoExrtZ8ZBwo= cloud.google.com/go/datalabeling v0.8.11/go.mod h1:6IGUV3z7hlkAU5ndKVshv/8z+7pxE+k0qXsEjyzO1Xg= cloud.google.com/go/dataplex v1.8.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= cloud.google.com/go/dataplex v1.16.1/go.mod h1:szV2OpxfbmRBcw1cYq2ln8QsLR3FJq+EwTTIo+0FnyE= cloud.google.com/go/dataplex v1.18.2/go.mod h1:NuBpJJMGGQn2xctX+foHEDKRbizwuiHJamKvvSteY3Q= cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= cloud.google.com/go/dataproc/v2 v2.4.2/go.mod h1:smGSj1LZP3wtnsM9eyRuDYftNAroAl6gvKp/Wk64XDE= cloud.google.com/go/dataproc/v2 v2.5.3/go.mod h1:RgA5QR7v++3xfP7DlgY3DUmoDSTaaemPe0ayKrQfyeg= cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= cloud.google.com/go/dataqna v0.8.7/go.mod h1:hvxGaSvINAVH5EJJsONIwT1y+B7OQogjHPjizOFoWOo= cloud.google.com/go/dataqna v0.8.11/go.mod h1:74Icl1oFKKZXPd+W7YDtqJLa+VwLV6wZ+UF+sHo2QZQ= cloud.google.com/go/datastore v1.12.0/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= cloud.google.com/go/datastore v1.12.1/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= cloud.google.com/go/datastore v1.17.1/go.mod h1:mtzZ2HcVtz90OVrEXXGDc2pO4NM1kiBQy8YV4qGe0ZM= cloud.google.com/go/datastream v1.9.1/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= cloud.google.com/go/datastream v1.10.6/go.mod h1:lPeXWNbQ1rfRPjBFBLUdi+5r7XrniabdIiEaCaAU55o= cloud.google.com/go/datastream v1.10.10/go.mod h1:NqchuNjhPlISvWbk426/AU/S+Kgv7srlID9P5XOAbtg= cloud.google.com/go/deploy v1.11.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= cloud.google.com/go/deploy v1.19.0/go.mod h1:BW9vAujmxi4b/+S7ViEuYR65GiEsqL6Mhf5S/9TeDRU= cloud.google.com/go/deploy v1.20.0/go.mod h1:PaOfS47VrvmYnxG5vhHg0KU60cKeWcqyLbMBjxS8DW8= cloud.google.com/go/dialogflow v1.38.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4= cloud.google.com/go/dialogflow v1.54.0/go.mod h1:/YQLqB0bdDJl+zFKN+UNQsYUqLfWZb1HsJUQqMT7Q6k= cloud.google.com/go/dialogflow v1.55.0/go.mod h1:0u0hSlJiFpMkMpMNoFrQETwDjaRm8Q8hYKv+jz5JeRA= cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= cloud.google.com/go/dlp v1.14.0/go.mod h1:4fvEu3EbLsHrgH3QFdFlTNIiCP5mHwdYhS/8KChDIC4= cloud.google.com/go/dlp v1.15.0/go.mod h1:LtPZxZAenBXKzvWIOB2hdHIXuEcK0wW0En8//u+/nNA= cloud.google.com/go/documentai v1.20.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E= cloud.google.com/go/documentai v1.30.1/go.mod h1:RohRpAfvuv3uk3WQtXPpgQ3YABvzacWnasyJQb6AAPk= cloud.google.com/go/documentai v1.30.5/go.mod h1:5ajlDvaPyl9tc+K/jZE8WtYIqSXqAD33Z1YAYIjfad4= cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= cloud.google.com/go/domains v0.9.7/go.mod h1:u/yVf3BgfPJW3QDZl51qTJcDXo9PLqnEIxfGmGgbHEc= cloud.google.com/go/domains v0.9.11/go.mod h1:efo5552kUyxsXEz30+RaoIS2lR7tp3M/rhiYtKXkhkk= cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= cloud.google.com/go/edgecontainer v1.2.1/go.mod h1:OE2D0lbkmGDVYLCvpj8Y0M4a4K076QB7E2JupqOR/qU= cloud.google.com/go/edgecontainer v1.2.5/go.mod h1:OAb6tElD3F3oBujFAup14PKOs9B/lYobTb6LARmoACY= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/errorreporting v0.3.1/go.mod h1:6xVQXU1UuntfAf+bVkFk6nld41+CPyF2NSPCyXE3Ztk= cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= cloud.google.com/go/essentialcontacts v1.6.8/go.mod h1:EHONVDSum2xxG2p+myyVda/FwwvGbY58ZYC4XqI/lDQ= cloud.google.com/go/essentialcontacts v1.6.12/go.mod h1:UGhWTIYewH8Ma4wDRJp8cMAHUCeAOCKsuwd6GLmmQLc= cloud.google.com/go/eventarc v1.12.1/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= cloud.google.com/go/eventarc v1.13.6/go.mod h1:QReOaYnDNdjwAQQWNC7nfr63WnaKFUw7MSdQ9PXJYj0= cloud.google.com/go/eventarc v1.13.10/go.mod h1:KlCcOMApmUaqOEZUpZRVH+p0nnnsY1HaJB26U4X5KXE= cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= cloud.google.com/go/filestore v1.8.3/go.mod h1:QTpkYpKBF6jlPRmJwhLqXfJQjVrQisplyb4e2CwfJWc= cloud.google.com/go/filestore v1.8.7/go.mod h1:dKfyH0YdPAKdYHqAR/bxZeil85Y5QmrEVQwIYuRjcXI= cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4= cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= cloud.google.com/go/firestore v1.16.0/go.mod h1:+22v/7p+WNBSQwdSwP57vz47aZiY+HrDkrOsJNhk7rg= cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= cloud.google.com/go/functions v1.16.2/go.mod h1:+gMvV5E3nMb9EPqX6XwRb646jTyVz8q4yk3DD6xxHpg= cloud.google.com/go/functions v1.16.6/go.mod h1:wOzZakhMueNQaBUJdf0yjsJIe0GBRu+ZTvdSTzqHLs0= cloud.google.com/go/gaming v1.10.1/go.mod h1:XQQvtfP8Rb9Rxnxm5wFVpAp9zCQkJi2bLIb7iHGwB3s= cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= cloud.google.com/go/gkebackup v1.3.0/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU= cloud.google.com/go/gkebackup v1.5.0/go.mod h1:eLaf/+n8jEmIvOvDriGjo99SN7wRvVadoqzbZu0WzEw= cloud.google.com/go/gkebackup v1.5.4/go.mod h1:V+llvHlRD0bCyrkYaAMJX+CHralceQcaOWjNQs8/Ymw= cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= cloud.google.com/go/gkeconnect v0.8.7/go.mod h1:iUH1jgQpTyNFMK5LgXEq2o0beIJ2p7KKUUFerkf/eGc= cloud.google.com/go/gkeconnect v0.8.11/go.mod h1:ejHv5ehbceIglu1GsMwlH0nZpTftjxEY6DX7tvaM8gA= cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= cloud.google.com/go/gkehub v0.14.7/go.mod h1:NLORJVTQeCdxyAjDgUwUp0A6BLEaNLq84mCiulsM4OE= cloud.google.com/go/gkehub v0.14.11/go.mod h1:CsmDJ4qbBnSPkoBltEubK6qGOjG0xNfeeT5jI5gCnRQ= cloud.google.com/go/gkemulticloud v0.6.1/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= cloud.google.com/go/gkemulticloud v1.2.0/go.mod h1:iN5wBxTLPR6VTBWpkUsOP2zuPOLqZ/KbgG1bZir1Cng= cloud.google.com/go/gkemulticloud v1.2.4/go.mod h1:PjTtoKLQpIRztrL+eKQw8030/S4c7rx/WvHydDJlpGE= cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= cloud.google.com/go/gsuiteaddons v1.6.7/go.mod h1:u+sGBvr07OKNnOnQiB/Co1q4U2cjo50ERQwvnlcpNis= cloud.google.com/go/gsuiteaddons v1.6.11/go.mod h1:U7mk5PLBzDpHhgHv5aJkuvLp9RQzZFpa8hgWAB+xVIk= cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= cloud.google.com/go/iam v1.1.12/go.mod h1:9LDX8J7dN5YRyzVHxwQzrQs9opFFqn0Mxs9nAeB+Hhg= cloud.google.com/go/iap v1.8.1/go.mod h1:sJCbeqg3mvWLqjZNsI6dfAtbbV1DL2Rl7e1mTyXYREQ= cloud.google.com/go/iap v1.9.6/go.mod h1:YiK+tbhDszhaVifvzt2zTEF2ch9duHtp6xzxj9a0sQk= cloud.google.com/go/iap v1.9.10/go.mod h1:pO0FEirrhMOT1H0WVwpD5dD9r3oBhvsunyBQtNXzzc0= cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= cloud.google.com/go/ids v1.4.7/go.mod h1:yUkDC71u73lJoTaoONy0dsA0T7foekvg6ZRg9IJL0AA= cloud.google.com/go/ids v1.4.11/go.mod h1:+ZKqWELpJm8WcRRsSvKZWUdkriu4A3XsLLzToTv3418= cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= cloud.google.com/go/iot v1.7.7/go.mod h1:tr0bCOSPXtsg64TwwZ/1x+ReTWKlQRVXbM+DnrE54yM= cloud.google.com/go/iot v1.7.11/go.mod h1:0vZJOqFy9kVLbUXwTP95e0dWHakfR4u5IWqsKMGIfHk= cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= cloud.google.com/go/kms v1.18.0/go.mod h1:DyRBeWD/pYBMeyiaXFa/DGNyxMDL3TslIKb8o/JkLkw= cloud.google.com/go/kms v1.18.4/go.mod h1:SG1bgQ3UWW6/KdPo9uuJnzELXY5YTTMJtDYvajiQ22g= cloud.google.com/go/language v1.10.1/go.mod h1:CPp94nsdVNiQEt1CNjF5WkTcisLiHPyIbMhvR8H2AW0= cloud.google.com/go/language v1.12.5/go.mod h1:w/6a7+Rhg6Bc2Uzw6thRdKKNjnOzfKTJuxzD0JZZ0nM= cloud.google.com/go/language v1.12.9/go.mod h1:B9FbD17g1EkilctNGUDAdSrBHiFOlKNErLljO7jplDU= cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= cloud.google.com/go/lifesciences v0.9.7/go.mod h1:FQ713PhjAOHqUVnuwsCe1KPi9oAdaTfh58h1xPiW13g= cloud.google.com/go/lifesciences v0.9.11/go.mod h1:NMxu++FYdv55TxOBEvLIhiAvah8acQwXsz79i9l9/RY= cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= cloud.google.com/go/logging v1.10.0/go.mod h1:EHOwcxlltJrYGqMGfghSet736KR3hX1MAj614mrMk9I= cloud.google.com/go/logging v1.11.0/go.mod h1:5LDiJC/RxTt+fHc1LAt20R9TKiUTReDg6RuuFOZ67+A= cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ= cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= cloud.google.com/go/longrunning v0.5.11/go.mod h1:rDn7//lmlfWV1Dx6IB4RatCPenTwwmqXuiP0/RgoEO4= cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= cloud.google.com/go/managedidentities v1.6.7/go.mod h1:UzslJgHnc6luoyx2JV19cTCi2Fni/7UtlcLeSYRzTV8= cloud.google.com/go/managedidentities v1.6.11/go.mod h1:df+8oZ1D4Eri+NrcpuiR5Hd6MGgiMqn0ZCzNmBYPS0A= cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= cloud.google.com/go/maps v1.3.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= cloud.google.com/go/maps v1.11.1/go.mod h1:XcSsd8lg4ZhLPCtJ2YHcu/xLVePBzZOlI7GmR2cRCws= cloud.google.com/go/maps v1.11.5/go.mod h1:MOS/NN0L6b7Kumr8bLux9XTpd8+D54DYxBMUjq+XfXs= cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= cloud.google.com/go/mediatranslation v0.8.7/go.mod h1:6eJbPj1QJwiCP8R4K413qMx6ZHZJUi9QFpApqY88xWU= cloud.google.com/go/mediatranslation v0.8.11/go.mod h1:3sNEm0fx61eHk7rfzBzrljVV9XKr931xI3OFacQBVFg= cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= cloud.google.com/go/memcache v1.10.7/go.mod h1:SrU6+QBhvXJV0TA59+B3oCHtLkPx37eqdKmRUlmSE1k= cloud.google.com/go/memcache v1.10.11/go.mod h1:ubJ7Gfz/xQawQY5WO5pht4Q0dhzXBFeEszAeEJnwBHU= cloud.google.com/go/metastore v1.11.1/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= cloud.google.com/go/metastore v1.13.6/go.mod h1:OBCVMCP7X9vA4KKD+5J4Q3d+tiyKxalQZnksQMq5MKY= cloud.google.com/go/metastore v1.13.10/go.mod h1:RPhMnBxUmTLT1fN7fNbPqtH5EoGHueDxubmJ1R1yT84= cloud.google.com/go/monitoring v1.15.1/go.mod h1:lADlSAlFdbqQuwwpaImhsJXu1QSdd3ojypXrFSMr2rM= cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw= cloud.google.com/go/monitoring v1.20.3/go.mod h1:GPIVIdNznIdGqEjtRKQWTLcUeRnPjZW85szouimiczU= cloud.google.com/go/networkconnectivity v1.12.1/go.mod h1:PelxSWYM7Sh9/guf8CFhi6vIqf19Ir/sbfZRUwXh92E= cloud.google.com/go/networkconnectivity v1.14.6/go.mod h1:/azB7+oCSmyBs74Z26EogZ2N3UcXxdCHkCPcz8G32bU= cloud.google.com/go/networkconnectivity v1.14.10/go.mod h1:f7ZbGl4CV08DDb7lw+NmMXQTKKjMhgCEEwFbEukWuOY= cloud.google.com/go/networkmanagement v1.8.0/go.mod h1:Ho/BUGmtyEqrttTgWEe7m+8vDdK74ibQc+Be0q7Fof0= cloud.google.com/go/networkmanagement v1.13.2/go.mod h1:24VrV/5HFIOXMEtVQEUoB4m/w8UWvUPAYjfnYZcBc4c= cloud.google.com/go/networkmanagement v1.13.6/go.mod h1:WXBijOnX90IFb6sberjnGrVtZbgDNcPDUYOlGXmG8+4= cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= cloud.google.com/go/networksecurity v0.9.7/go.mod h1:aB6UiPnh/l32+TRvgTeOxVRVAHAFFqvK+ll3idU5BoY= cloud.google.com/go/networksecurity v0.9.11/go.mod h1:4xbpOqCwplmFgymAjPFM6ZIplVC6+eQ4m7sIiEq9oJA= cloud.google.com/go/notebooks v1.9.1/go.mod h1:zqG9/gk05JrzgBt4ghLzEepPHNwE5jgPcHZRKhlC1A8= cloud.google.com/go/notebooks v1.11.5/go.mod h1:pz6P8l2TvhWqAW3sysIsS0g2IUJKOzEklsjWJfi8sd4= cloud.google.com/go/notebooks v1.11.9/go.mod h1:JmnRX0eLgHRJiyxw8HOgumW9iRajImZxr7r75U16uXw= cloud.google.com/go/optimization v1.4.1/go.mod h1:j64vZQP7h9bO49m2rVaTVoNM0vEBEN5eKPUPbZyXOrk= cloud.google.com/go/optimization v1.6.5/go.mod h1:eiJjNge1NqqLYyY75AtIGeQWKO0cvzD1ct/moCFaP2Q= cloud.google.com/go/optimization v1.6.9/go.mod h1:mcvkDy0p4s5k7iSaiKrwwpN0IkteHhGmuW5rP9nXA5M= cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= cloud.google.com/go/orchestration v1.9.2/go.mod h1:8bGNigqCQb/O1kK7PeStSNlyi58rQvZqDiuXT9KAcbg= cloud.google.com/go/orchestration v1.9.6/go.mod h1:gQvdIsHESZJigimnbUA8XLbYeFlSg/z+A7ppds5JULg= cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= cloud.google.com/go/orgpolicy v1.12.3/go.mod h1:6BOgIgFjWfJzTsVcib/4QNHOAeOjCdaBj69aJVs//MA= cloud.google.com/go/orgpolicy v1.12.7/go.mod h1:Os3GlUFRPf1UxOHTup5b70BARnhHeQNNVNZzJXPbWYI= cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= cloud.google.com/go/osconfig v1.12.7/go.mod h1:ID7Lbqr0fiihKMwAOoPomWRqsZYKWxfiuafNZ9j1Y1M= cloud.google.com/go/osconfig v1.13.2/go.mod h1:eupylkWQJCwSIEMkpVR4LqpgKkQi0mD4m1DzNCgpQso= cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= cloud.google.com/go/oslogin v1.13.3/go.mod h1:WW7Rs1OJQ1iSUckZDilvNBSNPE8on740zF+4ZDR4o8U= cloud.google.com/go/oslogin v1.13.7/go.mod h1:xq027cL0fojpcEcpEQdWayiDn8tIx3WEFYMM6+q7U+E= cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= cloud.google.com/go/phishingprotection v0.8.7/go.mod h1:FtYaOyGc/HQQU7wY4sfwYZBFDKAL+YtVBjUj8E3A3/I= cloud.google.com/go/phishingprotection v0.8.11/go.mod h1:Mge0cylqVFs+D0EyxlsTOJ1Guf3qDgrztHzxZqkhRQM= cloud.google.com/go/policytroubleshooter v1.7.1/go.mod h1:0NaT5v3Ag1M7U5r0GfDCpUFkWd9YqpubBWsQlhanRv0= cloud.google.com/go/policytroubleshooter v1.10.5/go.mod h1:bpOf94YxjWUqsVKokzPBibMSAx937Jp2UNGVoMAtGYI= cloud.google.com/go/policytroubleshooter v1.10.9/go.mod h1:X8HEPVBWz8E+qwI/QXnhBLahEHdcuPO3M9YvSj0LDek= cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= cloud.google.com/go/privatecatalog v0.9.7/go.mod h1:NWLa8MCL6NkRSt8jhL8Goy2A/oHkvkeAxiA0gv0rIXI= cloud.google.com/go/privatecatalog v0.9.11/go.mod h1:awEF2a8M6UgoqVJcF/MthkF8SSo6OoWQ7TtPNxUlljY= cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= cloud.google.com/go/pubsub v1.39.0/go.mod h1:FrEnrSGU6L0Kh3iBaAbIUM8KMR7LqyEkMboVxGXCT+s= cloud.google.com/go/pubsub v1.40.0/go.mod h1:BVJI4sI2FyXp36KFKvFwcfDRDfR8MiLT8mMhmIhdAeA= cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= cloud.google.com/go/pubsublite v1.8.2/go.mod h1:4r8GSa9NznExjuLPEJlF1VjOPOpgf3IT6k8x/YgaOPI= cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= cloud.google.com/go/recaptchaenterprise/v2 v2.13.0/go.mod h1:jNYyn2ScR4DTg+VNhjhv/vJQdaU8qz+NpmpIzEE7HFQ= cloud.google.com/go/recaptchaenterprise/v2 v2.14.2/go.mod h1:MwPgdgvBkE46aWuuXeBTCB8hQJ88p+CpXInROZYCTkc= cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= cloud.google.com/go/recommendationengine v0.8.7/go.mod h1:YsUIbweUcpm46OzpVEsV5/z+kjuV6GzMxl7OAKIGgKE= cloud.google.com/go/recommendationengine v0.8.11/go.mod h1:cEkU4tCXAF88a4boMFZym7U7uyxvVwcQtKzS85IbQio= cloud.google.com/go/recommender v1.10.1/go.mod h1:XFvrE4Suqn5Cq0Lf+mCP6oBHD/yRMA8XxP5sb7Q7gpA= cloud.google.com/go/recommender v1.12.3/go.mod h1:OgN0MjV7/6FZUUPgF2QPQtYErtZdZc4u+5onvurcGEI= cloud.google.com/go/recommender v1.12.7/go.mod h1:lG8DVtczLltWuaCv4IVpNphONZTzaCC9KdxLYeZM5G4= cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= cloud.google.com/go/redis v1.16.0/go.mod h1:NLzG3Ur8ykVIZk+i5ienRnycsvWzQ0uCLcil6Htc544= cloud.google.com/go/redis v1.16.4/go.mod h1:unCVfLP5eFrVhGLDnb7IaSaWxuZ+7cBgwwBwbdG9m9w= cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= cloud.google.com/go/resourcemanager v1.9.7/go.mod h1:cQH6lJwESufxEu6KepsoNAsjrUtYYNXRwxm4QFE5g8A= cloud.google.com/go/resourcemanager v1.9.11/go.mod h1:SbNAbjVLoi2rt9G74bEYb3aw1iwvyWPOJMnij4SsmHA= cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= cloud.google.com/go/resourcesettings v1.7.0/go.mod h1:pFzZYOQMyf1hco9pbNWGEms6N/2E7nwh0oVU1Tz+4qA= cloud.google.com/go/resourcesettings v1.7.4/go.mod h1:seBdLuyeq+ol2u9G2+74GkSjQaxaBWF+vVb6mVzQFG0= cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= cloud.google.com/go/retail v1.17.0/go.mod h1:GZ7+J084vyvCxO1sjdBft0DPZTCA/lMJ46JKWxWeb6w= cloud.google.com/go/retail v1.17.4/go.mod h1:oPkL1FzW7D+v/hX5alYIx52ro2FY/WPAviwR1kZZTMs= cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo= cloud.google.com/go/run v1.3.7/go.mod h1:iEUflDx4Js+wK0NzF5o7hE9Dj7QqJKnRj0/b6rhVq20= cloud.google.com/go/run v1.4.0/go.mod h1:4G9iHLjdOC+CQ0CzA0+6nLeR6NezVPmlj+GULmb0zE4= cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= cloud.google.com/go/scheduler v1.10.8/go.mod h1:0YXHjROF1f5qTMvGTm4o7GH1PGAcmu/H/7J7cHOiHl0= cloud.google.com/go/scheduler v1.10.12/go.mod h1:6DRtOddMWJ001HJ6MS148rtLSh/S2oqd2hQC3n5n9fQ= cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= cloud.google.com/go/secretmanager v1.13.1/go.mod h1:y9Ioh7EHp1aqEKGYXk3BOC+vkhlHm9ujL7bURT4oI/4= cloud.google.com/go/secretmanager v1.13.5/go.mod h1:/OeZ88l5Z6nBVilV0SXgv6XJ243KP2aIhSWRMrbvDCQ= cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= cloud.google.com/go/security v1.17.0/go.mod h1:eSuFs0SlBv1gWg7gHIoF0hYOvcSwJCek/GFXtgO6aA0= cloud.google.com/go/security v1.17.4/go.mod h1:KMuDJH+sEB3KTODd/tLJ7kZK+u2PQt+Cfu0oAxzIhgo= cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= cloud.google.com/go/securitycenter v1.30.0/go.mod h1:/tmosjS/dfTnzJxOzZhTXdX3MXWsCmPWfcYOgkJmaJk= cloud.google.com/go/securitycenter v1.33.1/go.mod h1:jeFisdYUWHr+ig72T4g0dnNCFhRwgwGoQV6GFuEwafw= cloud.google.com/go/servicedirectory v1.10.1/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= cloud.google.com/go/servicedirectory v1.11.7/go.mod h1:fiO/tM0jBpVhpCAe7Yp5HmEsmxSUcOoc4vPrO02v68I= cloud.google.com/go/servicedirectory v1.11.11/go.mod h1:pnynaftaj9LmRLIc6t3r7r7rdCZZKKxui/HaF/RqYfs= cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= cloud.google.com/go/shell v1.7.7/go.mod h1:7OYaMm3TFMSZBh8+QYw6Qef+fdklp7CjjpxYAoJpZbQ= cloud.google.com/go/shell v1.7.11/go.mod h1:SywZHWac7onifaT9m9MmegYp3GgCLm+tgk+w2lXK8vg= cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI= cloud.google.com/go/spanner v1.63.0/go.mod h1:iqDx7urZpgD7RekZ+CFvBRH6kVTW1ZSEb2HMDKOp5Cc= cloud.google.com/go/spanner v1.65.0/go.mod h1:dQGB+w5a67gtyE3qSKPPxzniedrnAmV6tewQeBY7Hxs= cloud.google.com/go/speech v1.17.1/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= cloud.google.com/go/speech v1.23.1/go.mod h1:UNgzNxhNBuo/OxpF1rMhA/U2rdai7ILL6PBXFs70wq0= cloud.google.com/go/speech v1.24.0/go.mod h1:HcVyIh5jRXM5zDMcbFCW+DF2uK/MSGN6Rastt6bj1ic= cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= cloud.google.com/go/storagetransfer v1.10.6/go.mod h1:3sAgY1bx1TpIzfSzdvNGHrGYldeCTyGI/Rzk6Lc6A7w= cloud.google.com/go/storagetransfer v1.10.10/go.mod h1:8+nX+WgQ2ZJJnK8e+RbK/zCXk8T7HdwyQAJeY7cEcm0= cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= cloud.google.com/go/talent v1.6.8/go.mod h1:kqPAJvhxmhoUTuqxjjk2KqA8zUEeTDmH+qKztVubGlQ= cloud.google.com/go/talent v1.6.12/go.mod h1:nT9kNVuJhZX2QgqKZS6t6eCWZs5XEBYRBv6bIMnPmo4= cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= cloud.google.com/go/texttospeech v1.7.7/go.mod h1:XO4Wr2VzWHjzQpMe3gS58Oj68nmtXMyuuH+4t0wy9eA= cloud.google.com/go/texttospeech v1.7.11/go.mod h1:Ua125HU+WT2IkIo5MzQtuNpNEk72soShJQVdorZ1SAE= cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= cloud.google.com/go/tpu v1.6.7/go.mod h1:o8qxg7/Jgt7TCgZc3jNkd4kTsDwuYD3c4JTMqXZ36hU= cloud.google.com/go/tpu v1.6.11/go.mod h1:W0C4xaSj1Ay3VX/H96FRvLt2HDs0CgdRPVI4e7PoCDk= cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= cloud.google.com/go/trace v1.10.7/go.mod h1:qk3eiKmZX0ar2dzIJN/3QhY2PIFh1eqcIdaN5uEjQPM= cloud.google.com/go/trace v1.10.11/go.mod h1:fUr5L3wSXerNfT0f1bBg08W4axS2VbHGgYcfH4KuTXU= cloud.google.com/go/translate v1.8.1/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= cloud.google.com/go/translate v1.10.7/go.mod h1:mH/+8tvcItuy1cOWqU+/Y3iFHgkVUObNIQYI/kiFFiY= cloud.google.com/go/video v1.17.1/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU= cloud.google.com/go/video v1.21.0/go.mod h1:Kqh97xHXZ/bIClgDHf5zkKvU3cvYnLyRefmC8yCBqKI= cloud.google.com/go/video v1.22.0/go.mod h1:CxPshUNAb1ucnzbtruEHlAal9XY+SPG2cFqC/woJzII= cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= cloud.google.com/go/videointelligence v1.11.7/go.mod h1:iMCXbfjurmBVgKuyLedTzv90kcnppOJ6ttb0+rLDID0= cloud.google.com/go/videointelligence v1.11.11/go.mod h1:dab2Ca3AXT6vNJmt3/6ieuquYRckpsActDekLcsd6dU= cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= cloud.google.com/go/vision/v2 v2.8.2/go.mod h1:BHZA1LC7dcHjSr9U9OVhxMtLKd5l2jKPzLRALEJvuaw= cloud.google.com/go/vision/v2 v2.8.6/go.mod h1:G3v0uovxCye3u369JfrHGY43H6u/IQ08x9dw5aVH8yY= cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= cloud.google.com/go/vmmigration v1.7.7/go.mod h1:qYIK5caZY3IDMXQK+A09dy81QU8qBW0/JDTc39OaKRw= cloud.google.com/go/vmmigration v1.7.11/go.mod h1:PmD1fDB0TEHGQR1tDZt9GEXFB9mnKKalLcTVRJKzcQA= cloud.google.com/go/vmwareengine v0.4.1/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= cloud.google.com/go/vmwareengine v1.1.3/go.mod h1:UoyF6LTdrIJRvDN8uUB8d0yimP5A5Ehkr1SRzL1APZw= cloud.google.com/go/vmwareengine v1.2.0/go.mod h1:rPjCHu6hG9N8d6PhkoDWFkqL9xpbFY+ueVW+0pNFbZg= cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= cloud.google.com/go/vpcaccess v1.7.7/go.mod h1:EzfSlgkoAnFWEMznZW0dVNvdjFjEW97vFlKk4VNBhwY= cloud.google.com/go/vpcaccess v1.7.11/go.mod h1:a2cuAiSCI4TVK0Dt6/dRjf22qQvfY+podxst2VvAkcI= cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= cloud.google.com/go/webrisk v1.9.7/go.mod h1:7FkQtqcKLeNwXCdhthdXHIQNcFWPF/OubrlyRcLHNuQ= cloud.google.com/go/webrisk v1.9.11/go.mod h1:mK6M8KEO0ZI7VkrjCq3Tjzw4vYq+3c4DzlMUDVaiswE= cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= cloud.google.com/go/websecurityscanner v1.6.7/go.mod h1:EpiW84G5KXxsjtFKK7fSMQNt8JcuLA8tQp7j0cyV458= cloud.google.com/go/websecurityscanner v1.6.11/go.mod h1:vhAZjksELSg58EZfUQ1BMExD+hxqpn0G0DuyCZQjiTg= cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g= cloud.google.com/go/workflows v1.12.6/go.mod h1:oDbEHKa4otYg4abwdw2Z094jB0TLLiFGAPA78EDAKag= cloud.google.com/go/workflows v1.12.10/go.mod h1:RcKqCiOmKs8wFUEf3EwWZPH5eHc7Oq0kamIyOUCk0IE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw= golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/api v0.180.0/go.mod h1:51AiyoEg1MJPSZ9zvklA8VnRILPXxn1iVen9v25XHAE= google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw= google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= google.golang.org/genproto v0.0.0-20240528184218-531527333157/go.mod h1:ubQlAQnzejB8uZzszhrTCU2Fyp6Vi7ZE5nn0c3W8+qQ= google.golang.org/genproto v0.0.0-20240604185151-ef581f913117/go.mod h1:lesfX/+9iA+3OdqeCpoDddJaNxVB1AB6tD7EfqMmprc= google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d h1:PksQg4dV6Sem3/HkBX+Ltq8T0ke0PKIRBNBatoDTVls= google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:s7iA721uChleev562UJO2OYB0PPT9CMFjV+Ce7VJH5M= google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230629202037-9506855d4529/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:ZevU1kiy5jwy/sOVakfUuu3kq2Fwdgt3pORDQ2Jhkec= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230720185612-659f7aaaa771/go.mod h1:3QoBVwTHkXbY1oRGzlhwhOykfcATQN43LJ6iT8Wy8kE= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:IN9OQUXZ0xT+26MDwZL8fJcYw+y99b0eYPA2U15Jt8o= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240513163218-0867130af1f8/go.mod h1:RCpt0+3mpEDPldc32vXBM8ADXlFL95T8Chxx0nv0/zE= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240604185151-ef581f913117/go.mod h1:0J6mmn3XAEjfNbPvpH63c0RXCjGNFcCzlEfWSN4In+k= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:/oe3+SiHAwz6s+M25PyTygWm3lnrhmGqIuIfkoUocqk= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240708141625-4ad9e859172b/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ= google.golang.org/genproto/googleapis/bytestream v0.0.0-20241021214115-324edc3d5d38/go.mod h1:T8O3fECQbif8cez15vxAcjbwXxvL2xbnvbQ7ZfiMAMs= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= gax-go-2.14.1/header.go000066400000000000000000000035121473113767300145550ustar00rootroot00000000000000// Copyright 2018, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import v2 "github.com/googleapis/gax-go/v2" // XGoogHeader is for use by the Google Cloud Libraries only. // // XGoogHeader formats key-value pairs. // The resulting string is suitable for x-goog-api-client header. func XGoogHeader(keyval ...string) string { return v2.XGoogHeader(keyval...) } gax-go-2.14.1/internal/000077500000000000000000000000001473113767300146115ustar00rootroot00000000000000gax-go-2.14.1/internal/kokoro/000077500000000000000000000000001473113767300161155ustar00rootroot00000000000000gax-go-2.14.1/internal/kokoro/test.sh000077500000000000000000000017331473113767300174370ustar00rootroot00000000000000#!/bin/bash # Fail on any error set -eo # Display commands being run set -x # cd to project dir on Kokoro instance cd github/gax-go go version # Set $GOPATH export GOPATH="$HOME/go" export PATH="$GOPATH/bin:$PATH" export GO111MODULE=on try3() { eval "$*" || eval "$*" || eval "$*"; } # All packages, including +build tools, are fetched. try3 go mod download ./internal/kokoro/vet.sh go get github.com/jstemmer/go-junit-report set +e go test -race -v . 2>&1 | tee sponge_log.log cat sponge_log.log | go-junit-report -set-exit-code > sponge_log.xml exit_code=$? cd v2 set -e try3 go mod download set +e go test -race -v . 2>&1 | tee sponge_log.log cat sponge_log.log | go-junit-report -set-exit-code > sponge_log.xml exit_code=$(($exit_code+$?)) # Send logs to Flaky Bot for continuous builds. if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then cd .. chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot $KOKORO_GFILE_DIR/linux_amd64/flakybot fi exit $exit_code gax-go-2.14.1/internal/kokoro/trampoline.sh000066400000000000000000000016131473113767300206240ustar00rootroot00000000000000#!/bin/bash # Copyright 2018 Google Inc. # # 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 # # http://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. set -eo pipefail # Always run the cleanup script, regardless of the success of bouncing into # the container. function cleanup() { chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh echo "cleanup"; } trap cleanup EXIT python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" gax-go-2.14.1/internal/kokoro/vet.sh000077500000000000000000000016061473113767300172550ustar00rootroot00000000000000#!/bin/bash # Fail on any error set -eo # Display commands being run set -x if [[ $KOKORO_JOB_NAME != *"latest-version"* ]]; then exit 0 fi # Look at all .go files (ignoring .pb.go files) and make sure they have a Copyright. Fail if any don't. find . -type f -name "*.go" ! -name "*.pb.go" -exec grep -L "\(Copyright [0-9]\{4,\}\)" {} \; 2>&1 | tee /dev/stderr | (! read) # Fail if a dependency was added without the necessary go.mod/go.sum change # being part of the commit. go mod tidy git diff go.mod | tee /dev/stderr | (! read) git diff go.sum | tee /dev/stderr | (! read) pushd v2 go mod tidy git diff go.mod | tee /dev/stderr | (! read) git diff go.sum | tee /dev/stderr | (! read) popd # Easier to debug CI. pwd gofmt -s -d -l . 2>&1 | tee /dev/stderr | (! read) goimports -l . 2>&1 | tee /dev/stderr | (! read) golint ./... 2>&1 | tee /dev/stderr | (! read) staticcheck ./... gax-go-2.14.1/invoke.go000066400000000000000000000041121473113767300146150ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "context" "time" v2 "github.com/googleapis/gax-go/v2" ) // APICall is a user defined call stub. type APICall = v2.APICall // Invoke calls the given APICall, // performing retries as specified by opts, if any. func Invoke(ctx context.Context, call APICall, opts ...CallOption) error { return v2.Invoke(ctx, call, opts...) } // Sleep is similar to time.Sleep, but it can be interrupted by ctx.Done() closing. // If interrupted, Sleep returns ctx.Err(). func Sleep(ctx context.Context, d time.Duration) error { return v2.Sleep(ctx, d) } gax-go-2.14.1/v2/000077500000000000000000000000001473113767300133245ustar00rootroot00000000000000gax-go-2.14.1/v2/.release-please-manifest.json000066400000000000000000000000271473113767300207670ustar00rootroot00000000000000{ "v2": "2.14.1" } gax-go-2.14.1/v2/CHANGES.md000066400000000000000000000174561473113767300147330ustar00rootroot00000000000000# Changelog ## [2.14.1](https://github.com/googleapis/gax-go/compare/v2.14.0...v2.14.1) (2024-12-19) ### Bug Fixes * update golang.org/x/net to v0.33.0 ([#391](https://github.com/googleapis/gax-go/issues/391)) ([547a5b4](https://github.com/googleapis/gax-go/commit/547a5b43aa6f376f71242da9f18e65fbdfb342f6)) ### Documentation * fix godoc to refer to the proper envvar ([#387](https://github.com/googleapis/gax-go/issues/387)) ([dc6baf7](https://github.com/googleapis/gax-go/commit/dc6baf75c1a737233739630b5af6c9759f08abcd)) ## [2.14.0](https://github.com/googleapis/gax-go/compare/v2.13.0...v2.14.0) (2024-11-13) ### Features * **internallog:** add a logging support package ([#380](https://github.com/googleapis/gax-go/issues/380)) ([c877470](https://github.com/googleapis/gax-go/commit/c87747098135631a3de5865ed03aaf2c79fd9319)) ## [2.13.0](https://github.com/googleapis/gax-go/compare/v2.12.5...v2.13.0) (2024-07-22) ### Features * **iterator:** add package to help work with new iter.Seq types ([#358](https://github.com/googleapis/gax-go/issues/358)) ([6bccdaa](https://github.com/googleapis/gax-go/commit/6bccdaac011fe6fd147e4eb533a8e6520b7d4acc)) ## [2.12.5](https://github.com/googleapis/gax-go/compare/v2.12.4...v2.12.5) (2024-06-18) ### Bug Fixes * **v2/apierror:** fix (*APIError).Error() for unwrapped Status ([#351](https://github.com/googleapis/gax-go/issues/351)) ([22c16e7](https://github.com/googleapis/gax-go/commit/22c16e7bff5402bdc4c25063771cdd01c650b500)), refs [#350](https://github.com/googleapis/gax-go/issues/350) ## [2.12.4](https://github.com/googleapis/gax-go/compare/v2.12.3...v2.12.4) (2024-05-03) ### Bug Fixes * provide unmarshal options for streams ([#343](https://github.com/googleapis/gax-go/issues/343)) ([ddf9a90](https://github.com/googleapis/gax-go/commit/ddf9a90bf180295d49875e15cb80b2136a49dbaf)) ## [2.12.3](https://github.com/googleapis/gax-go/compare/v2.12.2...v2.12.3) (2024-03-14) ### Bug Fixes * bump protobuf dep to v1.33 ([#333](https://github.com/googleapis/gax-go/issues/333)) ([2892b22](https://github.com/googleapis/gax-go/commit/2892b22c1ae8a70dec3448d82e634643fe6c1be2)) ## [2.12.2](https://github.com/googleapis/gax-go/compare/v2.12.1...v2.12.2) (2024-02-23) ### Bug Fixes * **v2/callctx:** fix SetHeader race by cloning header map ([#326](https://github.com/googleapis/gax-go/issues/326)) ([534311f](https://github.com/googleapis/gax-go/commit/534311f0f163d101f30657736c0e6f860e9c39dc)) ## [2.12.1](https://github.com/googleapis/gax-go/compare/v2.12.0...v2.12.1) (2024-02-13) ### Bug Fixes * add XGoogFieldMaskHeader constant ([#321](https://github.com/googleapis/gax-go/issues/321)) ([666ee08](https://github.com/googleapis/gax-go/commit/666ee08931041b7fed56bed7132649785b2d3dfe)) ## [2.12.0](https://github.com/googleapis/gax-go/compare/v2.11.0...v2.12.0) (2023-06-26) ### Features * **v2/callctx:** add new callctx package ([#291](https://github.com/googleapis/gax-go/issues/291)) ([11503ed](https://github.com/googleapis/gax-go/commit/11503ed98df4ae1bbdedf91ff64d47e63f187d68)) * **v2:** add BuildHeaders and InsertMetadataIntoOutgoingContext to header ([#290](https://github.com/googleapis/gax-go/issues/290)) ([6a4b89f](https://github.com/googleapis/gax-go/commit/6a4b89f5551a40262e7c3caf2e1bdc7321b76ea1)) ## [2.11.0](https://github.com/googleapis/gax-go/compare/v2.10.0...v2.11.0) (2023-06-13) ### Features * **v2:** add GoVersion package variable ([#283](https://github.com/googleapis/gax-go/issues/283)) ([26553cc](https://github.com/googleapis/gax-go/commit/26553ccadb4016b189881f52e6c253b68bb3e3d5)) ### Bug Fixes * **v2:** handle space in non-devel go version ([#288](https://github.com/googleapis/gax-go/issues/288)) ([fd7bca0](https://github.com/googleapis/gax-go/commit/fd7bca029a1c5e63def8f0a5fd1ec3f725d92f75)) ## [2.10.0](https://github.com/googleapis/gax-go/compare/v2.9.1...v2.10.0) (2023-05-30) ### Features * update dependencies ([#280](https://github.com/googleapis/gax-go/issues/280)) ([4514281](https://github.com/googleapis/gax-go/commit/4514281058590f3637c36bfd49baa65c4d3cfb21)) ## [2.9.1](https://github.com/googleapis/gax-go/compare/v2.9.0...v2.9.1) (2023-05-23) ### Bug Fixes * **v2:** drop cloud lro test dep ([#276](https://github.com/googleapis/gax-go/issues/276)) ([c67eeba](https://github.com/googleapis/gax-go/commit/c67eeba0f10a3294b1d93c1b8fbe40211a55ae5f)), refs [#270](https://github.com/googleapis/gax-go/issues/270) ## [2.9.0](https://github.com/googleapis/gax-go/compare/v2.8.0...v2.9.0) (2023-05-22) ### Features * **apierror:** add method to return HTTP status code conditionally ([#274](https://github.com/googleapis/gax-go/issues/274)) ([5874431](https://github.com/googleapis/gax-go/commit/587443169acd10f7f86d1989dc8aaf189e645e98)), refs [#229](https://github.com/googleapis/gax-go/issues/229) ### Documentation * add ref to usage with clients ([#272](https://github.com/googleapis/gax-go/issues/272)) ([ea4d72d](https://github.com/googleapis/gax-go/commit/ea4d72d514beba4de450868b5fb028601a29164e)), refs [#228](https://github.com/googleapis/gax-go/issues/228) ## [2.8.0](https://github.com/googleapis/gax-go/compare/v2.7.1...v2.8.0) (2023-03-15) ### Features * **v2:** add WithTimeout option ([#259](https://github.com/googleapis/gax-go/issues/259)) ([9a8da43](https://github.com/googleapis/gax-go/commit/9a8da43693002448b1e8758023699387481866d1)) ## [2.7.1](https://github.com/googleapis/gax-go/compare/v2.7.0...v2.7.1) (2023-03-06) ### Bug Fixes * **v2/apierror:** return Unknown GRPCStatus when err source is HTTP ([#260](https://github.com/googleapis/gax-go/issues/260)) ([043b734](https://github.com/googleapis/gax-go/commit/043b73437a240a91229207fb3ee52a9935a36f23)), refs [#254](https://github.com/googleapis/gax-go/issues/254) ## [2.7.0](https://github.com/googleapis/gax-go/compare/v2.6.0...v2.7.0) (2022-11-02) ### Features * update google.golang.org/api to latest ([#240](https://github.com/googleapis/gax-go/issues/240)) ([f690a02](https://github.com/googleapis/gax-go/commit/f690a02c806a2903bdee943ede3a58e3a331ebd6)) * **v2/apierror:** add apierror.FromWrappingError ([#238](https://github.com/googleapis/gax-go/issues/238)) ([9dbd96d](https://github.com/googleapis/gax-go/commit/9dbd96d59b9d54ceb7c025513aa8c1a9d727382f)) ## [2.6.0](https://github.com/googleapis/gax-go/compare/v2.5.1...v2.6.0) (2022-10-13) ### Features * **v2:** copy DetermineContentType functionality ([#230](https://github.com/googleapis/gax-go/issues/230)) ([2c52a70](https://github.com/googleapis/gax-go/commit/2c52a70bae965397f740ed27d46aabe89ff249b3)) ## [2.5.1](https://github.com/googleapis/gax-go/compare/v2.5.0...v2.5.1) (2022-08-04) ### Bug Fixes * **v2:** resolve bad genproto pseudoversion in go.mod ([#218](https://github.com/googleapis/gax-go/issues/218)) ([1379b27](https://github.com/googleapis/gax-go/commit/1379b27e9846d959f7e1163b9ef298b3c92c8d23)) ## [2.5.0](https://github.com/googleapis/gax-go/compare/v2.4.0...v2.5.0) (2022-08-04) ### Features * add ExtractProtoMessage to apierror ([#213](https://github.com/googleapis/gax-go/issues/213)) ([a6ce70c](https://github.com/googleapis/gax-go/commit/a6ce70c725c890533a9de6272d3b5ba2e336d6bb)) ## [2.4.0](https://github.com/googleapis/gax-go/compare/v2.3.0...v2.4.0) (2022-05-09) ### Features * **v2:** add OnHTTPCodes CallOption ([#188](https://github.com/googleapis/gax-go/issues/188)) ([ba7c534](https://github.com/googleapis/gax-go/commit/ba7c5348363ab6c33e1cee3c03c0be68a46ca07c)) ### Bug Fixes * **v2/apierror:** use errors.As in FromError ([#189](https://github.com/googleapis/gax-go/issues/189)) ([f30f05b](https://github.com/googleapis/gax-go/commit/f30f05be583828f4c09cca4091333ea88ff8d79e)) ### Miscellaneous Chores * **v2:** bump release-please processing ([#192](https://github.com/googleapis/gax-go/issues/192)) ([56172f9](https://github.com/googleapis/gax-go/commit/56172f971d1141d7687edaac053ad3470af76719)) gax-go-2.14.1/v2/apierror/000077500000000000000000000000001473113767300151475ustar00rootroot00000000000000gax-go-2.14.1/v2/apierror/apierror.go000066400000000000000000000275211473113767300173300ustar00rootroot00000000000000// Copyright 2021, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package apierror implements a wrapper error for parsing error details from // API calls. Both HTTP & gRPC status errors are supported. // // For examples of how to use [APIError] with client libraries please reference // [Inspecting errors](https://pkg.go.dev/cloud.google.com/go#hdr-Inspecting_errors) // in the client library documentation. package apierror import ( "errors" "fmt" "strings" jsonerror "github.com/googleapis/gax-go/v2/apierror/internal/proto" "google.golang.org/api/googleapi" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) // ErrDetails holds the google/rpc/error_details.proto messages. type ErrDetails struct { ErrorInfo *errdetails.ErrorInfo BadRequest *errdetails.BadRequest PreconditionFailure *errdetails.PreconditionFailure QuotaFailure *errdetails.QuotaFailure RetryInfo *errdetails.RetryInfo ResourceInfo *errdetails.ResourceInfo RequestInfo *errdetails.RequestInfo DebugInfo *errdetails.DebugInfo Help *errdetails.Help LocalizedMessage *errdetails.LocalizedMessage // Unknown stores unidentifiable error details. Unknown []interface{} } // ErrMessageNotFound is used to signal ExtractProtoMessage found no matching messages. var ErrMessageNotFound = errors.New("message not found") // ExtractProtoMessage provides a mechanism for extracting protobuf messages from the // Unknown error details. If ExtractProtoMessage finds an unknown message of the same type, // the content of the message is copied to the provided message. // // ExtractProtoMessage will return ErrMessageNotFound if there are no message matching the // protocol buffer type of the provided message. func (e ErrDetails) ExtractProtoMessage(v proto.Message) error { if v == nil { return ErrMessageNotFound } for _, elem := range e.Unknown { if elemProto, ok := elem.(proto.Message); ok { if v.ProtoReflect().Type() == elemProto.ProtoReflect().Type() { proto.Merge(v, elemProto) return nil } } } return ErrMessageNotFound } func (e ErrDetails) String() string { var d strings.Builder if e.ErrorInfo != nil { d.WriteString(fmt.Sprintf("error details: name = ErrorInfo reason = %s domain = %s metadata = %s\n", e.ErrorInfo.GetReason(), e.ErrorInfo.GetDomain(), e.ErrorInfo.GetMetadata())) } if e.BadRequest != nil { v := e.BadRequest.GetFieldViolations() var f []string var desc []string for _, x := range v { f = append(f, x.GetField()) desc = append(desc, x.GetDescription()) } d.WriteString(fmt.Sprintf("error details: name = BadRequest field = %s desc = %s\n", strings.Join(f, " "), strings.Join(desc, " "))) } if e.PreconditionFailure != nil { v := e.PreconditionFailure.GetViolations() var t []string var s []string var desc []string for _, x := range v { t = append(t, x.GetType()) s = append(s, x.GetSubject()) desc = append(desc, x.GetDescription()) } d.WriteString(fmt.Sprintf("error details: name = PreconditionFailure type = %s subj = %s desc = %s\n", strings.Join(t, " "), strings.Join(s, " "), strings.Join(desc, " "))) } if e.QuotaFailure != nil { v := e.QuotaFailure.GetViolations() var s []string var desc []string for _, x := range v { s = append(s, x.GetSubject()) desc = append(desc, x.GetDescription()) } d.WriteString(fmt.Sprintf("error details: name = QuotaFailure subj = %s desc = %s\n", strings.Join(s, " "), strings.Join(desc, " "))) } if e.RequestInfo != nil { d.WriteString(fmt.Sprintf("error details: name = RequestInfo id = %s data = %s\n", e.RequestInfo.GetRequestId(), e.RequestInfo.GetServingData())) } if e.ResourceInfo != nil { d.WriteString(fmt.Sprintf("error details: name = ResourceInfo type = %s resourcename = %s owner = %s desc = %s\n", e.ResourceInfo.GetResourceType(), e.ResourceInfo.GetResourceName(), e.ResourceInfo.GetOwner(), e.ResourceInfo.GetDescription())) } if e.RetryInfo != nil { d.WriteString(fmt.Sprintf("error details: retry in %s\n", e.RetryInfo.GetRetryDelay().AsDuration())) } if e.Unknown != nil { var s []string for _, x := range e.Unknown { s = append(s, fmt.Sprintf("%v", x)) } d.WriteString(fmt.Sprintf("error details: name = Unknown desc = %s\n", strings.Join(s, " "))) } if e.DebugInfo != nil { d.WriteString(fmt.Sprintf("error details: name = DebugInfo detail = %s stack = %s\n", e.DebugInfo.GetDetail(), strings.Join(e.DebugInfo.GetStackEntries(), " "))) } if e.Help != nil { var desc []string var url []string for _, x := range e.Help.Links { desc = append(desc, x.GetDescription()) url = append(url, x.GetUrl()) } d.WriteString(fmt.Sprintf("error details: name = Help desc = %s url = %s\n", strings.Join(desc, " "), strings.Join(url, " "))) } if e.LocalizedMessage != nil { d.WriteString(fmt.Sprintf("error details: name = LocalizedMessage locale = %s msg = %s\n", e.LocalizedMessage.GetLocale(), e.LocalizedMessage.GetMessage())) } return d.String() } // APIError wraps either a gRPC Status error or a HTTP googleapi.Error. It // implements error and Status interfaces. type APIError struct { err error status *status.Status httpErr *googleapi.Error details ErrDetails } // Details presents the error details of the APIError. func (a *APIError) Details() ErrDetails { return a.details } // Unwrap extracts the original error. func (a *APIError) Unwrap() error { return a.err } // Error returns a readable representation of the APIError. func (a *APIError) Error() string { var msg string if a.httpErr != nil { // Truncate the googleapi.Error message because it dumps the Details in // an ugly way. msg = fmt.Sprintf("googleapi: Error %d: %s", a.httpErr.Code, a.httpErr.Message) } else if a.status != nil && a.err != nil { msg = a.err.Error() } else if a.status != nil { msg = a.status.Message() } return strings.TrimSpace(fmt.Sprintf("%s\n%s", msg, a.details)) } // GRPCStatus extracts the underlying gRPC Status error. // This method is necessary to fulfill the interface // described in https://pkg.go.dev/google.golang.org/grpc/status#FromError. func (a *APIError) GRPCStatus() *status.Status { return a.status } // Reason returns the reason in an ErrorInfo. // If ErrorInfo is nil, it returns an empty string. func (a *APIError) Reason() string { return a.details.ErrorInfo.GetReason() } // Domain returns the domain in an ErrorInfo. // If ErrorInfo is nil, it returns an empty string. func (a *APIError) Domain() string { return a.details.ErrorInfo.GetDomain() } // Metadata returns the metadata in an ErrorInfo. // If ErrorInfo is nil, it returns nil. func (a *APIError) Metadata() map[string]string { return a.details.ErrorInfo.GetMetadata() } // setDetailsFromError parses a Status error or a googleapi.Error // and sets status and details or httpErr and details, respectively. // It returns false if neither Status nor googleapi.Error can be parsed. // When err is a googleapi.Error, the status of the returned error will // be set to an Unknown error, rather than nil, since a nil code is // interpreted as OK in the gRPC status package. func (a *APIError) setDetailsFromError(err error) bool { st, isStatus := status.FromError(err) var herr *googleapi.Error isHTTPErr := errors.As(err, &herr) switch { case isStatus: a.status = st a.details = parseDetails(st.Details()) case isHTTPErr: a.httpErr = herr a.details = parseHTTPDetails(herr) a.status = status.New(codes.Unknown, herr.Message) default: return false } return true } // FromError parses a Status error or a googleapi.Error and builds an // APIError, wrapping the provided error in the new APIError. It // returns false if neither Status nor googleapi.Error can be parsed. func FromError(err error) (*APIError, bool) { return ParseError(err, true) } // ParseError parses a Status error or a googleapi.Error and builds an // APIError. If wrap is true, it wraps the error in the new APIError. // It returns false if neither Status nor googleapi.Error can be parsed. func ParseError(err error, wrap bool) (*APIError, bool) { if err == nil { return nil, false } ae := APIError{} if wrap { ae = APIError{err: err} } if !ae.setDetailsFromError(err) { return nil, false } return &ae, true } // parseDetails accepts a slice of interface{} that should be backed by some // sort of proto.Message that can be cast to the google/rpc/error_details.proto // types. // // This is for internal use only. func parseDetails(details []interface{}) ErrDetails { var ed ErrDetails for _, d := range details { switch d := d.(type) { case *errdetails.ErrorInfo: ed.ErrorInfo = d case *errdetails.BadRequest: ed.BadRequest = d case *errdetails.PreconditionFailure: ed.PreconditionFailure = d case *errdetails.QuotaFailure: ed.QuotaFailure = d case *errdetails.RetryInfo: ed.RetryInfo = d case *errdetails.ResourceInfo: ed.ResourceInfo = d case *errdetails.RequestInfo: ed.RequestInfo = d case *errdetails.DebugInfo: ed.DebugInfo = d case *errdetails.Help: ed.Help = d case *errdetails.LocalizedMessage: ed.LocalizedMessage = d default: ed.Unknown = append(ed.Unknown, d) } } return ed } // parseHTTPDetails will convert the given googleapi.Error into the protobuf // representation then parse the Any values that contain the error details. // // This is for internal use only. func parseHTTPDetails(gae *googleapi.Error) ErrDetails { e := &jsonerror.Error{} if err := protojson.Unmarshal([]byte(gae.Body), e); err != nil { // If the error body does not conform to the error schema, ignore it // altogther. See https://cloud.google.com/apis/design/errors#http_mapping. return ErrDetails{} } // Coerce the Any messages into proto.Message then parse the details. details := []interface{}{} for _, any := range e.GetError().GetDetails() { m, err := any.UnmarshalNew() if err != nil { // Ignore malformed Any values. continue } details = append(details, m) } return parseDetails(details) } // HTTPCode returns the underlying HTTP response status code. This method returns // `-1` if the underlying error is a [google.golang.org/grpc/status.Status]. To // check gRPC error codes use [google.golang.org/grpc/status.Code]. func (a *APIError) HTTPCode() int { if a.httpErr == nil { return -1 } return a.httpErr.Code } gax-go-2.14.1/v2/apierror/apierror_test.go000066400000000000000000000433201473113767300203620ustar00rootroot00000000000000// Copyright 2021, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package apierror import ( "context" "errors" "flag" "io/ioutil" "path/filepath" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" jsonerror "github.com/googleapis/gax-go/v2/apierror/internal/proto" "google.golang.org/api/googleapi" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" ) var update = flag.Bool("update", false, "update golden files") func TestDetails(t *testing.T) { qf := &errdetails.QuotaFailure{ Violations: []*errdetails.QuotaFailure_Violation{{Subject: "Foo", Description: "Bar"}}, } qS, _ := status.New(codes.ResourceExhausted, "test").WithDetails(qf) apierr := &APIError{ err: qS.Err(), status: qS, details: ErrDetails{QuotaFailure: qf}, } got := apierr.Details() want := ErrDetails{QuotaFailure: qf} if diff := cmp.Diff(got, want, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("got(-), want(+):\n%s", diff) } } func TestDetails_ExtractProtoMessage(t *testing.T) { customError := &jsonerror.CustomError{ Code: jsonerror.CustomError_UNIVERSE_WAS_DESTROYED, Entity: "some entity", ErrorMessage: "custom error message", } testCases := []struct { description string src *status.Status extract proto.Message want interface{} wantErr error }{ { description: "no details", src: status.New(codes.Unimplemented, "unimp"), extract: &jsonerror.CustomError{}, wantErr: ErrMessageNotFound, }, { description: "nil argument", src: func() *status.Status { s, _ := status.New(codes.Unauthenticated, "who are you").WithDetails( &descriptorpb.DescriptorProto{}, ) return s }(), wantErr: ErrMessageNotFound, }, { description: "custom error success", src: func() *status.Status { s, _ := status.New(codes.Unknown, "unknown error").WithDetails( customError, ) return s }(), extract: &jsonerror.CustomError{}, want: customError, }, } for _, tc := range testCases { apiErr, ok := FromError(tc.src.Err()) if !ok { t.Errorf("%s: FromError failure", tc.description) } val := tc.extract gotErr := apiErr.Details().ExtractProtoMessage(val) if tc.wantErr != nil { if !errors.Is(gotErr, tc.wantErr) { t.Errorf("%s: got error %v, wanted error %v", tc.description, gotErr, tc.wantErr) } } else { if gotErr != nil { t.Errorf("%s: got error %v", tc.description, gotErr) } if diff := cmp.Diff(val, tc.want, protocmp.Transform()); diff != "" { t.Errorf("%s: got(-), want(+):\n%s", tc.description, diff) } } } } func TestUnwrap(t *testing.T) { pf := &errdetails.PreconditionFailure{ Violations: []*errdetails.PreconditionFailure_Violation{{Type: "Foo", Subject: "Bar", Description: "desc"}}, } pS, _ := status.New(codes.FailedPrecondition, "test").WithDetails(pf) apierr := &APIError{ err: pS.Err(), status: pS, details: ErrDetails{PreconditionFailure: pf}, } got := apierr.Unwrap() want := pS.Err() if diff := cmp.Diff(got, want, cmpopts.EquateErrors()); diff != "" { t.Errorf("got(-), want(+):\n%s", diff) } } func TestError(t *testing.T) { ei := &errdetails.ErrorInfo{ Reason: "Foo", Domain: "Bar", Metadata: map[string]string{"type": "test"}, } eS, _ := status.New(codes.Unauthenticated, "ei").WithDetails(ei) br := &errdetails.BadRequest{FieldViolations: []*errdetails.BadRequest_FieldViolation{{ Field: "Foo", Description: "Bar", }}, } bS, _ := status.New(codes.InvalidArgument, "br").WithDetails(br) qf := &errdetails.QuotaFailure{ Violations: []*errdetails.QuotaFailure_Violation{{Subject: "Foo", Description: "Bar"}}, } pf := &errdetails.PreconditionFailure{ Violations: []*errdetails.PreconditionFailure_Violation{{Type: "Foo", Subject: "Bar", Description: "desc"}}, } ri := &errdetails.RetryInfo{ RetryDelay: &durationpb.Duration{Seconds: 10, Nanos: 10}, } rq := &errdetails.RequestInfo{ RequestId: "Foo", ServingData: "Bar", } rqS, _ := status.New(codes.Canceled, "Request cancelled by client").WithDetails(rq, ri, pf, br, qf) rs := &errdetails.ResourceInfo{ ResourceType: "Foo", ResourceName: "Bar", Owner: "Client", Description: "Directory not Found", } rS, _ := status.New(codes.NotFound, "rs").WithDetails(rs) deb := &errdetails.DebugInfo{ StackEntries: []string{"Foo", "Bar"}, Detail: "Stack", } dS, _ := status.New(codes.DataLoss, "Here is the debug info").WithDetails(deb) hp := &errdetails.Help{ Links: []*errdetails.Help_Link{{Description: "Foo", Url: "Bar"}}, } hS, _ := status.New(codes.Unimplemented, "Help Info").WithDetails(hp) lo := &errdetails.LocalizedMessage{ Locale: "Foo", Message: "Bar", } lS, _ := status.New(codes.Unknown, "Localized Message").WithDetails(lo) var uu []interface{} uu = append(uu, "unknown detail 1") uS := status.New(codes.Unknown, "Unknown") httpErrInfo := &errdetails.ErrorInfo{Reason: "just because", Domain: "tests"} any, err := anypb.New(httpErrInfo) if err != nil { t.Fatal(err) } e := &jsonerror.Error{Error: &jsonerror.Error_Status{Details: []*anypb.Any{any}}} data, err := protojson.Marshal(e) if err != nil { t.Fatal(err) } hae := &googleapi.Error{ Message: "just because", Body: string(data), } haeS := status.New(codes.Unknown, "just because") tests := []struct { apierr *APIError name string }{ {&APIError{err: eS.Err(), status: eS, details: ErrDetails{ErrorInfo: ei}}, "error_info"}, {&APIError{err: bS.Err(), status: bS, details: ErrDetails{BadRequest: br}}, "bad_request"}, {&APIError{err: rqS.Err(), status: rqS, details: ErrDetails{RequestInfo: rq, RetryInfo: ri, PreconditionFailure: pf, QuotaFailure: qf, BadRequest: br}}, "multiple_info"}, {&APIError{err: bS.Err(), status: rS, details: ErrDetails{ResourceInfo: rs}}, "resource_info"}, {&APIError{err: bS.Err(), status: dS, details: ErrDetails{DebugInfo: deb}}, "debug_info"}, {&APIError{err: bS.Err(), status: hS, details: ErrDetails{Help: hp}}, "help"}, {&APIError{err: bS.Err(), status: lS, details: ErrDetails{LocalizedMessage: lo}}, "localized_message"}, {&APIError{err: bS.Err(), status: uS, details: ErrDetails{Unknown: uu}}, "unknown"}, {&APIError{err: bS.Err(), status: bS, details: ErrDetails{}}, "empty"}, {&APIError{err: hae, httpErr: hae, status: haeS, details: ErrDetails{ErrorInfo: httpErrInfo}}, "http_err"}, } for _, tc := range tests { t.Helper() got := tc.apierr.Error() want, err := golden(tc.name, got) if err != nil { t.Fatal(err) } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("got(-), want(+),: \n%s", diff) } } } func TestGRPCStatus(t *testing.T) { qf := &errdetails.QuotaFailure{ Violations: []*errdetails.QuotaFailure_Violation{{Subject: "Foo", Description: "Bar"}}, } want, _ := status.New(codes.ResourceExhausted, "test").WithDetails(qf) apierr := &APIError{ err: want.Err(), status: want, details: ErrDetails{QuotaFailure: qf}, } got := apierr.GRPCStatus() if diff := cmp.Diff(got, want, cmp.Comparer(proto.Equal), cmp.AllowUnexported(status.Status{})); diff != "" { t.Errorf("got(-), want(+),: \n%s", diff) } } func TestReason(t *testing.T) { tests := []struct { ei *errdetails.ErrorInfo }{ {&errdetails.ErrorInfo{Reason: "Foo"}}, {&errdetails.ErrorInfo{}}, } for _, tc := range tests { apierr := toAPIError(tc.ei) if diff := cmp.Diff(apierr.Reason(), tc.ei.GetReason()); diff != "" { t.Errorf("got(-), want(+),: \n%s", diff) } } } func TestDomain(t *testing.T) { tests := []struct { ei *errdetails.ErrorInfo }{ {&errdetails.ErrorInfo{Domain: "Bar"}}, {&errdetails.ErrorInfo{}}, } for _, tc := range tests { apierr := toAPIError(tc.ei) if diff := cmp.Diff(apierr.Domain(), tc.ei.GetDomain()); diff != "" { t.Errorf("got(-), want(+),: \n%s", diff) } } } func TestMetadata(t *testing.T) { tests := []struct { ei *errdetails.ErrorInfo }{ {&errdetails.ErrorInfo{Metadata: map[string]string{"type": "test"}}}, {&errdetails.ErrorInfo{}}, } for _, tc := range tests { apierr := toAPIError(tc.ei) if diff := cmp.Diff(apierr.Metadata(), tc.ei.GetMetadata()); diff != "" { t.Errorf("got(-), want(+),: \n%s", diff) } } } func TestFromError(t *testing.T) { ei := &errdetails.ErrorInfo{ Reason: "Foo", Domain: "Bar", Metadata: map[string]string{"type": "test"}, } eS, _ := status.New(codes.Unauthenticated, "ei").WithDetails(ei) br := &errdetails.BadRequest{FieldViolations: []*errdetails.BadRequest_FieldViolation{{ Field: "Foo", Description: "Bar", }}, } bS, _ := status.New(codes.InvalidArgument, "br").WithDetails(br) qf := &errdetails.QuotaFailure{ Violations: []*errdetails.QuotaFailure_Violation{{Subject: "Foo", Description: "Bar"}}, } qS, _ := status.New(codes.ResourceExhausted, "qf").WithDetails(qf, br) pf := &errdetails.PreconditionFailure{ Violations: []*errdetails.PreconditionFailure_Violation{{Type: "Foo", Subject: "Bar", Description: "desc"}}, } pS, _ := status.New(codes.FailedPrecondition, "pf").WithDetails(pf) ri := &errdetails.RetryInfo{ RetryDelay: &durationpb.Duration{Seconds: 10, Nanos: 10}, } riS, _ := status.New(codes.Unavailable, "foo").WithDetails(ri) rs := &errdetails.ResourceInfo{ ResourceType: "Foo", ResourceName: "Bar", Owner: "Client", Description: "Directory not Found", } rS, _ := status.New(codes.NotFound, "rs").WithDetails(rs) rq := &errdetails.RequestInfo{ RequestId: "Foo", ServingData: "Bar", } rqS, _ := status.New(codes.Canceled, "Request cancelled by client").WithDetails(rq) deb := &errdetails.DebugInfo{ StackEntries: []string{"Foo", "Bar"}, Detail: "Stack", } dS, _ := status.New(codes.DataLoss, "Here is the debug info").WithDetails(deb) hp := &errdetails.Help{ Links: []*errdetails.Help_Link{{Description: "Foo", Url: "Bar"}}, } hS, _ := status.New(codes.Unimplemented, "Help Info").WithDetails(hp) lo := &errdetails.LocalizedMessage{ Locale: "Foo", Message: "Bar", } lS, _ := status.New(codes.Unknown, "Localized Message").WithDetails(lo) msg := &descriptorpb.DescriptorProto{ Name: proto.String("Foo"), } u := []interface{}{msg} uS, _ := status.New(codes.Unknown, "test").WithDetails(msg) httpErrInfo := &errdetails.ErrorInfo{Reason: "just because", Domain: "tests"} any, err := anypb.New(httpErrInfo) if err != nil { t.Fatal(err) } e := &jsonerror.Error{Error: &jsonerror.Error_Status{Details: []*anypb.Any{any}}} data, err := protojson.Marshal(e) if err != nil { t.Fatal(err) } hae := &googleapi.Error{ Message: "just because", Body: string(data), } haeS := status.New(codes.Unknown, "just because") tests := []struct { apierr *APIError b bool }{ {&APIError{err: eS.Err(), status: eS, details: ErrDetails{ErrorInfo: ei}}, true}, {&APIError{err: bS.Err(), status: bS, details: ErrDetails{BadRequest: br}}, true}, {&APIError{err: qS.Err(), status: qS, details: ErrDetails{QuotaFailure: qf, BadRequest: br}}, true}, {&APIError{err: pS.Err(), status: pS, details: ErrDetails{PreconditionFailure: pf}}, true}, {&APIError{err: riS.Err(), status: riS, details: ErrDetails{RetryInfo: ri}}, true}, {&APIError{err: rS.Err(), status: rS, details: ErrDetails{ResourceInfo: rs}}, true}, {&APIError{err: rqS.Err(), status: rqS, details: ErrDetails{RequestInfo: rq}}, true}, {&APIError{err: dS.Err(), status: dS, details: ErrDetails{DebugInfo: deb}}, true}, {&APIError{err: hS.Err(), status: hS, details: ErrDetails{Help: hp}}, true}, {&APIError{err: lS.Err(), status: lS, details: ErrDetails{LocalizedMessage: lo}}, true}, {&APIError{err: uS.Err(), status: uS, details: ErrDetails{Unknown: u}}, true}, {&APIError{err: hae, httpErr: hae, status: haeS, details: ErrDetails{ErrorInfo: httpErrInfo}}, true}, {&APIError{err: errors.New("standard error")}, false}, } for _, tc := range tests { got, apiB := FromError(tc.apierr.err) if tc.b != apiB { t.Errorf("FromError(%s): got %v, want %v", tc.apierr.err, apiB, tc.b) } if tc.b { if diff := cmp.Diff(got.details, tc.apierr.details, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("FromError(%s): got(-), want(+),: \n%s", tc.apierr.err, diff) } if diff := cmp.Diff(got.status, tc.apierr.status, cmp.Comparer(proto.Equal), cmp.AllowUnexported(status.Status{})); diff != "" { t.Errorf("FromError(%s): got(-), want(+),: \n%s", tc.apierr.err, diff) } if diff := cmp.Diff(got.err, tc.apierr.err, cmpopts.EquateErrors()); diff != "" { t.Errorf("FromError(%s): got(-), want(+),: \n%s", tc.apierr.err, diff) } } } if err, _ := FromError(nil); err != nil { t.Errorf("got %s, want nil", err) } if c, _ := FromError(context.DeadlineExceeded); c != nil { t.Errorf("got %s, want nil", c) } } func TestParseError(t *testing.T) { httpErrInfo := &errdetails.ErrorInfo{Reason: "just because", Domain: "tests"} any, err := anypb.New(httpErrInfo) if err != nil { t.Fatal(err) } e := &jsonerror.Error{Error: &jsonerror.Error_Status{Details: []*anypb.Any{any}}} data, err := protojson.Marshal(e) if err != nil { t.Fatal(err) } hae := &googleapi.Error{ Message: "just because", Body: string(data), } haeS := status.New(codes.Unknown, "just because") se := errors.New("standard error") tests := []struct { name string source error wantErr *APIError wantParsed bool }{ { name: "with http ErrorInfo details", source: hae, wantErr: &APIError{httpErr: hae, status: haeS, details: ErrDetails{ErrorInfo: httpErrInfo}}, wantParsed: true, }, { name: "standard error no details", source: se, wantErr: &APIError{err: se}, wantParsed: false, }, { name: "grpc status no details", source: haeS.Err(), wantErr: &APIError{httpErr: hae, status: haeS, details: ErrDetails{}}, wantParsed: true, }, } for _, tc := range tests { // ParseError with wrap = true is covered by TestFromError, above. got, gotParsed := ParseError(tc.source, false) if tc.wantParsed != gotParsed { t.Errorf("ParseError(%s, false): got %v, want %v", tc.wantErr, gotParsed, tc.wantParsed) } if got != nil { if got.Error() == "" { t.Errorf("got.Error(): got %q, want non-empty", got.Error()) } } if tc.wantParsed { if diff := cmp.Diff(got.details, tc.wantErr.details, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("got(-), want(+),: \n%s", diff) } if diff := cmp.Diff(got.status, tc.wantErr.status, cmp.Comparer(proto.Equal), cmp.AllowUnexported(status.Status{})); diff != "" { t.Errorf("got(-), want(+),: \n%s", diff) } if got.err != nil { t.Errorf("got %s, want nil", got.err) } } else { if got != nil { t.Errorf("got %s, want nil", got) } } } if err, _ := ParseError(nil, false); err != nil { t.Errorf("got %s, want nil", err) } if c, _ := ParseError(context.DeadlineExceeded, false); c != nil { t.Errorf("got %s, want nil", c) } } func golden(name, got string) (string, error) { g := filepath.Join("testdata", name+".golden") if *update { if err := ioutil.WriteFile(g, []byte(got), 0644); err != nil { return "", err } } want, err := ioutil.ReadFile(g) return string(want), err } func toAPIError(e *errdetails.ErrorInfo) *APIError { st, _ := status.New(codes.Unavailable, "test").WithDetails(e) return &APIError{ err: st.Err(), status: st, details: ErrDetails{ErrorInfo: e}, } } func TestHTTPCode(t *testing.T) { tests := []struct { name string apierr *APIError want int }{ { name: "basic http error", apierr: &APIError{httpErr: &googleapi.Error{Code: 418}}, want: 418, }, { name: "http error, with unknown status", apierr: &APIError{httpErr: &googleapi.Error{Code: 418}, status: status.New(codes.Unknown, "???")}, want: 418, }, { name: "gRPC error", apierr: &APIError{status: status.New(codes.DataLoss, "where did it go?")}, want: -1, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := tt.apierr.HTTPCode(); got != tt.want { t.Errorf("HTTPCode() = %v, want %v", got, tt.want) } }) } } gax-go-2.14.1/v2/apierror/internal/000077500000000000000000000000001473113767300167635ustar00rootroot00000000000000gax-go-2.14.1/v2/apierror/internal/proto/000077500000000000000000000000001473113767300201265ustar00rootroot00000000000000gax-go-2.14.1/v2/apierror/internal/proto/README.md000066400000000000000000000023121473113767300214030ustar00rootroot00000000000000# HTTP JSON Error Schema The `error.proto` represents the HTTP-JSON schema used by Google APIs to convey error payloads as described by https://cloud.google.com/apis/design/errors#http_mapping. This package is for internal parsing logic only and should not be used in any other context. ## Regeneration To regenerate the protobuf Go code you will need the following: * A local copy of [googleapis], the absolute path to which should be exported to the environment variable `GOOGLEAPIS` * The protobuf compiler [protoc] * The Go [protobuf plugin] * The [goimports] tool From this directory run the following command: ```sh protoc -I $GOOGLEAPIS -I. --go_out=. --go_opt=module=github.com/googleapis/gax-go/v2/apierror/internal/proto error.proto goimports -w . ``` Note: the `module` plugin option ensures the generated code is placed in this directory, and not in several nested directories defined by `go_package` option. [googleapis]: https://github.com/googleapis/googleapis [protoc]: https://github.com/protocolbuffers/protobuf#protocol-compiler-installation [protobuf plugin]: https://developers.google.com/protocol-buffers/docs/reference/go-generated [goimports]: https://pkg.go.dev/golang.org/x/tools/cmd/goimportsgax-go-2.14.1/v2/apierror/internal/proto/custom_error.pb.go000066400000000000000000000220441473113767300236020ustar00rootroot00000000000000// Copyright 2022 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 // // http://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. DO NOT EDIT. // versions: // protoc-gen-go v1.28.0 // protoc v3.17.3 // source: custom_error.proto package jsonerror import ( reflect "reflect" sync "sync" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // Error code for `CustomError`. type CustomError_CustomErrorCode int32 const ( // Default error. CustomError_CUSTOM_ERROR_CODE_UNSPECIFIED CustomError_CustomErrorCode = 0 // Too many foo. CustomError_TOO_MANY_FOO CustomError_CustomErrorCode = 1 // Not enough foo. CustomError_NOT_ENOUGH_FOO CustomError_CustomErrorCode = 2 // Catastrophic error. CustomError_UNIVERSE_WAS_DESTROYED CustomError_CustomErrorCode = 3 ) // Enum value maps for CustomError_CustomErrorCode. var ( CustomError_CustomErrorCode_name = map[int32]string{ 0: "CUSTOM_ERROR_CODE_UNSPECIFIED", 1: "TOO_MANY_FOO", 2: "NOT_ENOUGH_FOO", 3: "UNIVERSE_WAS_DESTROYED", } CustomError_CustomErrorCode_value = map[string]int32{ "CUSTOM_ERROR_CODE_UNSPECIFIED": 0, "TOO_MANY_FOO": 1, "NOT_ENOUGH_FOO": 2, "UNIVERSE_WAS_DESTROYED": 3, } ) func (x CustomError_CustomErrorCode) Enum() *CustomError_CustomErrorCode { p := new(CustomError_CustomErrorCode) *p = x return p } func (x CustomError_CustomErrorCode) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (CustomError_CustomErrorCode) Descriptor() protoreflect.EnumDescriptor { return file_custom_error_proto_enumTypes[0].Descriptor() } func (CustomError_CustomErrorCode) Type() protoreflect.EnumType { return &file_custom_error_proto_enumTypes[0] } func (x CustomError_CustomErrorCode) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use CustomError_CustomErrorCode.Descriptor instead. func (CustomError_CustomErrorCode) EnumDescriptor() ([]byte, []int) { return file_custom_error_proto_rawDescGZIP(), []int{0, 0} } // CustomError is an example of a custom error message which may be included // in an rpc status. It is not meant to reflect a standard error. type CustomError struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Error code specific to the custom API being invoked. Code CustomError_CustomErrorCode `protobuf:"varint,1,opt,name=code,proto3,enum=error.CustomError_CustomErrorCode" json:"code,omitempty"` // Name of the failed entity. Entity string `protobuf:"bytes,2,opt,name=entity,proto3" json:"entity,omitempty"` // Message that describes the error. ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` } func (x *CustomError) Reset() { *x = CustomError{} if protoimpl.UnsafeEnabled { mi := &file_custom_error_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CustomError) String() string { return protoimpl.X.MessageStringOf(x) } func (*CustomError) ProtoMessage() {} func (x *CustomError) ProtoReflect() protoreflect.Message { mi := &file_custom_error_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use CustomError.ProtoReflect.Descriptor instead. func (*CustomError) Descriptor() ([]byte, []int) { return file_custom_error_proto_rawDescGZIP(), []int{0} } func (x *CustomError) GetCode() CustomError_CustomErrorCode { if x != nil { return x.Code } return CustomError_CUSTOM_ERROR_CODE_UNSPECIFIED } func (x *CustomError) GetEntity() string { if x != nil { return x.Entity } return "" } func (x *CustomError) GetErrorMessage() string { if x != nil { return x.ErrorMessage } return "" } var File_custom_error_proto protoreflect.FileDescriptor var file_custom_error_proto_rawDesc = []byte{ 0x0a, 0x12, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xfa, 0x01, 0x0a, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x36, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x76, 0x0a, 0x0f, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x46, 0x4f, 0x4f, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x4e, 0x4f, 0x55, 0x47, 0x48, 0x5f, 0x46, 0x4f, 0x4f, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x4e, 0x49, 0x56, 0x45, 0x52, 0x53, 0x45, 0x5f, 0x57, 0x41, 0x53, 0x5f, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x45, 0x44, 0x10, 0x03, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x78, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x6a, 0x73, 0x6f, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_custom_error_proto_rawDescOnce sync.Once file_custom_error_proto_rawDescData = file_custom_error_proto_rawDesc ) func file_custom_error_proto_rawDescGZIP() []byte { file_custom_error_proto_rawDescOnce.Do(func() { file_custom_error_proto_rawDescData = protoimpl.X.CompressGZIP(file_custom_error_proto_rawDescData) }) return file_custom_error_proto_rawDescData } var file_custom_error_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_custom_error_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_custom_error_proto_goTypes = []interface{}{ (CustomError_CustomErrorCode)(0), // 0: error.CustomError.CustomErrorCode (*CustomError)(nil), // 1: error.CustomError } var file_custom_error_proto_depIdxs = []int32{ 0, // 0: error.CustomError.code:type_name -> error.CustomError.CustomErrorCode 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_custom_error_proto_init() } func file_custom_error_proto_init() { if File_custom_error_proto != nil { return } if !protoimpl.UnsafeEnabled { file_custom_error_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CustomError); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_custom_error_proto_rawDesc, NumEnums: 1, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_custom_error_proto_goTypes, DependencyIndexes: file_custom_error_proto_depIdxs, EnumInfos: file_custom_error_proto_enumTypes, MessageInfos: file_custom_error_proto_msgTypes, }.Build() File_custom_error_proto = out.File file_custom_error_proto_rawDesc = nil file_custom_error_proto_goTypes = nil file_custom_error_proto_depIdxs = nil } gax-go-2.14.1/v2/apierror/internal/proto/custom_error.proto000066400000000000000000000025331473113767300237410ustar00rootroot00000000000000// Copyright 2022 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 // // http://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. syntax = "proto3"; package error; option go_package = "github.com/googleapis/gax-go/v2/apierror/internal/proto;jsonerror"; // CustomError is an example of a custom error message which may be included // in an rpc status. It is not meant to reflect a standard error. message CustomError { // Error code for `CustomError`. enum CustomErrorCode { // Default error. CUSTOM_ERROR_CODE_UNSPECIFIED = 0; // Too many foo. TOO_MANY_FOO = 1; // Not enough foo. NOT_ENOUGH_FOO = 2; // Catastrophic error. UNIVERSE_WAS_DESTROYED = 3; } // Error code specific to the custom API being invoked. CustomErrorCode code = 1; // Name of the failed entity. string entity = 2; // Message that describes the error. string error_message = 3; } gax-go-2.14.1/v2/apierror/internal/proto/error.pb.go000066400000000000000000000241351473113767300222130ustar00rootroot00000000000000// Copyright 2021 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 // // http://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. DO NOT EDIT. // versions: // protoc-gen-go v1.28.0 // protoc v3.15.8 // source: apierror/internal/proto/error.proto package jsonerror import ( reflect "reflect" sync "sync" code "google.golang.org/genproto/googleapis/rpc/code" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" anypb "google.golang.org/protobuf/types/known/anypb" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // The error format v2 for Google JSON REST APIs. // Copied from https://cloud.google.com/apis/design/errors#http_mapping. // // NOTE: This schema is not used for other wire protocols. type Error struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The actual error payload. The nested message structure is for backward // compatibility with Google API client libraries. It also makes the error // more readable to developers. Error *Error_Status `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` } func (x *Error) Reset() { *x = Error{} if protoimpl.UnsafeEnabled { mi := &file_apierror_internal_proto_error_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Error) String() string { return protoimpl.X.MessageStringOf(x) } func (*Error) ProtoMessage() {} func (x *Error) ProtoReflect() protoreflect.Message { mi := &file_apierror_internal_proto_error_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Error.ProtoReflect.Descriptor instead. func (*Error) Descriptor() ([]byte, []int) { return file_apierror_internal_proto_error_proto_rawDescGZIP(), []int{0} } func (x *Error) GetError() *Error_Status { if x != nil { return x.Error } return nil } // This message has the same semantics as `google.rpc.Status`. It uses HTTP // status code instead of gRPC status code. It has an extra field `status` // for backward compatibility with Google API Client Libraries. type Error_Status struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The HTTP status code that corresponds to `google.rpc.Status.code`. Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // This corresponds to `google.rpc.Status.message`. Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // This is the enum version for `google.rpc.Status.code`. Status code.Code `protobuf:"varint,4,opt,name=status,proto3,enum=google.rpc.Code" json:"status,omitempty"` // This corresponds to `google.rpc.Status.details`. Details []*anypb.Any `protobuf:"bytes,5,rep,name=details,proto3" json:"details,omitempty"` } func (x *Error_Status) Reset() { *x = Error_Status{} if protoimpl.UnsafeEnabled { mi := &file_apierror_internal_proto_error_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Error_Status) String() string { return protoimpl.X.MessageStringOf(x) } func (*Error_Status) ProtoMessage() {} func (x *Error_Status) ProtoReflect() protoreflect.Message { mi := &file_apierror_internal_proto_error_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Error_Status.ProtoReflect.Descriptor instead. func (*Error_Status) Descriptor() ([]byte, []int) { return file_apierror_internal_proto_error_proto_rawDescGZIP(), []int{0, 0} } func (x *Error_Status) GetCode() int32 { if x != nil { return x.Code } return 0 } func (x *Error_Status) GetMessage() string { if x != nil { return x.Message } return "" } func (x *Error_Status) GetStatus() code.Code { if x != nil { return x.Status } return code.Code(0) } func (x *Error_Status) GetDetails() []*anypb.Any { if x != nil { return x.Details } return nil } var File_apierror_internal_proto_error_proto protoreflect.FileDescriptor var file_apierror_internal_proto_error_proto_rawDesc = []byte{ 0x0a, 0x23, 0x61, 0x70, 0x69, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc5, 0x01, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x90, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x78, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x6a, 0x73, 0x6f, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_apierror_internal_proto_error_proto_rawDescOnce sync.Once file_apierror_internal_proto_error_proto_rawDescData = file_apierror_internal_proto_error_proto_rawDesc ) func file_apierror_internal_proto_error_proto_rawDescGZIP() []byte { file_apierror_internal_proto_error_proto_rawDescOnce.Do(func() { file_apierror_internal_proto_error_proto_rawDescData = protoimpl.X.CompressGZIP(file_apierror_internal_proto_error_proto_rawDescData) }) return file_apierror_internal_proto_error_proto_rawDescData } var file_apierror_internal_proto_error_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_apierror_internal_proto_error_proto_goTypes = []interface{}{ (*Error)(nil), // 0: error.Error (*Error_Status)(nil), // 1: error.Error.Status (code.Code)(0), // 2: google.rpc.Code (*anypb.Any)(nil), // 3: google.protobuf.Any } var file_apierror_internal_proto_error_proto_depIdxs = []int32{ 1, // 0: error.Error.error:type_name -> error.Error.Status 2, // 1: error.Error.Status.status:type_name -> google.rpc.Code 3, // 2: error.Error.Status.details:type_name -> google.protobuf.Any 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name } func init() { file_apierror_internal_proto_error_proto_init() } func file_apierror_internal_proto_error_proto_init() { if File_apierror_internal_proto_error_proto != nil { return } if !protoimpl.UnsafeEnabled { file_apierror_internal_proto_error_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Error); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_apierror_internal_proto_error_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Error_Status); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_apierror_internal_proto_error_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_apierror_internal_proto_error_proto_goTypes, DependencyIndexes: file_apierror_internal_proto_error_proto_depIdxs, MessageInfos: file_apierror_internal_proto_error_proto_msgTypes, }.Build() File_apierror_internal_proto_error_proto = out.File file_apierror_internal_proto_error_proto_rawDesc = nil file_apierror_internal_proto_error_proto_goTypes = nil file_apierror_internal_proto_error_proto_depIdxs = nil } gax-go-2.14.1/v2/apierror/internal/proto/error.proto000066400000000000000000000034171473113767300223510ustar00rootroot00000000000000// Copyright 2021 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 // // http://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. syntax = "proto3"; package error; import "google/protobuf/any.proto"; import "google/rpc/code.proto"; option go_package = "github.com/googleapis/gax-go/v2/apierror/internal/proto;jsonerror"; // The error format v2 for Google JSON REST APIs. // Copied from https://cloud.google.com/apis/design/errors#http_mapping. // // NOTE: This schema is not used for other wire protocols. message Error { // This message has the same semantics as `google.rpc.Status`. It uses HTTP // status code instead of gRPC status code. It has an extra field `status` // for backward compatibility with Google API Client Libraries. message Status { // The HTTP status code that corresponds to `google.rpc.Status.code`. int32 code = 1; // This corresponds to `google.rpc.Status.message`. string message = 2; // This is the enum version for `google.rpc.Status.code`. google.rpc.Code status = 4; // This corresponds to `google.rpc.Status.details`. repeated google.protobuf.Any details = 5; } // The actual error payload. The nested message structure is for backward // compatibility with Google API client libraries. It also makes the error // more readable to developers. Status error = 1; } gax-go-2.14.1/v2/apierror/testdata/000077500000000000000000000000001473113767300167605ustar00rootroot00000000000000gax-go-2.14.1/v2/apierror/testdata/bad_request.golden000066400000000000000000000001431473113767300224460ustar00rootroot00000000000000rpc error: code = InvalidArgument desc = br error details: name = BadRequest field = Foo desc = Bargax-go-2.14.1/v2/apierror/testdata/debug_info.golden000066400000000000000000000001521473113767300222510ustar00rootroot00000000000000rpc error: code = InvalidArgument desc = br error details: name = DebugInfo detail = Stack stack = Foo Bargax-go-2.14.1/v2/apierror/testdata/empty.golden000066400000000000000000000000531473113767300213060ustar00rootroot00000000000000rpc error: code = InvalidArgument desc = brgax-go-2.14.1/v2/apierror/testdata/error_info.golden000066400000000000000000000001771473113767300223230ustar00rootroot00000000000000rpc error: code = Unauthenticated desc = ei error details: name = ErrorInfo reason = Foo domain = Bar metadata = map[type:test]gax-go-2.14.1/v2/apierror/testdata/help.golden000066400000000000000000000001331473113767300210770ustar00rootroot00000000000000rpc error: code = InvalidArgument desc = br error details: name = Help desc = Foo url = Bargax-go-2.14.1/v2/apierror/testdata/http_err.golden000066400000000000000000000001661473113767300220040ustar00rootroot00000000000000googleapi: Error 0: just because error details: name = ErrorInfo reason = just because domain = tests metadata = map[]gax-go-2.14.1/v2/apierror/testdata/localized_message.golden000066400000000000000000000001511473113767300236210ustar00rootroot00000000000000rpc error: code = InvalidArgument desc = br error details: name = LocalizedMessage locale = Foo msg = Bargax-go-2.14.1/v2/apierror/testdata/multiple_info.golden000066400000000000000000000005251473113767300230220ustar00rootroot00000000000000rpc error: code = Canceled desc = Request cancelled by client error details: name = BadRequest field = Foo desc = Bar error details: name = PreconditionFailure type = Foo subj = Bar desc = desc error details: name = QuotaFailure subj = Foo desc = Bar error details: name = RequestInfo id = Foo data = Bar error details: retry in 10.00000001sgax-go-2.14.1/v2/apierror/testdata/resource_info.golden000066400000000000000000000002261473113767300230140ustar00rootroot00000000000000rpc error: code = InvalidArgument desc = br error details: name = ResourceInfo type = Foo resourcename = Bar owner = Client desc = Directory not Foundgax-go-2.14.1/v2/apierror/testdata/unknown.golden000066400000000000000000000001421473113767300216460ustar00rootroot00000000000000rpc error: code = InvalidArgument desc = br error details: name = Unknown desc = unknown detail 1gax-go-2.14.1/v2/call_option.go000066400000000000000000000171551473113767300161670ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "errors" "math/rand" "time" "google.golang.org/api/googleapi" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // CallOption is an option used by Invoke to control behaviors of RPC calls. // CallOption works by modifying relevant fields of CallSettings. type CallOption interface { // Resolve applies the option by modifying cs. Resolve(cs *CallSettings) } // Retryer is used by Invoke to determine retry behavior. type Retryer interface { // Retry reports whether a request should be retried and how long to pause before retrying // if the previous attempt returned with err. Invoke never calls Retry with nil error. Retry(err error) (pause time.Duration, shouldRetry bool) } type retryerOption func() Retryer func (o retryerOption) Resolve(s *CallSettings) { s.Retry = o } // WithRetry sets CallSettings.Retry to fn. func WithRetry(fn func() Retryer) CallOption { return retryerOption(fn) } // OnErrorFunc returns a Retryer that retries if and only if the previous attempt // returns an error that satisfies shouldRetry. // // Pause times between retries are specified by bo. bo is only used for its // parameters; each Retryer has its own copy. func OnErrorFunc(bo Backoff, shouldRetry func(err error) bool) Retryer { return &errorRetryer{ shouldRetry: shouldRetry, backoff: bo, } } type errorRetryer struct { backoff Backoff shouldRetry func(err error) bool } func (r *errorRetryer) Retry(err error) (time.Duration, bool) { if r.shouldRetry(err) { return r.backoff.Pause(), true } return 0, false } // OnCodes returns a Retryer that retries if and only if // the previous attempt returns a GRPC error whose error code is stored in cc. // Pause times between retries are specified by bo. // // bo is only used for its parameters; each Retryer has its own copy. func OnCodes(cc []codes.Code, bo Backoff) Retryer { return &boRetryer{ backoff: bo, codes: append([]codes.Code(nil), cc...), } } type boRetryer struct { backoff Backoff codes []codes.Code } func (r *boRetryer) Retry(err error) (time.Duration, bool) { st, ok := status.FromError(err) if !ok { return 0, false } c := st.Code() for _, rc := range r.codes { if c == rc { return r.backoff.Pause(), true } } return 0, false } // OnHTTPCodes returns a Retryer that retries if and only if // the previous attempt returns a googleapi.Error whose status code is stored in // cc. Pause times between retries are specified by bo. // // bo is only used for its parameters; each Retryer has its own copy. func OnHTTPCodes(bo Backoff, cc ...int) Retryer { codes := make(map[int]bool, len(cc)) for _, c := range cc { codes[c] = true } return &httpRetryer{ backoff: bo, codes: codes, } } type httpRetryer struct { backoff Backoff codes map[int]bool } func (r *httpRetryer) Retry(err error) (time.Duration, bool) { var gerr *googleapi.Error if !errors.As(err, &gerr) { return 0, false } if r.codes[gerr.Code] { return r.backoff.Pause(), true } return 0, false } // Backoff implements exponential backoff. The wait time between retries is a // random value between 0 and the "retry period" - the time between retries. The // retry period starts at Initial and increases by the factor of Multiplier // every retry, but is capped at Max. // // Note: MaxNumRetries / RPCDeadline is specifically not provided. These should // be built on top of Backoff. type Backoff struct { // Initial is the initial value of the retry period, defaults to 1 second. Initial time.Duration // Max is the maximum value of the retry period, defaults to 30 seconds. Max time.Duration // Multiplier is the factor by which the retry period increases. // It should be greater than 1 and defaults to 2. Multiplier float64 // cur is the current retry period. cur time.Duration } // Pause returns the next time.Duration that the caller should use to backoff. func (bo *Backoff) Pause() time.Duration { if bo.Initial == 0 { bo.Initial = time.Second } if bo.cur == 0 { bo.cur = bo.Initial } if bo.Max == 0 { bo.Max = 30 * time.Second } if bo.Multiplier < 1 { bo.Multiplier = 2 } // Select a duration between 1ns and the current max. It might seem // counterintuitive to have so much jitter, but // https://www.awsarchitectureblog.com/2015/03/backoff.html argues that // that is the best strategy. d := time.Duration(1 + rand.Int63n(int64(bo.cur))) bo.cur = time.Duration(float64(bo.cur) * bo.Multiplier) if bo.cur > bo.Max { bo.cur = bo.Max } return d } type grpcOpt []grpc.CallOption func (o grpcOpt) Resolve(s *CallSettings) { s.GRPC = o } type pathOpt struct { p string } func (p pathOpt) Resolve(s *CallSettings) { s.Path = p.p } type timeoutOpt struct { t time.Duration } func (t timeoutOpt) Resolve(s *CallSettings) { s.timeout = t.t } // WithPath applies a Path override to the HTTP-based APICall. // // This is for internal use only. func WithPath(p string) CallOption { return &pathOpt{p: p} } // WithGRPCOptions allows passing gRPC call options during client creation. func WithGRPCOptions(opt ...grpc.CallOption) CallOption { return grpcOpt(append([]grpc.CallOption(nil), opt...)) } // WithTimeout is a convenience option for setting a context.WithTimeout on the // singular context.Context used for **all** APICall attempts. Calculated from // the start of the first APICall attempt. // If the context.Context provided to Invoke already has a Deadline set, that // will always be respected over the deadline calculated using this option. func WithTimeout(t time.Duration) CallOption { return &timeoutOpt{t: t} } // CallSettings allow fine-grained control over how calls are made. type CallSettings struct { // Retry returns a Retryer to be used to control retry logic of a method call. // If Retry is nil or the returned Retryer is nil, the call will not be retried. Retry func() Retryer // CallOptions to be forwarded to GRPC. GRPC []grpc.CallOption // Path is an HTTP override for an APICall. Path string // Timeout defines the amount of time that Invoke has to complete. // Unexported so it cannot be changed by the code in an APICall. timeout time.Duration } gax-go-2.14.1/v2/call_option_test.go000066400000000000000000000107111473113767300172150ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "context" "net/http" "testing" "time" "google.golang.org/api/googleapi" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) var _ Retryer = &boRetryer{} func TestBackofDefault(t *testing.T) { backoff := Backoff{} max := []time.Duration{1, 2, 4, 8, 16, 30, 30, 30, 30, 30} for i, m := range max { max[i] = m * time.Second } for i, w := range max { if d := backoff.Pause(); d > w { t.Errorf("Backoff duration should be at most %s, got %s", w, d) } else if i < len(max)-1 && backoff.cur != max[i+1] { t.Errorf("current envelope is %s, want %s", backoff.cur, max[i+1]) } } } func TestBackoffExponential(t *testing.T) { backoff := Backoff{Initial: 1, Max: 20, Multiplier: 2} want := []time.Duration{1, 2, 4, 8, 16, 20, 20, 20, 20, 20} for _, w := range want { if d := backoff.Pause(); d > w { t.Errorf("Backoff duration should be at most %s, got %s", w, d) } } } func TestOnCodes(t *testing.T) { // Lint errors grpc.Errorf in 1.6. It mistakenly expects the first arg to Errorf to be a string. errf := status.Errorf apiErr := errf(codes.Unavailable, "") tests := []struct { c []codes.Code retry bool }{ {nil, false}, {[]codes.Code{codes.DeadlineExceeded}, false}, {[]codes.Code{codes.DeadlineExceeded, codes.Unavailable}, true}, {[]codes.Code{codes.Unavailable}, true}, } for _, tst := range tests { b := OnCodes(tst.c, Backoff{}) if _, retry := b.Retry(apiErr); retry != tst.retry { t.Errorf("retriable codes: %v, error: %s, retry: %t, want %t", tst.c, apiErr, retry, tst.retry) } } } func TestOnErrorFunc(t *testing.T) { // Use errors.Is if on go 1.13 or higher. is := func(err, target error) bool { return err == target } tests := []struct { e error shouldRetry func(err error) bool retry bool }{ {context.DeadlineExceeded, func(err error) bool { return false }, false}, {context.DeadlineExceeded, func(err error) bool { return is(err, context.DeadlineExceeded) }, true}, } for _, tst := range tests { b := OnErrorFunc(Backoff{}, tst.shouldRetry) if _, retry := b.Retry(tst.e); retry != tst.retry { t.Errorf("retriable func: error: %s, retry: %t, want %t", tst.e, retry, tst.retry) } } } func TestOnHTTPCodes(t *testing.T) { apiErr := &googleapi.Error{Code: http.StatusBadGateway} tests := []struct { c []int retry bool }{ {nil, false}, {[]int{http.StatusConflict}, false}, {[]int{http.StatusConflict, http.StatusBadGateway}, true}, {[]int{http.StatusBadGateway}, true}, } for _, tst := range tests { b := OnHTTPCodes(Backoff{}, tst.c...) if _, retry := b.Retry(apiErr); retry != tst.retry { t.Errorf("retriable codes: %v, error: %s, retry: %t, want %t", tst.c, apiErr, retry, tst.retry) } } } func TestWithTimeout(t *testing.T) { settings := CallSettings{} to := 10 * time.Second WithTimeout(to).Resolve(&settings) if settings.timeout != to { t.Errorf("got %v, want %v", settings.timeout, to) } } gax-go-2.14.1/v2/callctx/000077500000000000000000000000001473113767300147565ustar00rootroot00000000000000gax-go-2.14.1/v2/callctx/callctx.go000066400000000000000000000076141473113767300167470ustar00rootroot00000000000000// Copyright 2023, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package callctx provides helpers for storing and retrieving values out of // [context.Context]. These values are used by our client libraries in various // ways across the stack. package callctx import ( "context" "fmt" ) const ( // XGoogFieldMaskHeader is the canonical header key for the [System Parameter] // that specifies the response read mask. The value(s) for this header // must adhere to format described in [fieldmaskpb]. // // [System Parameter]: https://cloud.google.com/apis/docs/system-parameters // [fieldmaskpb]: https://google.golang.org/protobuf/types/known/fieldmaskpb XGoogFieldMaskHeader = "x-goog-fieldmask" headerKey = contextKey("header") ) // contextKey is a private type used to store/retrieve context values. type contextKey string // HeadersFromContext retrieves headers set from [SetHeaders]. These headers // can then be cast to http.Header or metadata.MD to send along on requests. func HeadersFromContext(ctx context.Context) map[string][]string { m, ok := ctx.Value(headerKey).(map[string][]string) if !ok { return nil } return m } // SetHeaders stores key value pairs in the returned context that can later // be retrieved by [HeadersFromContext]. Values stored in this manner will // automatically be retrieved by client libraries and sent as outgoing headers // on all requests. keyvals should have a corresponding value for every key // provided. If there is an odd number of keyvals this method will panic. func SetHeaders(ctx context.Context, keyvals ...string) context.Context { if len(keyvals)%2 != 0 { panic(fmt.Sprintf("callctx: an even number of key value pairs must be provided, got %d", len(keyvals))) } h, ok := ctx.Value(headerKey).(map[string][]string) if !ok { h = make(map[string][]string) } else { h = cloneHeaders(h) } for i := 0; i < len(keyvals); i = i + 2 { h[keyvals[i]] = append(h[keyvals[i]], keyvals[i+1]) } return context.WithValue(ctx, headerKey, h) } // cloneHeaders makes a new key-value map while reusing the value slices. // As such, new values should be appended to the value slice, and modifying // indexed values is not thread safe. // // TODO: Replace this with maps.Clone when Go 1.21 is the minimum version. func cloneHeaders(h map[string][]string) map[string][]string { c := make(map[string][]string, len(h)) for k, v := range h { vc := make([]string, len(v)) copy(vc, v) c[k] = vc } return c } gax-go-2.14.1/v2/callctx/callctx_example_test.go000066400000000000000000000052521473113767300215150ustar00rootroot00000000000000// Copyright 2023, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package callctx_test import ( "context" "fmt" "github.com/googleapis/gax-go/v2/callctx" "google.golang.org/genproto/googleapis/api/metric" "google.golang.org/protobuf/types/known/fieldmaskpb" ) func ExampleSetHeaders() { ctx := context.Background() ctx = callctx.SetHeaders(ctx, "key", "value") // Send the returned context to the request you are making. Later on these // values will be retrieved and set on outgoing requests. headers := callctx.HeadersFromContext(ctx) fmt.Println(headers["key"][0]) // Output: value } func ExampleXGoogFieldMaskHeader() { ctx := context.Background() ctx = callctx.SetHeaders(ctx, callctx.XGoogFieldMaskHeader, "field_one,field.two") // Send the returned context to the request you are making. } func ExampleXGoogFieldMaskHeader_fieldmaskpb() { // Build a mask using the expected response protobuf message. mask, err := fieldmaskpb.New(&metric.MetricDescriptor{}, "display_name", "metadata.launch_stage") if err != nil { // handle error } ctx := context.Background() ctx = callctx.SetHeaders(ctx, callctx.XGoogFieldMaskHeader, mask.String()) // Send the returned context to the request you are making. } gax-go-2.14.1/v2/callctx/callctx_test.go000066400000000000000000000073261473113767300200060ustar00rootroot00000000000000// Copyright 2023, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package callctx import ( "context" "sync" "testing" "github.com/google/go-cmp/cmp" ) func TestAll(t *testing.T) { testCases := []struct { name string pairs []string want map[string][]string }{ { name: "standard", pairs: []string{"key", "value"}, want: map[string][]string{"key": {"value"}}, }, { name: "multiple values", pairs: []string{"key", "value", "key2", "value2"}, want: map[string][]string{"key": {"value"}, "key2": {"value2"}}, }, { name: "multiple values with same key", pairs: []string{"key", "value", "key", "value2"}, want: map[string][]string{"key": {"value", "value2"}}, }, } for _, tc := range testCases { ctx := context.Background() ctx = SetHeaders(ctx, tc.pairs...) got := HeadersFromContext(ctx) if diff := cmp.Diff(tc.want, got); diff != "" { t.Errorf("HeadersFromContext() mismatch (-want +got):\n%s", diff) } } } func TestSetHeaders_panics(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("expected panic with odd key value pairs") } }() ctx := context.Background() SetHeaders(ctx, "1", "2", "3") } func TestSetHeaders_reuse(t *testing.T) { c := SetHeaders(context.Background(), "key", "value1") v1 := HeadersFromContext(c) c = SetHeaders(c, "key", "value2") v2 := HeadersFromContext(c) if cmp.Diff(v2, v1) == "" { t.Errorf("Second header set did not differ from first header set as expected") } } func TestSetHeaders_race(t *testing.T) { key := "key" value := "value" want := map[string][]string{ key: {value, value}, } // Init the ctx so a value already exists to be "shared". cctx := SetHeaders(context.Background(), key, value) // Reusing the same cctx and adding to the same header key // should *not* produce a race condition when run with -race. var wg sync.WaitGroup for i := 0; i < 3; i++ { wg.Add(1) go func(ctx context.Context) { defer wg.Done() c := SetHeaders(ctx, key, value) h := HeadersFromContext(c) // Additionally, if there was a race condition, // we may see that one instance of these headers // contains extra values. if diff := cmp.Diff(h, want); diff != "" { t.Errorf("got(-),want(+):\n%s", diff) } }(cctx) } wg.Wait() } gax-go-2.14.1/v2/content_type.go000066400000000000000000000100541473113767300163660ustar00rootroot00000000000000// Copyright 2022, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "io" "io/ioutil" "net/http" ) const sniffBuffSize = 512 func newContentSniffer(r io.Reader) *contentSniffer { return &contentSniffer{r: r} } // contentSniffer wraps a Reader, and reports the content type determined by sniffing up to 512 bytes from the Reader. type contentSniffer struct { r io.Reader start []byte // buffer for the sniffed bytes. err error // set to any error encountered while reading bytes to be sniffed. ctype string // set on first sniff. sniffed bool // set to true on first sniff. } func (cs *contentSniffer) Read(p []byte) (n int, err error) { // Ensure that the content type is sniffed before any data is consumed from Reader. _, _ = cs.ContentType() if len(cs.start) > 0 { n := copy(p, cs.start) cs.start = cs.start[n:] return n, nil } // We may have read some bytes into start while sniffing, even if the read ended in an error. // We should first return those bytes, then the error. if cs.err != nil { return 0, cs.err } // Now we have handled all bytes that were buffered while sniffing. Now just delegate to the underlying reader. return cs.r.Read(p) } // ContentType returns the sniffed content type, and whether the content type was successfully sniffed. func (cs *contentSniffer) ContentType() (string, bool) { if cs.sniffed { return cs.ctype, cs.ctype != "" } cs.sniffed = true // If ReadAll hits EOF, it returns err==nil. cs.start, cs.err = ioutil.ReadAll(io.LimitReader(cs.r, sniffBuffSize)) // Don't try to detect the content type based on possibly incomplete data. if cs.err != nil { return "", false } cs.ctype = http.DetectContentType(cs.start) return cs.ctype, true } // DetermineContentType determines the content type of the supplied reader. // The content of media will be sniffed to determine the content type. // After calling DetectContentType the caller must not perform further reads on // media, but rather read from the Reader that is returned. func DetermineContentType(media io.Reader) (io.Reader, string) { // For backwards compatibility, allow clients to set content // type by providing a ContentTyper for media. // Note: This is an anonymous interface definition copied from googleapi.ContentTyper. if typer, ok := media.(interface { ContentType() string }); ok { return media, typer.ContentType() } sniffer := newContentSniffer(media) if ctype, ok := sniffer.ContentType(); ok { return sniffer, ctype } // If content type could not be sniffed, reads from sniffer will eventually fail with an error. return sniffer, "" } gax-go-2.14.1/v2/content_type_test.go000066400000000000000000000122411473113767300174250ustar00rootroot00000000000000// Copyright 2022, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "bytes" "io" "io/ioutil" "reflect" "testing" ) // errReader reads out of a buffer until it is empty, then returns the specified error. type errReader struct { buf []byte err error } func (er *errReader) Read(p []byte) (int, error) { if len(er.buf) == 0 { if er.err == nil { return 0, io.EOF } return 0, er.err } n := copy(p, er.buf) er.buf = er.buf[n:] return n, nil } func TestContentSniffing(t *testing.T) { type testCase struct { data []byte // the data to read from the Reader finalErr error // error to return after data has been read wantContentType string wantContentTypeResult bool } for _, tc := range []testCase{ { data: []byte{0, 0, 0, 0}, finalErr: nil, wantContentType: "application/octet-stream", wantContentTypeResult: true, }, { data: []byte(""), finalErr: nil, wantContentType: "text/plain; charset=utf-8", wantContentTypeResult: true, }, { data: []byte(""), finalErr: io.ErrUnexpectedEOF, wantContentType: "text/plain; charset=utf-8", wantContentTypeResult: false, }, { data: []byte("abc"), finalErr: nil, wantContentType: "text/plain; charset=utf-8", wantContentTypeResult: true, }, { data: []byte("abc"), finalErr: io.ErrUnexpectedEOF, wantContentType: "text/plain; charset=utf-8", wantContentTypeResult: false, }, // The following examples contain more bytes than are buffered for sniffing. { data: bytes.Repeat([]byte("a"), 513), finalErr: nil, wantContentType: "text/plain; charset=utf-8", wantContentTypeResult: true, }, { data: bytes.Repeat([]byte("a"), 513), finalErr: io.ErrUnexpectedEOF, wantContentType: "text/plain; charset=utf-8", wantContentTypeResult: true, // true because error is after first 512 bytes. }, } { er := &errReader{buf: tc.data, err: tc.finalErr} sct := newContentSniffer(er) // Even if was an error during the first 512 bytes, we should still be able to read those bytes. buf, err := ioutil.ReadAll(sct) if !reflect.DeepEqual(buf, tc.data) { t.Fatalf("Failed reading buffer: got: %q; want:%q", buf, tc.data) } if err != tc.finalErr { t.Fatalf("Reading buffer error: got: %v; want: %v", err, tc.finalErr) } ct, ok := sct.ContentType() if ok != tc.wantContentTypeResult { t.Fatalf("Content type result got: %v; want: %v", ok, tc.wantContentTypeResult) } if ok && ct != tc.wantContentType { t.Fatalf("Content type got: %q; want: %q", ct, tc.wantContentType) } } } type staticContentTyper struct { io.Reader } func (sct staticContentTyper) ContentType() string { return "static content type" } func TestDetermineContentType(t *testing.T) { data := []byte("abc") rdr := func() io.Reader { return bytes.NewBuffer(data) } type testCase struct { r io.Reader wantContentType string } for _, tc := range []testCase{ { r: rdr(), wantContentType: "text/plain; charset=utf-8", }, { r: staticContentTyper{rdr()}, wantContentType: "static content type", }, } { r, ctype := DetermineContentType(tc.r) got, err := ioutil.ReadAll(r) if err != nil { t.Fatalf("Failed reading buffer: %v", err) } if !reflect.DeepEqual(got, data) { t.Fatalf("Failed reading buffer: got: %q; want:%q", got, data) } if ctype != tc.wantContentType { t.Fatalf("Content type got: %q; want: %q", ctype, tc.wantContentType) } } } gax-go-2.14.1/v2/example_test.go000066400000000000000000000216631473113767300163550ustar00rootroot00000000000000// Copyright 2019, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax_test import ( "context" "io" "net/http" "time" gax "github.com/googleapis/gax-go/v2" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/structpb" ) // Some result that the client might return. type fakeResponse struct{} // Some client that can perform RPCs. type fakeClient struct{} // PerformSomeRPC is a fake RPC that a client might perform. func (c *fakeClient) PerformSomeRPC(ctx context.Context) (*fakeResponse, error) { // An actual client would return something meaningful here. return nil, nil } func ExampleOnErrorFunc() { ctx := context.Background() c := &fakeClient{} shouldRetryUnavailableUnKnown := func(err error) bool { st, ok := status.FromError(err) if !ok { return false } return st.Code() == codes.Unavailable || st.Code() == codes.Unknown } retryer := gax.OnErrorFunc(gax.Backoff{ Initial: time.Second, Max: 32 * time.Second, Multiplier: 2, }, shouldRetryUnavailableUnKnown) performSomeRPCWithRetry := func(ctx context.Context) (*fakeResponse, error) { for { resp, err := c.PerformSomeRPC(ctx) if err != nil { if delay, shouldRetry := retryer.Retry(err); shouldRetry { if err := gax.Sleep(ctx, delay); err != nil { return nil, err } continue } return nil, err } return resp, err } } // It's recommended to set deadlines on RPCs and around retrying. This is // also usually preferred over setting some fixed number of retries: one // advantage this has is that backoff settings can be changed independently // of the deadline, whereas with a fixed number of retries the deadline // would be a constantly-shifting goalpost. ctxWithTimeout, cancel := context.WithDeadline(ctx, time.Now().Add(5*time.Minute)) defer cancel() resp, err := performSomeRPCWithRetry(ctxWithTimeout) if err != nil { // TODO: handle err } _ = resp // TODO: use resp if err is nil } func ExampleOnCodes() { ctx := context.Background() c := &fakeClient{} // UNKNOWN and UNAVAILABLE are typically safe to retry for idempotent RPCs. retryer := gax.OnCodes([]codes.Code{codes.Unknown, codes.Unavailable}, gax.Backoff{ Initial: time.Second, Max: 32 * time.Second, Multiplier: 2, }) performSomeRPCWithRetry := func(ctx context.Context) (*fakeResponse, error) { for { resp, err := c.PerformSomeRPC(ctx) if err != nil { if delay, shouldRetry := retryer.Retry(err); shouldRetry { if err := gax.Sleep(ctx, delay); err != nil { return nil, err } continue } return nil, err } return resp, err } } // It's recommended to set deadlines on RPCs and around retrying. This is // also usually preferred over setting some fixed number of retries: one // advantage this has is that backoff settings can be changed independently // of the deadline, whereas with a fixed number of retries the deadline // would be a constantly-shifting goalpost. ctxWithTimeout, cancel := context.WithDeadline(ctx, time.Now().Add(5*time.Minute)) defer cancel() resp, err := performSomeRPCWithRetry(ctxWithTimeout) if err != nil { // TODO: handle err } _ = resp // TODO: use resp if err is nil } func ExampleOnHTTPCodes() { ctx := context.Background() c := &fakeClient{} retryer := gax.OnHTTPCodes(gax.Backoff{ Initial: time.Second, Max: 32 * time.Second, Multiplier: 2, }, http.StatusBadGateway, http.StatusServiceUnavailable) performSomeRPCWithRetry := func(ctx context.Context) (*fakeResponse, error) { for { resp, err := c.PerformSomeRPC(ctx) if err != nil { if delay, shouldRetry := retryer.Retry(err); shouldRetry { if err := gax.Sleep(ctx, delay); err != nil { return nil, err } continue } return nil, err } return resp, err } } // It's recommended to set deadlines on RPCs and around retrying. This is // also usually preferred over setting some fixed number of retries: one // advantage this has is that backoff settings can be changed independently // of the deadline, whereas with a fixed number of retries the deadline // would be a constantly-shifting goalpost. ctxWithTimeout, cancel := context.WithDeadline(ctx, time.Now().Add(5*time.Minute)) defer cancel() resp, err := performSomeRPCWithRetry(ctxWithTimeout) if err != nil { // TODO: handle err } _ = resp // TODO: use resp if err is nil } func ExampleBackoff() { ctx := context.Background() bo := gax.Backoff{ Initial: time.Second, Max: time.Minute, // Maximum amount of time between retries. Multiplier: 2, } performHTTPCallWithRetry := func(ctx context.Context, doHTTPCall func(ctx context.Context) (*http.Response, error)) (*http.Response, error) { for { resp, err := doHTTPCall(ctx) if err != nil { // Retry 503 UNAVAILABLE. if resp.StatusCode == http.StatusServiceUnavailable { if err := gax.Sleep(ctx, bo.Pause()); err != nil { return nil, err } continue } return nil, err } return resp, err } } // It's recommended to set deadlines on HTTP calls and around retrying. This // is also usually preferred over setting some fixed number of retries: one // advantage this has is that backoff settings can be changed independently // of the deadline, whereas with a fixed number of retries the deadline // would be a constantly-shifting goalpost. ctxWithTimeout, cancel := context.WithDeadline(ctx, time.Now().Add(5*time.Minute)) defer cancel() resp, err := performHTTPCallWithRetry(ctxWithTimeout, func(ctx context.Context) (*http.Response, error) { req, err := http.NewRequest("some-method", "example.com", nil) if err != nil { return nil, err } req = req.WithContext(ctx) return http.DefaultClient.Do(req) }) if err != nil { // TODO: handle err } _ = resp // TODO: use resp if err is nil } func ExampleProtoJSONStream() { var someHTTPCall func() (http.Response, error) res, err := someHTTPCall() if err != nil { // TODO: handle err } // The type of message expected in the stream. var typ protoreflect.MessageType = (&structpb.Struct{}).ProtoReflect().Type() stream := gax.NewProtoJSONStreamReader(res.Body, typ) defer stream.Close() for { m, err := stream.Recv() if err != nil { break } // TODO: use resp _ = m.(*structpb.Struct) } if err != io.EOF { // TODO: handle err } } func ExampleInvoke_grpc() { ctx := context.Background() c := &fakeClient{} opt := gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{codes.Unknown, codes.Unavailable}, gax.Backoff{ Initial: time.Second, Max: 32 * time.Second, Multiplier: 2, }) }) var resp *fakeResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = c.PerformSomeRPC(ctx) return err }, opt) if err != nil { // TODO: handle err } _ = resp // TODO: use resp if err is nil } func ExampleInvoke_http() { ctx := context.Background() c := &fakeClient{} opt := gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: time.Second, Max: 32 * time.Second, Multiplier: 2, }, http.StatusBadGateway, http.StatusServiceUnavailable) }) var resp *fakeResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = c.PerformSomeRPC(ctx) return err }, opt) if err != nil { // TODO: handle err } _ = resp // TODO: use resp if err is nil } gax-go-2.14.1/v2/gax.go000066400000000000000000000040501473113767300144310ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package gax contains a set of modules which aid the development of APIs // for clients and servers based on gRPC and Google API conventions. // // Application code will rarely need to use this library directly. // However, code generated automatically from API definition files can use it // to simplify code generation and to provide more convenient and idiomatic API surfaces. package gax import "github.com/googleapis/gax-go/v2/internal" // Version specifies the gax-go version being used. const Version = internal.Version gax-go-2.14.1/v2/go.mod000066400000000000000000000007371473113767300144410ustar00rootroot00000000000000module github.com/googleapis/gax-go/v2 go 1.21 require ( github.com/google/go-cmp v0.6.0 google.golang.org/api v0.211.0 google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.2 ) require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect ) gax-go-2.14.1/v2/go.sum000066400000000000000000000031551473113767300144630ustar00rootroot00000000000000github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= google.golang.org/api v0.211.0 h1:IUpLjq09jxBSV1lACO33CGY3jsRcbctfGzhj+ZSE/Bg= google.golang.org/api v0.211.0/go.mod h1:XOloB4MXFH4UTlQSGuNUxw0UT74qdENK8d6JNsXKLi0= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gax-go-2.14.1/v2/header.go000066400000000000000000000153561473113767300151150ustar00rootroot00000000000000// Copyright 2018, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "bytes" "context" "fmt" "net/http" "runtime" "strings" "unicode" "github.com/googleapis/gax-go/v2/callctx" "google.golang.org/grpc/metadata" ) var ( // GoVersion is a header-safe representation of the current runtime // environment's Go version. This is for GAX consumers that need to // report the Go runtime version in API calls. GoVersion string // version is a package internal global variable for testing purposes. version = runtime.Version ) // versionUnknown is only used when the runtime version cannot be determined. const versionUnknown = "UNKNOWN" func init() { GoVersion = goVersion() } // goVersion returns a Go runtime version derived from the runtime environment // that is modified to be suitable for reporting in a header, meaning it has no // whitespace. If it is unable to determine the Go runtime version, it returns // versionUnknown. func goVersion() string { const develPrefix = "devel +" s := version() if strings.HasPrefix(s, develPrefix) { s = s[len(develPrefix):] if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 { s = s[:p] } return s } else if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 { s = s[:p] } notSemverRune := func(r rune) bool { return !strings.ContainsRune("0123456789.", r) } if strings.HasPrefix(s, "go1") { s = s[2:] var prerelease string if p := strings.IndexFunc(s, notSemverRune); p >= 0 { s, prerelease = s[:p], s[p:] } if strings.HasSuffix(s, ".") { s += "0" } else if strings.Count(s, ".") < 2 { s += ".0" } if prerelease != "" { // Some release candidates already have a dash in them. if !strings.HasPrefix(prerelease, "-") { prerelease = "-" + prerelease } s += prerelease } return s } return "UNKNOWN" } // XGoogHeader is for use by the Google Cloud Libraries only. See package // [github.com/googleapis/gax-go/v2/callctx] for help setting/retrieving // request/response headers. // // XGoogHeader formats key-value pairs. // The resulting string is suitable for x-goog-api-client header. func XGoogHeader(keyval ...string) string { if len(keyval) == 0 { return "" } if len(keyval)%2 != 0 { panic("gax.Header: odd argument count") } var buf bytes.Buffer for i := 0; i < len(keyval); i += 2 { buf.WriteByte(' ') buf.WriteString(keyval[i]) buf.WriteByte('/') buf.WriteString(keyval[i+1]) } return buf.String()[1:] } // InsertMetadataIntoOutgoingContext is for use by the Google Cloud Libraries // only. See package [github.com/googleapis/gax-go/v2/callctx] for help // setting/retrieving request/response headers. // // InsertMetadataIntoOutgoingContext returns a new context that merges the // provided keyvals metadata pairs with any existing metadata/headers in the // provided context. keyvals should have a corresponding value for every key // provided. If there is an odd number of keyvals this method will panic. // Existing values for keys will not be overwritten, instead provided values // will be appended to the list of existing values. func InsertMetadataIntoOutgoingContext(ctx context.Context, keyvals ...string) context.Context { return metadata.NewOutgoingContext(ctx, insertMetadata(ctx, keyvals...)) } // BuildHeaders is for use by the Google Cloud Libraries only. See package // [github.com/googleapis/gax-go/v2/callctx] for help setting/retrieving // request/response headers. // // BuildHeaders returns a new http.Header that merges the provided // keyvals header pairs with any existing metadata/headers in the provided // context. keyvals should have a corresponding value for every key provided. // If there is an odd number of keyvals this method will panic. // Existing values for keys will not be overwritten, instead provided values // will be appended to the list of existing values. func BuildHeaders(ctx context.Context, keyvals ...string) http.Header { return http.Header(insertMetadata(ctx, keyvals...)) } func insertMetadata(ctx context.Context, keyvals ...string) metadata.MD { if len(keyvals)%2 != 0 { panic(fmt.Sprintf("gax: an even number of key value pairs must be provided, got %d", len(keyvals))) } out, ok := metadata.FromOutgoingContext(ctx) if !ok { out = metadata.MD(make(map[string][]string)) } headers := callctx.HeadersFromContext(ctx) // x-goog-api-client is a special case that we want to make sure gets merged // into a single header. const xGoogHeader = "x-goog-api-client" var mergedXgoogHeader strings.Builder for k, vals := range headers { if k == xGoogHeader { // Merge all values for the x-goog-api-client header set on the ctx. for _, v := range vals { mergedXgoogHeader.WriteString(v) mergedXgoogHeader.WriteRune(' ') } continue } out[k] = append(out[k], vals...) } for i := 0; i < len(keyvals); i = i + 2 { out[keyvals[i]] = append(out[keyvals[i]], keyvals[i+1]) if keyvals[i] == xGoogHeader { // Merge the x-goog-api-client header values set on the ctx with any // values passed in for it from the client. mergedXgoogHeader.WriteString(keyvals[i+1]) mergedXgoogHeader.WriteRune(' ') } } // Add the x goog header back in, replacing the separate values that were set. if mergedXgoogHeader.Len() > 0 { out[xGoogHeader] = []string{mergedXgoogHeader.String()[:mergedXgoogHeader.Len()-1]} } return out } gax-go-2.14.1/v2/header_test.go000066400000000000000000000125661473113767300161540ustar00rootroot00000000000000// Copyright 2018, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "context" "net/http" "testing" "github.com/google/go-cmp/cmp" "github.com/googleapis/gax-go/v2/callctx" "google.golang.org/grpc/metadata" ) func TestXGoogHeader(t *testing.T) { for _, tst := range []struct { kv []string want string }{ {nil, ""}, {[]string{"abc", "def"}, "abc/def"}, {[]string{"abc", "def", "xyz", "123", "foo", ""}, "abc/def xyz/123 foo/"}, } { got := XGoogHeader(tst.kv...) if got != tst.want { t.Errorf("Header(%q) = %q, want %q", tst.kv, got, tst.want) } } } func TestGoVersion(t *testing.T) { testVersion := func(v string) func() string { return func() string { return v } } for _, tst := range []struct { v func() string want string }{ { testVersion("go1.19"), "1.19.0", }, { testVersion("go1.21-20230317-RC01"), "1.21.0-20230317-RC01", }, { testVersion("devel +abc1234"), "abc1234", }, { testVersion("this should be unknown"), versionUnknown, }, { testVersion("go1.21-20230101-RC01 cl/1234567 +abc1234"), "1.21.0-20230101-RC01", }, } { version = tst.v got := goVersion() if diff := cmp.Diff(got, tst.want); diff != "" { t.Errorf("got(-),want(+):\n%s", diff) } } } func TestInsertMetadataIntoOutgoingContext(t *testing.T) { for _, tst := range []struct { // User-provided metadata set in context userMd metadata.MD // User-provided headers set in context userHeaders []string // Client-provided headers passed to func clientHeaders []string want metadata.MD }{ { userMd: metadata.Pairs("key_1", "val_1", "key_2", "val_21"), want: metadata.Pairs("key_1", "val_1", "key_2", "val_21"), }, { userHeaders: []string{"key_2", "val_22"}, want: metadata.Pairs("key_2", "val_22"), }, { clientHeaders: []string{"key_2", "val_23", "key_2", "val_24"}, want: metadata.Pairs("key_2", "val_23", "key_2", "val_24"), }, { userMd: metadata.Pairs("key_1", "val_1", "key_2", "val_21"), userHeaders: []string{"key_2", "val_22"}, clientHeaders: []string{"key_2", "val_23", "key_2", "val_24"}, want: metadata.Pairs("key_1", "val_1", "key_2", "val_21", "key_2", "val_22", "key_2", "val_23", "key_2", "val_24"), }, { clientHeaders: []string{"x-goog-api-client", "val_23 val_22", "key_2", "val_24", "x-goog-api-client", "val_1"}, want: metadata.Pairs("key_2", "val_24", "x-goog-api-client", "val_23 val_22 val_1"), }, { userHeaders: []string{"key_2", "val_22", "x-goog-api-client", "val_1 val_2"}, clientHeaders: []string{"x-goog-api-client", "val_3 val_4", "key_2", "val_24", "x-goog-api-client", "val_11 val_22"}, want: metadata.Pairs("key_2", "val_22", "key_2", "val_24", "x-goog-api-client", "val_1 val_2 val_3 val_4 val_11 val_22"), }, } { ctx := context.Background() if tst.userMd != nil { ctx = metadata.NewOutgoingContext(ctx, tst.userMd) } ctx = callctx.SetHeaders(ctx, tst.userHeaders...) ctx = InsertMetadataIntoOutgoingContext(ctx, tst.clientHeaders...) got, _ := metadata.FromOutgoingContext(ctx) if diff := cmp.Diff(tst.want, got); diff != "" { t.Errorf("InsertMetadata(ctx, %q) mismatch (-want +got):\n%s", tst.clientHeaders, diff) } } } func TestBuildHeaders(t *testing.T) { // User-provided metadata set in context existingMd := metadata.Pairs("key_1", "val_1", "key_2", "val_21") ctx := metadata.NewOutgoingContext(context.Background(), existingMd) // User-provided headers set in context ctx = callctx.SetHeaders(ctx, "key_2", "val_22") // Client-provided headers keyvals := []string{"key_2", "val_23", "key_2", "val_24"} got := BuildHeaders(ctx, keyvals...) want := http.Header{"key_1": []string{"val_1"}, "key_2": []string{"val_21", "val_22", "val_23", "val_24"}} if diff := cmp.Diff(want, got); diff != "" { t.Errorf("InsertMetadata(ctx, %q) mismatch (-want +got):\n%s", keyvals, diff) } } gax-go-2.14.1/v2/internal/000077500000000000000000000000001473113767300151405ustar00rootroot00000000000000gax-go-2.14.1/v2/internal/version.go000066400000000000000000000031711473113767300171560ustar00rootroot00000000000000// Copyright 2022, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package internal // Version is the current tagged release of the library. const Version = "2.14.1" gax-go-2.14.1/v2/internallog/000077500000000000000000000000001473113767300156425ustar00rootroot00000000000000gax-go-2.14.1/v2/internallog/grpclog/000077500000000000000000000000001473113767300172775ustar00rootroot00000000000000gax-go-2.14.1/v2/internallog/grpclog/grpclog.go000066400000000000000000000061111473113767300212620ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package grpclog in intended for internal use by generated clients only. package grpclog import ( "context" "encoding/json" "log/slog" "strings" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) // ProtoMessageRequest returns a lazily evaluated [slog.LogValuer] for // the provided message. The context is used to extract outgoing headers. func ProtoMessageRequest(ctx context.Context, msg proto.Message) slog.LogValuer { return &protoMessage{ctx: ctx, msg: msg} } // ProtoMessageResponse returns a lazily evaluated [slog.LogValuer] for // the provided message. func ProtoMessageResponse(msg proto.Message) slog.LogValuer { return &protoMessage{msg: msg} } type protoMessage struct { ctx context.Context msg proto.Message } func (m *protoMessage) LogValue() slog.Value { if m == nil || m.msg == nil { return slog.Value{} } var groupValueAttrs []slog.Attr if m.ctx != nil { var headerAttr []slog.Attr if m, ok := metadata.FromOutgoingContext(m.ctx); ok { for k, v := range m { headerAttr = append(headerAttr, slog.String(k, strings.Join(v, ","))) } } if len(headerAttr) > 0 { groupValueAttrs = append(groupValueAttrs, slog.Any("headers", headerAttr)) } } mo := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} if b, err := mo.Marshal(m.msg); err == nil { var m map[string]any if err := json.Unmarshal(b, &m); err == nil { groupValueAttrs = append(groupValueAttrs, slog.Any("payload", m)) } } return slog.GroupValue(groupValueAttrs...) } gax-go-2.14.1/v2/internallog/grpclog/grpclog_test.go000066400000000000000000000057661473113767300223400ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // - Redistributions of source code must retain the above copyright // // notice, this list of conditions and the following disclaimer. // - Redistributions in binary form must reproduce the above // // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // - Neither the name of Google Inc. nor the names of its // // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package grpclog import ( "context" "flag" "log/slog" "os" "testing" "github.com/googleapis/gax-go/v2/internallog/internal" "github.com/googleapis/gax-go/v2/internallog/internal/bookpb" "github.com/googleapis/gax-go/v2/internallog/internal/logtest" "google.golang.org/grpc/metadata" ) // To update conformance tests in this package run `go test -update_golden` func TestMain(m *testing.M) { flag.Parse() os.Exit(m.Run()) } func TestLog_protoMessageRequest(t *testing.T) { golden := "request.log" t.Setenv(internal.LoggingLevelEnvVar, "debug") logger, f := setupLogger(t, golden) ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("foo", "bar")) book := &bookpb.Book{ Title: "The book", Author: "The author", } logger.DebugContext(ctx, "msg", "request", ProtoMessageRequest(ctx, book)) f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_protoMessageResponse(t *testing.T) { golden := "response.log" t.Setenv(internal.LoggingLevelEnvVar, "debug") logger, f := setupLogger(t, golden) ctx := context.Background() book := &bookpb.Book{ Title: "The book", Author: "The author", } logger.DebugContext(ctx, "msg", "response", ProtoMessageResponse(book)) f.Close() logtest.DiffTest(t, f.Name(), golden) } func setupLogger(t *testing.T, golden string) (*slog.Logger, *os.File) { t.Helper() f, err := os.CreateTemp(t.TempDir(), golden) if err != nil { t.Fatal(err) } logger := internal.NewLoggerWithWriter(f) return logger, f } gax-go-2.14.1/v2/internallog/grpclog/testdata/000077500000000000000000000000001473113767300211105ustar00rootroot00000000000000gax-go-2.14.1/v2/internallog/grpclog/testdata/request.log000077500000000000000000000001761473113767300233120ustar00rootroot00000000000000{"message":"msg","request":{"headers":{"foo":"bar"},"payload":{"author":"The author","title":"The book"}},"severity":"DEBUG"} gax-go-2.14.1/v2/internallog/grpclog/testdata/response.log000077500000000000000000000001471473113767300234560ustar00rootroot00000000000000{"message":"msg","response":{"payload":{"author":"The author","title":"The book"}},"severity":"DEBUG"} gax-go-2.14.1/v2/internallog/internal/000077500000000000000000000000001473113767300174565ustar00rootroot00000000000000gax-go-2.14.1/v2/internallog/internal/bookpb/000077500000000000000000000000001473113767300207325ustar00rootroot00000000000000gax-go-2.14.1/v2/internallog/internal/bookpb/book.pb.go000066400000000000000000000137031473113767300226170ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v5.28.2 // source: book.proto package bookpb import ( reflect "reflect" sync "sync" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // A single book in the library. type Book struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The title of the book. Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` // The name of the book author. Author string `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"` } func (x *Book) Reset() { *x = Book{} if protoimpl.UnsafeEnabled { mi := &file_book_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Book) String() string { return protoimpl.X.MessageStringOf(x) } func (*Book) ProtoMessage() {} func (x *Book) ProtoReflect() protoreflect.Message { mi := &file_book_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Book.ProtoReflect.Descriptor instead. func (*Book) Descriptor() ([]byte, []int) { return file_book_proto_rawDescGZIP(), []int{0} } func (x *Book) GetTitle() string { if x != nil { return x.Title } return "" } func (x *Book) GetAuthor() string { if x != nil { return x.Author } return "" } var File_book_proto protoreflect.FileDescriptor var file_book_proto_rawDesc = []byte{ 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x78, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6c, 0x6f, 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x62, 0x6f, 0x6f, 0x6b, 0x70, 0x62, 0x3b, 0x62, 0x6f, 0x6f, 0x6b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_book_proto_rawDescOnce sync.Once file_book_proto_rawDescData = file_book_proto_rawDesc ) func file_book_proto_rawDescGZIP() []byte { file_book_proto_rawDescOnce.Do(func() { file_book_proto_rawDescData = protoimpl.X.CompressGZIP(file_book_proto_rawDescData) }) return file_book_proto_rawDescData } var file_book_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_book_proto_goTypes = []interface{}{ (*Book)(nil), // 0: book.Book } var file_book_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_book_proto_init() } func file_book_proto_init() { if File_book_proto != nil { return } if !protoimpl.UnsafeEnabled { file_book_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Book); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_book_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_book_proto_goTypes, DependencyIndexes: file_book_proto_depIdxs, MessageInfos: file_book_proto_msgTypes, }.Build() File_book_proto = out.File file_book_proto_rawDesc = nil file_book_proto_goTypes = nil file_book_proto_depIdxs = nil } gax-go-2.14.1/v2/internallog/internal/bookpb/book.proto000066400000000000000000000034551473113767300227600ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package book; option go_package = "github.com/googleapis/gax-go/v2/internallog/internal/bookpb;bookpb"; // A single book in the library. message Book { // The title of the book. string title = 1; // The name of the book author. string author = 2; } gax-go-2.14.1/v2/internallog/internal/internal.go000066400000000000000000000100251473113767300216170ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package internal provides some common logic and types to other logging // sub-packages. package internal import ( "context" "io" "log/slog" "os" "strings" "time" ) const ( // LoggingLevelEnvVar is the environment variable used to enable logging // at a particular level. LoggingLevelEnvVar = "GOOGLE_SDK_GO_LOGGING_LEVEL" googLvlKey = "severity" googMsgKey = "message" googSourceKey = "sourceLocation" googTimeKey = "timestamp" ) // NewLoggerWithWriter is exposed for testing. func NewLoggerWithWriter(w io.Writer) *slog.Logger { lvl, loggingEnabled := checkLoggingLevel() if !loggingEnabled { return slog.New(noOpHandler{}) } return slog.New(newGCPSlogHandler(lvl, w)) } // checkLoggingLevel returned the configured logging level and whether or not // logging is enabled. func checkLoggingLevel() (slog.Leveler, bool) { sLevel := strings.ToLower(os.Getenv(LoggingLevelEnvVar)) var level slog.Level switch sLevel { case "debug": level = slog.LevelDebug case "info": level = slog.LevelInfo case "warn": level = slog.LevelWarn case "error": level = slog.LevelError default: return nil, false } return level, true } // newGCPSlogHandler returns a Handler that is configured to output in a JSON // format with well-known keys. For more information on this format see // https://cloud.google.com/logging/docs/agent/logging/configuration#special-fields. func newGCPSlogHandler(lvl slog.Leveler, w io.Writer) slog.Handler { return slog.NewJSONHandler(w, &slog.HandlerOptions{ Level: lvl, ReplaceAttr: replaceAttr, }) } // replaceAttr remaps default Go logging keys to match what is expected in // cloud logging. func replaceAttr(groups []string, a slog.Attr) slog.Attr { if groups == nil { if a.Key == slog.LevelKey { a.Key = googLvlKey return a } else if a.Key == slog.MessageKey { a.Key = googMsgKey return a } else if a.Key == slog.SourceKey { a.Key = googSourceKey return a } else if a.Key == slog.TimeKey { a.Key = googTimeKey if a.Value.Kind() == slog.KindTime { a.Value = slog.StringValue(a.Value.Time().Format(time.RFC3339)) } return a } } return a } // The handler returned if logging is not enabled. type noOpHandler struct{} func (h noOpHandler) Enabled(_ context.Context, _ slog.Level) bool { return false } func (h noOpHandler) Handle(_ context.Context, _ slog.Record) error { return nil } func (h noOpHandler) WithAttrs(_ []slog.Attr) slog.Handler { return h } func (h noOpHandler) WithGroup(_ string) slog.Handler { return h } gax-go-2.14.1/v2/internallog/internal/logtest/000077500000000000000000000000001473113767300211375ustar00rootroot00000000000000gax-go-2.14.1/v2/internallog/internal/logtest/logtest.go000066400000000000000000000063201473113767300231500ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package logtest is a helper for validating logging tests. // // To update conformance tests in this package run `go test -update_golden` package logtest import ( "bytes" "encoding/json" "flag" "os" "path/filepath" "testing" "github.com/google/go-cmp/cmp" ) var updateGolden = flag.Bool("update-golden", false, "update golden files") // DiffTest is a test helper, testing got against contents of a goldenFile. func DiffTest(t *testing.T, tempFile, goldenFile string) { rawGot, err := os.ReadFile(tempFile) if err != nil { t.Fatal(err) } t.Helper() if *updateGolden { got := removeLogVariance(t, rawGot) if err := os.WriteFile(filepath.Join("testdata", goldenFile), got, os.ModePerm); err != nil { t.Fatal(err) } return } want, err := os.ReadFile(filepath.Join("testdata", goldenFile)) if err != nil { t.Fatal(err) } got := removeLogVariance(t, rawGot) if diff := cmp.Diff(want, got); diff != "" { t.Errorf("mismatch(-want, +got): %s", diff) } } // removeLogVariance removes parts of log lines that may differ between runs // and/or machines. func removeLogVariance(t *testing.T, in []byte) []byte { if len(in) == 0 { return in } bs := bytes.Split(in, []byte("\n")) for i, b := range bs { if len(b) == 0 { continue } m := map[string]any{} if err := json.Unmarshal(b, &m); err != nil { t.Fatal(err) } delete(m, "timestamp") if sl, ok := m["sourceLocation"].(map[string]any); ok { delete(sl, "file") // So that if test cases move around in this file they don't cause // failures delete(sl, "line") } b2, err := json.Marshal(m) if err != nil { t.Fatal(err) } t.Logf("%s", b2) bs[i] = b2 } return bytes.Join(bs, []byte("\n")) } gax-go-2.14.1/v2/internallog/internallog.go000066400000000000000000000112041473113767300205050ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Package internallog in intended for internal use by generated clients only. package internallog import ( "bytes" "encoding/json" "fmt" "log/slog" "net/http" "os" "strings" "github.com/googleapis/gax-go/v2/internallog/internal" ) // New returns a new [slog.Logger] default logger, or the provided logger if // non-nil. The returned logger will be a no-op logger unless the environment // variable GOOGLE_SDK_GO_LOGGING_LEVEL is set. func New(l *slog.Logger) *slog.Logger { if l != nil { return l } return internal.NewLoggerWithWriter(os.Stderr) } // HTTPRequest returns a lazily evaluated [slog.LogValuer] for a // [http.Request] and the associated body. func HTTPRequest(req *http.Request, body []byte) slog.LogValuer { return &request{ req: req, payload: body, } } type request struct { req *http.Request payload []byte } func (r *request) LogValue() slog.Value { if r == nil || r.req == nil { return slog.Value{} } var groupValueAttrs []slog.Attr groupValueAttrs = append(groupValueAttrs, slog.String("method", r.req.Method)) groupValueAttrs = append(groupValueAttrs, slog.String("url", r.req.URL.String())) var headerAttr []slog.Attr for k, val := range r.req.Header { headerAttr = append(headerAttr, slog.String(k, strings.Join(val, ","))) } if len(headerAttr) > 0 { groupValueAttrs = append(groupValueAttrs, slog.Any("headers", headerAttr)) } if len(r.payload) > 0 { if attr, ok := processPayload(r.payload); ok { groupValueAttrs = append(groupValueAttrs, attr) } } return slog.GroupValue(groupValueAttrs...) } // HTTPResponse returns a lazily evaluated [slog.LogValuer] for a // [http.Response] and the associated body. func HTTPResponse(resp *http.Response, body []byte) slog.LogValuer { return &response{ resp: resp, payload: body, } } type response struct { resp *http.Response payload []byte } func (r *response) LogValue() slog.Value { if r == nil { return slog.Value{} } var groupValueAttrs []slog.Attr groupValueAttrs = append(groupValueAttrs, slog.String("status", fmt.Sprint(r.resp.StatusCode))) var headerAttr []slog.Attr for k, val := range r.resp.Header { headerAttr = append(headerAttr, slog.String(k, strings.Join(val, ","))) } if len(headerAttr) > 0 { groupValueAttrs = append(groupValueAttrs, slog.Any("headers", headerAttr)) } if len(r.payload) > 0 { if attr, ok := processPayload(r.payload); ok { groupValueAttrs = append(groupValueAttrs, attr) } } return slog.GroupValue(groupValueAttrs...) } func processPayload(payload []byte) (slog.Attr, bool) { peekChar := payload[0] if peekChar == '{' { // JSON object var m map[string]any if err := json.Unmarshal(payload, &m); err == nil { return slog.Any("payload", m), true } } else if peekChar == '[' { // JSON array var m []any if err := json.Unmarshal(payload, &m); err == nil { return slog.Any("payload", m), true } } else { // Everything else buf := &bytes.Buffer{} if err := json.Compact(buf, payload); err != nil { // Write raw payload incase of error buf.Write(payload) } return slog.String("payload", buf.String()), true } return slog.Attr{}, false } gax-go-2.14.1/v2/internallog/internallog_test.go000066400000000000000000000132071473113767300215510ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package internallog import ( "bytes" "context" "flag" "io" "log/slog" "net/http" "net/url" "os" "strings" "testing" "github.com/googleapis/gax-go/v2/internallog/internal" "github.com/googleapis/gax-go/v2/internallog/internal/logtest" ) // To update conformance tests in this package run `go test -update_golden` func TestMain(m *testing.M) { flag.Parse() os.Exit(m.Run()) } func TestLog_off(t *testing.T) { golden := "off.log" logger, f := setupLogger(t, golden) logger.Error("one") logger.Info("two") logger.Warn("three") logger.Debug("four") f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_envarError(t *testing.T) { golden := "envar-error.log" t.Setenv(internal.LoggingLevelEnvVar, "eRrOr") logger, f := setupLogger(t, golden) logger.Error("one") logger.Info("two") logger.Warn("three") logger.Debug("four") f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_envarInfo(t *testing.T) { golden := "envar-info.log" t.Setenv(internal.LoggingLevelEnvVar, "info") logger, f := setupLogger(t, golden) logger.Error("one") logger.Info("two") logger.Warn("three") logger.Debug("four") f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_envarWarn(t *testing.T) { golden := "envar-warn.log" t.Setenv(internal.LoggingLevelEnvVar, "warn") logger, f := setupLogger(t, golden) logger.Error("one") logger.Info("two") logger.Warn("three") logger.Debug("four") f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_envarDebug(t *testing.T) { golden := "envar-debug.log" t.Setenv(internal.LoggingLevelEnvVar, "debug") logger, f := setupLogger(t, golden) logger.Error("one") logger.Info("two") logger.Warn("three") logger.Debug("four") f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_HTTPRequest(t *testing.T) { golden := "httpRequest.log" t.Setenv(internal.LoggingLevelEnvVar, "debug") logger, f := setupLogger(t, golden) ctx := context.Background() body := []byte(`{"secret":"shh, it's a secret"}`) request, err := http.NewRequest(http.MethodPost, "https://example.com", bytes.NewReader(body)) if err != nil { t.Fatal(err) } request.Header.Add("foo", "bar") logger.DebugContext(ctx, "msg", "request", HTTPRequest(request, body)) f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_HTTPResponse(t *testing.T) { golden := "httpResponse.log" t.Setenv(internal.LoggingLevelEnvVar, "debug") logger, f := setupLogger(t, golden) ctx := context.Background() body := []byte(`{"secret":"shh, it's a secret"}`) response := &http.Response{ StatusCode: 200, Header: http.Header{"Foo": []string{"bar"}}, Body: io.NopCloser(bytes.NewReader(body)), } logger.DebugContext(ctx, "msg", "response", HTTPResponse(response, body)) f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_HTTPRequest_formData(t *testing.T) { golden := "httpRequest-form.log" t.Setenv(internal.LoggingLevelEnvVar, "debug") logger, f := setupLogger(t, golden) ctx := context.Background() form := url.Values{} form.Add("foo", "bar") form.Add("baz", "qux") request, err := http.NewRequest(http.MethodPost, "https://example.com", strings.NewReader(form.Encode())) if err != nil { t.Fatal(err) } request.Header.Add("foo", "bar") logger.DebugContext(ctx, "msg", "request", HTTPRequest(request, []byte(form.Encode()))) f.Close() logtest.DiffTest(t, f.Name(), golden) } func TestLog_HTTPRequest_jsonArray(t *testing.T) { golden := "httpRequest-array.log" t.Setenv(internal.LoggingLevelEnvVar, "debug") logger, f := setupLogger(t, golden) ctx := context.Background() body := []byte(`[{"secret":"shh, it's a secret"},{"secret":"and, another"}]`) request, err := http.NewRequest(http.MethodPost, "https://example.com", bytes.NewReader(body)) if err != nil { t.Fatal(err) } request.Header.Add("foo", "bar") logger.DebugContext(ctx, "msg", "request", HTTPRequest(request, body)) f.Close() logtest.DiffTest(t, f.Name(), golden) } func setupLogger(t *testing.T, golden string) (*slog.Logger, *os.File) { t.Helper() f, err := os.CreateTemp(t.TempDir(), golden) if err != nil { t.Fatal(err) } logger := internal.NewLoggerWithWriter(f) return logger, f } gax-go-2.14.1/v2/internallog/testdata/000077500000000000000000000000001473113767300174535ustar00rootroot00000000000000gax-go-2.14.1/v2/internallog/testdata/envar-debug.log000077500000000000000000000002251473113767300223570ustar00rootroot00000000000000{"message":"one","severity":"ERROR"} {"message":"two","severity":"INFO"} {"message":"three","severity":"WARN"} {"message":"four","severity":"DEBUG"} gax-go-2.14.1/v2/internallog/testdata/envar-error.log000077500000000000000000000000451473113767300224220ustar00rootroot00000000000000{"message":"one","severity":"ERROR"} gax-go-2.14.1/v2/internallog/testdata/envar-info.log000077500000000000000000000001571473113767300222300ustar00rootroot00000000000000{"message":"one","severity":"ERROR"} {"message":"two","severity":"INFO"} {"message":"three","severity":"WARN"} gax-go-2.14.1/v2/internallog/testdata/envar-warn.log000077500000000000000000000001131473113767300222340ustar00rootroot00000000000000{"message":"one","severity":"ERROR"} {"message":"three","severity":"WARN"} gax-go-2.14.1/v2/internallog/testdata/httpRequest-array.log000077500000000000000000000002731473113767300236270ustar00rootroot00000000000000{"message":"msg","request":{"headers":{"Foo":"bar"},"method":"POST","payload":[{"secret":"shh, it's a secret"},{"secret":"and, another"}],"url":"https://example.com"},"severity":"DEBUG"} gax-go-2.14.1/v2/internallog/testdata/httpRequest-form.log000077500000000000000000000002261473113767300234520ustar00rootroot00000000000000{"message":"msg","request":{"headers":{"Foo":"bar"},"method":"POST","payload":"baz=qux\u0026foo=bar","url":"https://example.com"},"severity":"DEBUG"} gax-go-2.14.1/v2/internallog/testdata/httpRequest.log000077500000000000000000000002371473113767300225130ustar00rootroot00000000000000{"message":"msg","request":{"headers":{"Foo":"bar"},"method":"POST","payload":{"secret":"shh, it's a secret"},"url":"https://example.com"},"severity":"DEBUG"} gax-go-2.14.1/v2/internallog/testdata/httpResponse.log000077500000000000000000000002031473113767300226520ustar00rootroot00000000000000{"message":"msg","response":{"headers":{"Foo":"bar"},"payload":{"secret":"shh, it's a secret"},"status":"200"},"severity":"DEBUG"} gax-go-2.14.1/v2/internallog/testdata/off.log000077500000000000000000000000001473113767300207210ustar00rootroot00000000000000gax-go-2.14.1/v2/invoke.go000066400000000000000000000074671473113767300151640ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "context" "strings" "time" "github.com/googleapis/gax-go/v2/apierror" ) // APICall is a user defined call stub. type APICall func(context.Context, CallSettings) error // Invoke calls the given APICall, performing retries as specified by opts, if // any. func Invoke(ctx context.Context, call APICall, opts ...CallOption) error { var settings CallSettings for _, opt := range opts { opt.Resolve(&settings) } return invoke(ctx, call, settings, Sleep) } // Sleep is similar to time.Sleep, but it can be interrupted by ctx.Done() closing. // If interrupted, Sleep returns ctx.Err(). func Sleep(ctx context.Context, d time.Duration) error { t := time.NewTimer(d) select { case <-ctx.Done(): t.Stop() return ctx.Err() case <-t.C: return nil } } type sleeper func(ctx context.Context, d time.Duration) error // invoke implements Invoke, taking an additional sleeper argument for testing. func invoke(ctx context.Context, call APICall, settings CallSettings, sp sleeper) error { var retryer Retryer // Only use the value provided via WithTimeout if the context doesn't // already have a deadline. This is important for backwards compatibility if // the user already set a deadline on the context given to Invoke. if _, ok := ctx.Deadline(); !ok && settings.timeout != 0 { c, cc := context.WithTimeout(ctx, settings.timeout) defer cc() ctx = c } for { err := call(ctx, settings) if err == nil { return nil } // Never retry permanent certificate errors. (e.x. if ca-certificates // are not installed). We should only make very few, targeted // exceptions: many (other) status=Unavailable should be retried, such // as if there's a network hiccup, or the internet goes out for a // minute. This is also why here we are doing string parsing instead of // simply making Unavailable a non-retried code elsewhere. if strings.Contains(err.Error(), "x509: certificate signed by unknown authority") { return err } if apierr, ok := apierror.FromError(err); ok { err = apierr } if settings.Retry == nil { return err } if retryer == nil { if r := settings.Retry(); r != nil { retryer = r } else { return err } } if d, ok := retryer.Retry(err); !ok { return err } else if err = sp(ctx, d); err != nil { return err } } } gax-go-2.14.1/v2/invoke_test.go000066400000000000000000000202561473113767300162120ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "context" "errors" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/googleapis/gax-go/v2/apierror" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) var canceledContext context.Context func init() { ctx, cancel := context.WithCancel(context.Background()) cancel() canceledContext = ctx } // recordSleeper is a test implementation of sleeper. type recordSleeper int func (s *recordSleeper) sleep(ctx context.Context, _ time.Duration) error { *s++ return ctx.Err() } type boolRetryer bool func (r boolRetryer) Retry(err error) (time.Duration, bool) { return 0, bool(r) } func TestInvokeSuccess(t *testing.T) { apiCall := func(context.Context, CallSettings) error { return nil } var sp recordSleeper err := invoke(context.Background(), apiCall, CallSettings{}, sp.sleep) if err != nil { t.Errorf("found error %s, want nil", err) } if sp != 0 { t.Errorf("slept %d times, should not have slept since the call succeeded", int(sp)) } } func TestInvokeCertificateError(t *testing.T) { stat := status.New(codes.Unavailable, "x509: certificate signed by unknown authority") apiErr := stat.Err() apiCall := func(context.Context, CallSettings) error { return apiErr } var sp recordSleeper err := invoke(context.Background(), apiCall, CallSettings{}, sp.sleep) if diff := cmp.Diff(err, apiErr, cmpopts.EquateErrors()); diff != "" { t.Errorf("got(-), want(+): \n%s", diff) } } func TestInvokeAPIError(t *testing.T) { qf := &errdetails.QuotaFailure{ Violations: []*errdetails.QuotaFailure_Violation{{Subject: "Foo", Description: "Bar"}}, } stat, _ := status.New(codes.ResourceExhausted, "Per user quota has been exhausted").WithDetails(qf) apiErr, _ := apierror.FromError(stat.Err()) apiCall := func(context.Context, CallSettings) error { return stat.Err() } var sp recordSleeper err := invoke(context.Background(), apiCall, CallSettings{}, sp.sleep) if diff := cmp.Diff(err.Error(), apiErr.Error()); diff != "" { t.Errorf("got(-), want(+): \n%s", diff) } if sp != 0 { t.Errorf("slept %d times, should not have slept since the call succeeded", int(sp)) } } func TestInvokeCtxError(t *testing.T) { ctxErr := context.DeadlineExceeded apiCall := func(context.Context, CallSettings) error { return ctxErr } var sp recordSleeper err := invoke(context.Background(), apiCall, CallSettings{}, sp.sleep) if err != ctxErr { t.Errorf("found error %s, want %s", err, ctxErr) } if sp != 0 { t.Errorf("slept %d times, should not have slept since the call succeeded", int(sp)) } } func TestInvokeNoRetry(t *testing.T) { apiErr := errors.New("foo error") apiCall := func(context.Context, CallSettings) error { return apiErr } var sp recordSleeper err := invoke(context.Background(), apiCall, CallSettings{}, sp.sleep) if err != apiErr { t.Errorf("found error %s, want %s", err, apiErr) } if sp != 0 { t.Errorf("slept %d times, should not have slept since retry is not specified", int(sp)) } } func TestInvokeNilRetry(t *testing.T) { apiErr := errors.New("foo error") apiCall := func(context.Context, CallSettings) error { return apiErr } var settings CallSettings WithRetry(func() Retryer { return nil }).Resolve(&settings) var sp recordSleeper err := invoke(context.Background(), apiCall, settings, sp.sleep) if err != apiErr { t.Errorf("found error %s, want %s", err, apiErr) } if sp != 0 { t.Errorf("slept %d times, should not have slept since retry is not specified", int(sp)) } } func TestInvokeNeverRetry(t *testing.T) { apiErr := errors.New("foo error") apiCall := func(context.Context, CallSettings) error { return apiErr } var settings CallSettings WithRetry(func() Retryer { return boolRetryer(false) }).Resolve(&settings) var sp recordSleeper err := invoke(context.Background(), apiCall, settings, sp.sleep) if err != apiErr { t.Errorf("found error %s, want %s", err, apiErr) } if sp != 0 { t.Errorf("slept %d times, should not have slept since retry is not specified", int(sp)) } } func TestInvokeRetry(t *testing.T) { const target = 3 retryNum := 0 apiErr := errors.New("foo error") apiCall := func(context.Context, CallSettings) error { retryNum++ if retryNum < target { return apiErr } return nil } var settings CallSettings WithRetry(func() Retryer { return boolRetryer(true) }).Resolve(&settings) var sp recordSleeper err := invoke(context.Background(), apiCall, settings, sp.sleep) if err != nil { t.Errorf("found error %s, want nil, call should have succeeded after %d tries", err, target) } if sp != target-1 { t.Errorf("retried %d times, want %d", int(sp), int(target-1)) } } func TestInvokeRetryTimeout(t *testing.T) { apiErr := errors.New("foo error") apiCall := func(context.Context, CallSettings) error { return apiErr } var settings CallSettings WithRetry(func() Retryer { return boolRetryer(true) }).Resolve(&settings) var sp recordSleeper err := invoke(canceledContext, apiCall, settings, sp.sleep) if err != context.Canceled { t.Errorf("found error %s, want %s", err, context.Canceled) } } func TestInvokeWithTimeout(t *testing.T) { // Dummy APICall that sleeps for the given amount of time. This simulates an // APICall executing, allowing us to verify which deadline was respected, // that which is already set on the Context, or the one calculated using the // WithTimeout option's value. sleepingCall := func(sleep time.Duration) APICall { return func(ctx context.Context, _ CallSettings) error { time.Sleep(sleep) return ctx.Err() } } bg := context.Background() preset, pcc := context.WithTimeout(bg, 10*time.Millisecond) defer pcc() for _, tst := range []struct { name string timeout time.Duration sleep time.Duration ctx context.Context want error }{ { name: "success", timeout: 10 * time.Millisecond, sleep: 1 * time.Millisecond, ctx: bg, want: nil, }, { name: "respect_context_deadline", timeout: 1 * time.Millisecond, sleep: 3 * time.Millisecond, ctx: preset, want: nil, }, { name: "with_timeout_deadline_exceeded", timeout: 1 * time.Millisecond, sleep: 3 * time.Millisecond, ctx: bg, want: context.DeadlineExceeded, }, } { t.Run(tst.name, func(t *testing.T) { // Recording sleep isn't really necessary since there is // no retry here, but we need a sleeper so might as well. var sp recordSleeper var settings CallSettings WithTimeout(tst.timeout).Resolve(&settings) err := invoke(tst.ctx, sleepingCall(tst.sleep), settings, sp.sleep) if err != tst.want { t.Errorf("found error %v, want %v", err, tst.want) } }) } } gax-go-2.14.1/v2/iterator/000077500000000000000000000000001473113767300151555ustar00rootroot00000000000000gax-go-2.14.1/v2/iterator/example_test.go000066400000000000000000000042521473113767300202010ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //go:build go1.23 package iterator_test import ( "fmt" "iter" "github.com/googleapis/gax-go/v2/iterator" otherit "google.golang.org/api/iterator" ) type exampleType struct { data []int i int } func (t *exampleType) next() (int, error) { var v int if t.i == len(t.data) { return v, otherit.Done } v = t.data[t.i] t.i++ return v, nil } func (t *exampleType) All() iter.Seq2[int, error] { return iterator.RangeAdapter[int](t.next) } func ExampleRangeAdapter() { t := &exampleType{ data: []int{1, 2, 3}, } for v, err := range t.All() { if err != nil { // TODO: handle error } fmt.Println(v) } // Output: // 1 // 2 // 3 } gax-go-2.14.1/v2/iterator/iterator.go000066400000000000000000000043011473113767300173330ustar00rootroot00000000000000// Copyright 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //go:build go1.23 // Package iterator contains helper for working with iterators. It is meant for // internal use only by the Go Client Libraries. package iterator import ( "iter" otherit "google.golang.org/api/iterator" ) // RangeAdapter transforms client iterator type into a [iter.Seq2] that can // be used with Go's range expressions. // // This is for internal use only. func RangeAdapter[T any](next func() (T, error)) iter.Seq2[T, error] { var err error return func(yield func(T, error) bool) { for { if err != nil { return } var resp T resp, err = next() if err == otherit.Done { return } if !yield(resp, err) { return } } } } gax-go-2.14.1/v2/proto_json_stream.go000066400000000000000000000107301473113767300174230ustar00rootroot00000000000000// Copyright 2022, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "encoding/json" "errors" "io" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" ) var ( arrayOpen = json.Delim('[') arrayClose = json.Delim(']') errBadOpening = errors.New("unexpected opening token, expected '['") ) // ProtoJSONStream represents a wrapper for consuming a stream of protobuf // messages encoded using protobuf-JSON format. More information on this format // can be found at https://developers.google.com/protocol-buffers/docs/proto3#json. // The stream must appear as a comma-delimited, JSON array of obbjects with // opening and closing square braces. // // This is for internal use only. type ProtoJSONStream struct { first, closed bool reader io.ReadCloser stream *json.Decoder typ protoreflect.MessageType } // NewProtoJSONStreamReader accepts a stream of bytes via an io.ReadCloser that are // protobuf-JSON encoded protobuf messages of the given type. The ProtoJSONStream // must be closed when done. // // This is for internal use only. func NewProtoJSONStreamReader(rc io.ReadCloser, typ protoreflect.MessageType) *ProtoJSONStream { return &ProtoJSONStream{ first: true, reader: rc, stream: json.NewDecoder(rc), typ: typ, } } // Recv decodes the next protobuf message in the stream or returns io.EOF if // the stream is done. It is not safe to call Recv on the same stream from // different goroutines, just like it is not safe to do so with a single gRPC // stream. Type-cast the protobuf message returned to the type provided at // ProtoJSONStream creation. // Calls to Recv after calling Close will produce io.EOF. func (s *ProtoJSONStream) Recv() (proto.Message, error) { if s.closed { return nil, io.EOF } if s.first { s.first = false // Consume the opening '[' so Decode gets one object at a time. if t, err := s.stream.Token(); err != nil { return nil, err } else if t != arrayOpen { return nil, errBadOpening } } // Capture the next block of data for the item (a JSON object) in the stream. var raw json.RawMessage if err := s.stream.Decode(&raw); err != nil { e := err // To avoid checking the first token of each stream, just attempt to // Decode the next blob and if that fails, double check if it is just // the closing token ']'. If it is the closing, return io.EOF. If it // isn't, return the original error. if t, _ := s.stream.Token(); t == arrayClose { e = io.EOF } return nil, e } // Initialize a new instance of the protobuf message to unmarshal the // raw data into. m := s.typ.New().Interface() unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} err := unm.Unmarshal(raw, m) return m, err } // Close closes the stream so that resources are cleaned up. func (s *ProtoJSONStream) Close() error { // Dereference the *json.Decoder so that the memory is gc'd. s.stream = nil s.closed = true return s.reader.Close() } gax-go-2.14.1/v2/proto_json_stream_test.go000066400000000000000000000120721473113767300204630ustar00rootroot00000000000000// Copyright 2022, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package gax import ( "bytes" "errors" "io" "io/ioutil" "testing" "time" "github.com/google/go-cmp/cmp" serviceconfigpb "google.golang.org/genproto/googleapis/api/serviceconfig" "google.golang.org/genproto/googleapis/rpc/code" "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" ) func TestRecv(t *testing.T) { locations := []proto.Message{ &serviceconfigpb.Property{ Name: "property1", Type: serviceconfigpb.Property_STRING, Description: "Property 1", }, &serviceconfigpb.Property{ Name: "property2", Type: serviceconfigpb.Property_STRING, Description: "Property 2", }, &serviceconfigpb.Property{ Name: "property3", Type: serviceconfigpb.Property_STRING, Description: "Property 3", }, } durations := []proto.Message{ durationpb.New(time.Second), durationpb.New(time.Minute), durationpb.New(time.Hour), } detail, err := anypb.New(locations[0]) if err != nil { t.Fatal(err) } nested := []proto.Message{ &status.Status{ Code: int32(code.Code_INTERNAL), Message: "oops", Details: []*anypb.Any{ detail, }, }, } for _, tst := range []struct { name string want []proto.Message typ protoreflect.MessageType }{ { name: "empty", }, { name: "simple_locations", want: locations, typ: locations[0].ProtoReflect().Type(), }, { // google.type.Duration is JSON encoded as a string, not an object. name: "message_as_primitive", want: durations, typ: durations[0].ProtoReflect().Type(), }, { name: "nested", want: nested, typ: nested[0].ProtoReflect().Type(), }, } { s, err := prepareStream(tst.want) if err != nil { t.Errorf("%s: %v", tst.name, err) continue } stream := NewProtoJSONStreamReader(s, tst.typ) defer stream.Close() got, err := stream.Recv() for ndx := 0; err == nil; ndx++ { if diff := cmp.Diff(got, tst.want[ndx], cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("%s: got(-),want(+):\n%s", tst.name, diff) } got, err = stream.Recv() } if !errors.Is(err, io.EOF) { t.Errorf("%s: expected %v but got %v", tst.name, io.EOF, err) } } } func TestRecvAfterClose(t *testing.T) { empty := ioutil.NopCloser(bytes.NewReader([]byte("[]"))) s := NewProtoJSONStreamReader(empty, nil) if _, err := s.Recv(); !errors.Is(err, io.EOF) { t.Errorf("Expected %v but got %v", io.EOF, err) } // Close to ensure reader is closed. s.Close() if _, err := s.Recv(); !errors.Is(err, io.EOF) { t.Errorf("Expected %v after close but got %v", io.EOF, err) } } func TestRecvError(t *testing.T) { noOpening := ioutil.NopCloser(bytes.NewReader([]byte{'{'})) s := NewProtoJSONStreamReader(noOpening, nil) if _, err := s.Recv(); !errors.Is(err, errBadOpening) { t.Errorf("Expected %v but got %v", errBadOpening, err) } } func prepareStream(messages []proto.Message) (io.ReadCloser, error) { if len(messages) == 0 { return ioutil.NopCloser(bytes.NewReader([]byte("[]"))), nil } data := []byte("[") mo := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} for _, m := range messages { d, err := mo.Marshal(m) if err != nil { return nil, err } data = append(data, d...) data = append(data, ',') } // Set the trailing ',' to a closing ']'. data[len(data)-1] = ']' return ioutil.NopCloser(bytes.NewReader(data)), nil } gax-go-2.14.1/v2/release-please-config.json000066400000000000000000000002771473113767300203570ustar00rootroot00000000000000{ "release-type": "go-yoshi", "separate-pull-requests": true, "include-component-in-tag": false, "packages": { "v2": { "component": "v2" } } }