mirror of
https://github.com/GoogleContainerTools/kaniko
synced 2026-10-21 11:04:24 +02:00
fix(executor): make pax tar builds reproducible again (#2384)
In v1.8.0 (commit 7410007) kaniko switched to using the pax tar header
format for compressing image layers, since this format allows for greater
precision in recording timestamps, however this inadvertendly broke the
"--reproducible" functionality, due to an bug in the underlying
go-containerregistry dependency which did not set the additional
timestamps in the pax header when canonicalizing image layers. This
oversight has since been fixed in the dependency.
This commit bumps the google/go-containerregistry dependency to the
first commit which has fixed the bug
(v0.13.1-0.20230201183932-824efc7772b0). It also bumps the version of
cloud.google.com/go/storage to v1.29.0 to be compatible with the higher
transitive dependency.
This commit is contained in:
Generated
Vendored
+1
-1
@@ -193,7 +193,7 @@
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
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,
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
// Copyright 2022 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package client is a cross-platform client for the signer binary (a.k.a."EnterpriseCertSigner").
|
||||
//
|
||||
// The signer binary is OS-specific, but exposes a standard set of APIs for the client to use.
|
||||
package client
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/rpc"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/googleapis/enterprise-certificate-proxy/client/util"
|
||||
)
|
||||
|
||||
const signAPI = "EnterpriseCertSigner.Sign"
|
||||
const certificateChainAPI = "EnterpriseCertSigner.CertificateChain"
|
||||
const publicKeyAPI = "EnterpriseCertSigner.Public"
|
||||
|
||||
// A Connection wraps a pair of unidirectional streams as an io.ReadWriteCloser.
|
||||
type Connection struct {
|
||||
io.ReadCloser
|
||||
io.WriteCloser
|
||||
}
|
||||
|
||||
// Close closes c's underlying ReadCloser and WriteCloser.
|
||||
func (c *Connection) Close() error {
|
||||
rerr := c.ReadCloser.Close()
|
||||
werr := c.WriteCloser.Close()
|
||||
if rerr != nil {
|
||||
return rerr
|
||||
}
|
||||
return werr
|
||||
}
|
||||
|
||||
// If ECP Logging is enabled return true
|
||||
// Otherwise return false
|
||||
func enableECPLogging() bool {
|
||||
if os.Getenv("ENABLE_ENTERPRISE_CERTIFICATE_LOGS") != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
log.SetOutput(ioutil.Discard)
|
||||
return false
|
||||
}
|
||||
|
||||
func init() {
|
||||
gob.Register(crypto.SHA256)
|
||||
gob.Register(&rsa.PSSOptions{})
|
||||
}
|
||||
|
||||
// SignArgs contains arguments to a crypto Signer.Sign method.
|
||||
type SignArgs struct {
|
||||
Digest []byte // The content to sign.
|
||||
Opts crypto.SignerOpts // Options for signing, such as Hash identifier.
|
||||
}
|
||||
|
||||
// Key implements credential.Credential by holding the executed signer subprocess.
|
||||
type Key struct {
|
||||
cmd *exec.Cmd // Pointer to the signer subprocess.
|
||||
client *rpc.Client // Pointer to the rpc client that communicates with the signer subprocess.
|
||||
publicKey crypto.PublicKey // Public key of loaded certificate.
|
||||
chain [][]byte // Certificate chain of loaded certificate.
|
||||
}
|
||||
|
||||
// CertificateChain returns the credential as a raw X509 cert chain. This contains the public key.
|
||||
func (k *Key) CertificateChain() [][]byte {
|
||||
return k.chain
|
||||
}
|
||||
|
||||
// Close closes the RPC connection and kills the signer subprocess.
|
||||
// Call this to free up resources when the Key object is no longer needed.
|
||||
func (k *Key) Close() error {
|
||||
if err := k.cmd.Process.Kill(); err != nil {
|
||||
return fmt.Errorf("failed to kill signer process: %w", err)
|
||||
}
|
||||
// Wait for cmd to exit and release resources. Since the process is forcefully killed, this
|
||||
// will return a non-nil error (varies by OS), which we will ignore.
|
||||
k.cmd.Wait()
|
||||
// The Pipes connecting the RPC client should have been closed when the signer subprocess was killed.
|
||||
// Calling `k.client.Close()` before `k.cmd.Process.Kill()` or `k.cmd.Wait()` _will_ cause a segfault.
|
||||
if err := k.client.Close(); err.Error() != "close |0: file already closed" {
|
||||
return fmt.Errorf("failed to close RPC connection: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Public returns the public key for this Key.
|
||||
func (k *Key) Public() crypto.PublicKey {
|
||||
return k.publicKey
|
||||
}
|
||||
|
||||
// Sign signs a message digest, using the specified signer options.
|
||||
func (k *Key) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) (signed []byte, err error) {
|
||||
if opts != nil && opts.HashFunc() != 0 && len(digest) != opts.HashFunc().Size() {
|
||||
return nil, fmt.Errorf("Digest length of %v bytes does not match Hash function size of %v bytes", len(digest), opts.HashFunc().Size())
|
||||
}
|
||||
err = k.client.Call(signAPI, SignArgs{Digest: digest, Opts: opts}, &signed)
|
||||
return
|
||||
}
|
||||
|
||||
// Cred spawns a signer subprocess that listens on stdin/stdout to perform certificate
|
||||
// related operations, including signing messages with the private key.
|
||||
//
|
||||
// The signer binary path is read from the specified configFilePath, if provided.
|
||||
// Otherwise, use the default config file path.
|
||||
//
|
||||
// The config file also specifies which certificate the signer should use.
|
||||
func Cred(configFilePath string) (*Key, error) {
|
||||
enableECPLogging()
|
||||
if configFilePath == "" {
|
||||
configFilePath = util.GetDefaultConfigFilePath()
|
||||
}
|
||||
enterpriseCertSignerPath, err := util.LoadSignerBinaryPath(configFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k := &Key{
|
||||
cmd: exec.Command(enterpriseCertSignerPath, configFilePath),
|
||||
}
|
||||
|
||||
// Redirect errors from subprocess to parent process.
|
||||
k.cmd.Stderr = os.Stderr
|
||||
|
||||
// RPC client will communicate with subprocess over stdin/stdout.
|
||||
kin, err := k.cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kout, err := k.cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k.client = rpc.NewClient(&Connection{kout, kin})
|
||||
|
||||
if err := k.cmd.Start(); err != nil {
|
||||
return nil, fmt.Errorf("starting enterprise cert signer subprocess: %w", err)
|
||||
}
|
||||
|
||||
if err := k.client.Call(certificateChainAPI, struct{}{}, &k.chain); err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve certificate chain: %w", err)
|
||||
}
|
||||
|
||||
var publicKeyBytes []byte
|
||||
if err := k.client.Call(publicKeyAPI, struct{}{}, &publicKeyBytes); err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve public key: %w", err)
|
||||
}
|
||||
|
||||
publicKey, err := x509.ParsePKIXPublicKey(publicKeyBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse public key: %w", err)
|
||||
}
|
||||
|
||||
var ok bool
|
||||
k.publicKey, ok = publicKey.(crypto.PublicKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid public key type: %T", publicKey)
|
||||
}
|
||||
|
||||
switch pub := k.publicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
if pub.Size() < 256 {
|
||||
return nil, fmt.Errorf("RSA modulus size is less than 2048 bits: %v", pub.Size()*8)
|
||||
}
|
||||
case *ecdsa.PublicKey:
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported public key type: %v", pub)
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// Package util provides helper functions for the client.
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const configFileName = "certificate_config.json"
|
||||
|
||||
// EnterpriseCertificateConfig contains parameters for initializing signer.
|
||||
type EnterpriseCertificateConfig struct {
|
||||
Libs Libs `json:"libs"`
|
||||
}
|
||||
|
||||
// Libs specifies the locations of helper libraries.
|
||||
type Libs struct {
|
||||
ECP string `json:"ecp"`
|
||||
}
|
||||
|
||||
// LoadSignerBinaryPath retrieves the path of the signer binary from the config file.
|
||||
func LoadSignerBinaryPath(configFilePath string) (path string, err error) {
|
||||
jsonFile, err := os.Open(configFilePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
byteValue, err := ioutil.ReadAll(jsonFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var config EnterpriseCertificateConfig
|
||||
err = json.Unmarshal(byteValue, &config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
signerBinaryPath := config.Libs.ECP
|
||||
if signerBinaryPath == "" {
|
||||
return "", errors.New("signer binary path is missing")
|
||||
}
|
||||
return signerBinaryPath, nil
|
||||
}
|
||||
|
||||
func guessHomeDir() string {
|
||||
// Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
|
||||
if v := os.Getenv("HOME"); v != "" {
|
||||
return v
|
||||
}
|
||||
// Else, fall back to user.Current:
|
||||
if u, err := user.Current(); err == nil {
|
||||
return u.HomeDir
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getDefaultConfigFileDirectory() (directory string) {
|
||||
if runtime.GOOS == "windows" {
|
||||
return filepath.Join(os.Getenv("APPDATA"), "gcloud")
|
||||
}
|
||||
return filepath.Join(guessHomeDir(), ".config/gcloud")
|
||||
}
|
||||
|
||||
// GetDefaultConfigFilePath returns the default path of the enterprise certificate config file created by gCloud.
|
||||
func GetDefaultConfigFilePath() (path string) {
|
||||
return filepath.Join(getDefaultConfigFileDirectory(), configFileName)
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"v2": "2.7.0"
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# Changelog
|
||||
|
||||
## [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))
|
||||
+60
-14
@@ -32,6 +32,7 @@
|
||||
package apierror
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -40,6 +41,7 @@ import (
|
||||
"google.golang.org/genproto/googleapis/rpc/errdetails"
|
||||
"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.
|
||||
@@ -59,6 +61,30 @@ type ErrDetails struct {
|
||||
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 {
|
||||
@@ -207,29 +233,49 @@ func (a *APIError) Metadata() map[string]string {
|
||||
|
||||
}
|
||||
|
||||
// FromError parses a Status error or a googleapi.Error and builds an APIError.
|
||||
func FromError(err error) (*APIError, bool) {
|
||||
if err == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
ae := APIError{err: err}
|
||||
// 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.
|
||||
func (a *APIError) setDetailsFromError(err error) bool {
|
||||
st, isStatus := status.FromError(err)
|
||||
herr, isHTTPErr := err.(*googleapi.Error)
|
||||
var herr *googleapi.Error
|
||||
isHTTPErr := errors.As(err, &herr)
|
||||
|
||||
switch {
|
||||
case isStatus:
|
||||
ae.status = st
|
||||
ae.details = parseDetails(st.Details())
|
||||
a.status = st
|
||||
a.details = parseDetails(st.Details())
|
||||
case isHTTPErr:
|
||||
ae.httpErr = herr
|
||||
ae.details = parseHTTPDetails(herr)
|
||||
a.httpErr = herr
|
||||
a.details = parseHTTPDetails(herr)
|
||||
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
|
||||
|
||||
Generated
Vendored
+256
@@ -0,0 +1,256 @@
|
||||
// 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
|
||||
}
|
||||
Generated
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
// 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;
|
||||
}
|
||||
+56
-54
@@ -14,9 +14,9 @@
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc-gen-go v1.28.0
|
||||
// protoc v3.15.8
|
||||
// source: error.proto
|
||||
// source: apierror/internal/proto/error.proto
|
||||
|
||||
package jsonerror
|
||||
|
||||
@@ -55,7 +55,7 @@ type Error struct {
|
||||
func (x *Error) Reset() {
|
||||
*x = Error{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_error_proto_msgTypes[0]
|
||||
mi := &file_apierror_internal_proto_error_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func (x *Error) String() string {
|
||||
func (*Error) ProtoMessage() {}
|
||||
|
||||
func (x *Error) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_error_proto_msgTypes[0]
|
||||
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 {
|
||||
@@ -81,7 +81,7 @@ func (x *Error) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Error.ProtoReflect.Descriptor instead.
|
||||
func (*Error) Descriptor() ([]byte, []int) {
|
||||
return file_error_proto_rawDescGZIP(), []int{0}
|
||||
return file_apierror_internal_proto_error_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Error) GetError() *Error_Status {
|
||||
@@ -112,7 +112,7 @@ type Error_Status struct {
|
||||
func (x *Error_Status) Reset() {
|
||||
*x = Error_Status{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_error_proto_msgTypes[1]
|
||||
mi := &file_apierror_internal_proto_error_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -125,7 +125,7 @@ func (x *Error_Status) String() string {
|
||||
func (*Error_Status) ProtoMessage() {}
|
||||
|
||||
func (x *Error_Status) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_error_proto_msgTypes[1]
|
||||
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 {
|
||||
@@ -138,7 +138,7 @@ func (x *Error_Status) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Error_Status.ProtoReflect.Descriptor instead.
|
||||
func (*Error_Status) Descriptor() ([]byte, []int) {
|
||||
return file_error_proto_rawDescGZIP(), []int{0, 0}
|
||||
return file_apierror_internal_proto_error_proto_rawDescGZIP(), []int{0, 0}
|
||||
}
|
||||
|
||||
func (x *Error_Status) GetCode() int32 {
|
||||
@@ -169,53 +169,55 @@ func (x *Error_Status) GetDetails() []*anypb.Any {
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_error_proto protoreflect.FileDescriptor
|
||||
var File_apierror_internal_proto_error_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_error_proto_rawDesc = []byte{
|
||||
0x0a, 0x0b, 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_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_error_proto_rawDescOnce sync.Once
|
||||
file_error_proto_rawDescData = file_error_proto_rawDesc
|
||||
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_error_proto_rawDescGZIP() []byte {
|
||||
file_error_proto_rawDescOnce.Do(func() {
|
||||
file_error_proto_rawDescData = protoimpl.X.CompressGZIP(file_error_proto_rawDescData)
|
||||
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_error_proto_rawDescData
|
||||
return file_apierror_internal_proto_error_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_error_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_error_proto_goTypes = []interface{}{
|
||||
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_error_proto_depIdxs = []int32{
|
||||
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
|
||||
@@ -226,13 +228,13 @@ var file_error_proto_depIdxs = []int32{
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_error_proto_init() }
|
||||
func file_error_proto_init() {
|
||||
if File_error_proto != nil {
|
||||
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_error_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
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
|
||||
@@ -244,7 +246,7 @@ func file_error_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_error_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
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
|
||||
@@ -261,18 +263,18 @@ func file_error_proto_init() {
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_error_proto_rawDesc,
|
||||
RawDescriptor: file_apierror_internal_proto_error_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_error_proto_goTypes,
|
||||
DependencyIndexes: file_error_proto_depIdxs,
|
||||
MessageInfos: file_error_proto_msgTypes,
|
||||
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_error_proto = out.File
|
||||
file_error_proto_rawDesc = nil
|
||||
file_error_proto_goTypes = nil
|
||||
file_error_proto_depIdxs = nil
|
||||
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
|
||||
}
|
||||
|
||||
+55
@@ -30,9 +30,11 @@
|
||||
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"
|
||||
@@ -119,6 +121,41 @@ func (r *boRetryer) Retry(err error) (time.Duration, bool) {
|
||||
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
|
||||
@@ -173,6 +210,21 @@ func (o grpcOpt) Resolve(s *CallSettings) {
|
||||
s.GRPC = o
|
||||
}
|
||||
|
||||
type pathOpt struct {
|
||||
p string
|
||||
}
|
||||
|
||||
func (p pathOpt) Resolve(s *CallSettings) {
|
||||
s.Path = p.p
|
||||
}
|
||||
|
||||
// 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...))
|
||||
@@ -186,4 +238,7 @@ type CallSettings struct {
|
||||
|
||||
// CallOptions to be forwarded to GRPC.
|
||||
GRPC []grpc.CallOption
|
||||
|
||||
// Path is an HTTP override for an APICall.
|
||||
Path string
|
||||
}
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
// 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, ""
|
||||
}
|
||||
+3
-1
@@ -35,5 +35,7 @@
|
||||
// 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 = "2.2.0"
|
||||
const Version = internal.Version
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// 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.7.0"
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"release-type": "go-yoshi",
|
||||
"separate-pull-requests": true,
|
||||
"include-component-in-tag": false,
|
||||
"packages": {
|
||||
"v2": {
|
||||
"component": "v2"
|
||||
}
|
||||
}
|
||||
}
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
// 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
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
|
||||
cpb "google.golang.org/genproto/googleapis/type/color"
|
||||
wpb "google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
// ProtoColorToRGBA returns an RGBA based on the provided google.type.Color.
|
||||
// If alpha is not set in the proto, full opacity is assumed.
|
||||
//
|
||||
// Note: Converting between a float using [0, 1] to an int using [0, 256)
|
||||
// causes some cognitive dissonance between accuracy and user expectations.
|
||||
// For example, most people writing CSS use 0x80 (decimal 128) to mean "half",
|
||||
// but it is not actually half (it is slightly over). There is actually no
|
||||
// way to precisely specify the 0.5 float value in a [0, 256) range of
|
||||
// integers.
|
||||
//
|
||||
// This function uses math.Round to address this, meaning that 0.5 will be
|
||||
// rounded up to 128 rather than rounded down to 127.
|
||||
//
|
||||
// Because of this fuzziness and precision loss, it is NOT guaranteed that
|
||||
// ProtoColorToRGBA and RGBAToProtoColor are exact inverses, and both functions
|
||||
// will lose precision.
|
||||
func ProtoColorToRGBA(c *cpb.Color) *color.RGBA {
|
||||
// Determine the appropriate alpha value.
|
||||
// If alpha is unset, full opacity is the proper default.
|
||||
alpha := uint8(255)
|
||||
if c.Alpha != nil {
|
||||
alpha = uint8(math.Round(float64(c.GetAlpha().GetValue() * 255)))
|
||||
}
|
||||
|
||||
// Return the RGBA.
|
||||
return &color.RGBA{
|
||||
R: uint8(math.Round(float64(c.GetRed()) * 255)),
|
||||
G: uint8(math.Round(float64(c.GetGreen()) * 255)),
|
||||
B: uint8(math.Round(float64(c.GetBlue()) * 255)),
|
||||
A: alpha,
|
||||
}
|
||||
}
|
||||
|
||||
// RGBAToProtoColor returns a google.type.Color based on the provided RGBA.
|
||||
//
|
||||
// Note: Converting between ints using [0, 256) and a float using [0, 1]
|
||||
// causes some cognitive dissonance between accuracy and user expectations.
|
||||
// For example, most people using CSS use 0x80 (decimal 128) to mean "half",
|
||||
// but it is not actually half (it is slightly over). These is actually no
|
||||
// way to precisely specify the 0.5 float value in a [0, 256) range of
|
||||
// integers.
|
||||
//
|
||||
// This function addresses this by limiting decimal precision to 0.01, on
|
||||
// the rationale that most precision beyond this point is probably
|
||||
// unintentional.
|
||||
//
|
||||
// Because of this fuzziness and precision loss, it is NOT guaranteed that
|
||||
// ProtoColorToRGBA and RGBAToProtoColor are exact inverses, and both functions
|
||||
// will lose precision.
|
||||
func RGBAToProtoColor(rgba *color.RGBA) *cpb.Color {
|
||||
return &cpb.Color{
|
||||
Red: float32(int(rgba.R)*100/255) / 100,
|
||||
Green: float32(int(rgba.G)*100/255) / 100,
|
||||
Blue: float32(int(rgba.B)*100/255) / 100,
|
||||
Alpha: &wpb.FloatValue{Value: float32(int(rgba.A)*100/255) / 100},
|
||||
}
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
// 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
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
dpb "google.golang.org/genproto/googleapis/type/date"
|
||||
)
|
||||
|
||||
// ProtoDateToLocalTime returns a new Time based on the google.type.Date, in
|
||||
// the system's time zone.
|
||||
//
|
||||
// Hours, minues, seconds, and nanoseconds are set to 0.
|
||||
func ProtoDateToLocalTime(d *dpb.Date) time.Time {
|
||||
return ProtoDateToTime(d, time.Local)
|
||||
}
|
||||
|
||||
// ProtoDateToUTCTime returns a new Time based on the google.type.Date, in UTC.
|
||||
//
|
||||
// Hours, minutes, seconds, and nanoseconds are set to 0.
|
||||
func ProtoDateToUTCTime(d *dpb.Date) time.Time {
|
||||
return ProtoDateToTime(d, time.UTC)
|
||||
}
|
||||
|
||||
// ProtoDateToTime returns a new Time based on the google.type.Date and provided
|
||||
// *time.Location.
|
||||
//
|
||||
// Hours, minutes, seconds, and nanoseconds are set to 0.
|
||||
func ProtoDateToTime(d *dpb.Date, l *time.Location) time.Time {
|
||||
return time.Date(int(d.GetYear()), time.Month(d.GetMonth()), int(d.GetDay()), 0, 0, 0, 0, l)
|
||||
}
|
||||
|
||||
// TimeToProtoDate returns a new google.type.Date based on the provided time.Time.
|
||||
// The location is ignored, as is anything more precise than the day.
|
||||
func TimeToProtoDate(t time.Time) *dpb.Date {
|
||||
return &dpb.Date{
|
||||
Year: int32(t.Year()),
|
||||
Month: int32(t.Month()),
|
||||
Day: int32(t.Day()),
|
||||
}
|
||||
}
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
// 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
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
dtpb "google.golang.org/genproto/googleapis/type/datetime"
|
||||
durpb "google.golang.org/protobuf/types/known/durationpb"
|
||||
)
|
||||
|
||||
// ProtoDateTimeToTime returns a new Time based on the google.type.DateTime.
|
||||
//
|
||||
// It errors if it gets invalid time zone information.
|
||||
func ProtoDateTimeToTime(d *dtpb.DateTime) (time.Time, error) {
|
||||
var err error
|
||||
|
||||
// Determine the location.
|
||||
loc := time.UTC
|
||||
if tz := d.GetTimeZone(); tz != nil {
|
||||
loc, err = time.LoadLocation(tz.GetId())
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
}
|
||||
if offset := d.GetUtcOffset(); offset != nil {
|
||||
hours := int(offset.GetSeconds()) / 3600
|
||||
loc = time.FixedZone(fmt.Sprintf("UTC%+d", hours), hours)
|
||||
}
|
||||
|
||||
// Return the Time.
|
||||
return time.Date(
|
||||
int(d.GetYear()),
|
||||
time.Month(d.GetMonth()),
|
||||
int(d.GetDay()),
|
||||
int(d.GetHours()),
|
||||
int(d.GetMinutes()),
|
||||
int(d.GetSeconds()),
|
||||
int(d.GetNanos()),
|
||||
loc,
|
||||
), nil
|
||||
}
|
||||
|
||||
// TimeToProtoDateTime returns a new google.type.DateTime based on the
|
||||
// provided time.Time.
|
||||
//
|
||||
// It errors if it gets invalid time zone information.
|
||||
func TimeToProtoDateTime(t time.Time) (*dtpb.DateTime, error) {
|
||||
dt := &dtpb.DateTime{
|
||||
Year: int32(t.Year()),
|
||||
Month: int32(t.Month()),
|
||||
Day: int32(t.Day()),
|
||||
Hours: int32(t.Hour()),
|
||||
Minutes: int32(t.Minute()),
|
||||
Seconds: int32(t.Second()),
|
||||
Nanos: int32(t.Nanosecond()),
|
||||
}
|
||||
|
||||
// If the location is a UTC offset, encode it as such in the proto.
|
||||
loc := t.Location().String()
|
||||
if match := offsetRegexp.FindStringSubmatch(loc); len(match) > 0 {
|
||||
offsetInt, err := strconv.Atoi(match[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dt.TimeOffset = &dtpb.DateTime_UtcOffset{
|
||||
UtcOffset: &durpb.Duration{Seconds: int64(offsetInt) * 3600},
|
||||
}
|
||||
} else if loc != "" {
|
||||
dt.TimeOffset = &dtpb.DateTime_TimeZone{
|
||||
TimeZone: &dtpb.TimeZone{Id: loc},
|
||||
}
|
||||
}
|
||||
|
||||
return dt, nil
|
||||
}
|
||||
|
||||
var offsetRegexp = regexp.MustCompile(`^UTC([+-][\d]{1,2})$`)
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
// 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
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
dpb "google.golang.org/genproto/googleapis/type/decimal"
|
||||
)
|
||||
|
||||
// ProtoDecimalToFloat converts the provided google.type.Decimal to a big.Float.
|
||||
func ProtoDecimalToFloat(d *dpb.Decimal) (*big.Float, error) {
|
||||
value := strings.ToLower(d.GetValue())
|
||||
|
||||
// Determine the required precision.
|
||||
v := value
|
||||
if strings.ContainsRune(v, 'e') {
|
||||
v = v[0:strings.IndexRune(v, 'e')]
|
||||
}
|
||||
v = nan.ReplaceAllLiteralString(v, "")
|
||||
prec := uint(math.Pow(2, float64(len(v)+1)))
|
||||
|
||||
// Parse and return a big.Float.
|
||||
f, _, err := big.ParseFloat(value, 10, prec, big.AwayFromZero)
|
||||
return f, err
|
||||
}
|
||||
|
||||
// ProtoDecimalToFloat64 converts the provided google.type.Decimal to a float64.
|
||||
func ProtoDecimalToFloat64(d *dpb.Decimal) (float64, big.Accuracy, error) {
|
||||
f, err := ProtoDecimalToFloat(d)
|
||||
if err != nil {
|
||||
return 0.0, big.Exact, err
|
||||
}
|
||||
f64, accuracy := f.Float64()
|
||||
return f64, accuracy, nil
|
||||
}
|
||||
|
||||
// Float64ToProtoDecimal converts the provided float64 to a google.type.Decimal.
|
||||
func Float64ToProtoDecimal(f float64) *dpb.Decimal {
|
||||
return &dpb.Decimal{
|
||||
Value: fmt.Sprintf("%f", f),
|
||||
}
|
||||
}
|
||||
|
||||
// FloatToProtoDecimal converts the provided big.Float to a google.type.Decimal.
|
||||
func FloatToProtoDecimal(f *big.Float) *dpb.Decimal {
|
||||
return &dpb.Decimal{
|
||||
Value: f.String(),
|
||||
}
|
||||
}
|
||||
|
||||
var nan = regexp.MustCompile(`[^\d]`)
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
// 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
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// package adapters provides helper functions for the google.type protobuf
|
||||
// messages (Decimal, Fraction, etc.).
|
||||
package adapters
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
// 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
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
fpb "google.golang.org/genproto/googleapis/type/fraction"
|
||||
)
|
||||
|
||||
// ProtoFractionToRat returns a math/big Rat (rational number) based on the given
|
||||
// google.type.fraction.
|
||||
func ProtoFractionToRat(f *fpb.Fraction) *big.Rat {
|
||||
return big.NewRat(f.GetNumerator(), f.GetDenominator())
|
||||
}
|
||||
|
||||
// RatToProtoFraction returns a google.type.Fraction from a math/big Rat.
|
||||
func RatToProtoFraction(r *big.Rat) *fpb.Fraction {
|
||||
return &fpb.Fraction{
|
||||
Numerator: r.Num().Int64(),
|
||||
Denominator: r.Denom().Int64(),
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
// 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
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
mpb "google.golang.org/genproto/googleapis/type/month"
|
||||
)
|
||||
|
||||
// ToMonth converts a google.type.Month to a golang Month.
|
||||
func ToMonth(m mpb.Month) time.Month {
|
||||
return time.Month(m.Number())
|
||||
}
|
||||
|
||||
// ToProtoMonth converts a golang Month to a google.type.Month.
|
||||
func ToProtoMonth(m time.Month) mpb.Month {
|
||||
return mpb.Month(m)
|
||||
}
|
||||
Reference in New Issue
Block a user