Skip to content

Commit 4832e10

Browse files
authored
chore(internal/protoveneer): support Status (#10280)
Support the Status type from google.golang.org/genproto/googleapis/rpc/status. Convert it to `apierror.APIError`, which was designed to wrap it.
1 parent 4924efa commit 4832e10

File tree

7 files changed

+124
-1
lines changed

7 files changed

+124
-1
lines changed

internal/protoveneer/cmd/protoveneer/protoveneer.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ func buildConverterMap(typeInfos []*typeInfo, conf *config) (map[string]converte
263263

264264
// Add converters for used external types to the map.
265265
for _, et := range externalTypes {
266-
if et.used {
266+
if et.used && et.convertTo != "" {
267267
converters[et.qualifiedName] = customConverter{et.convertTo, et.convertFrom}
268268
}
269269
}
@@ -849,13 +849,23 @@ var externalTypes = []*externalType{
849849
convertTo: "timestamppb.New",
850850
convertFrom: "support.TimeFromProto",
851851
},
852+
{
853+
qualifiedName: "*apierror.APIError",
854+
replaces: "*status.Status",
855+
importPaths: []string{"github.com/googleapis/gax-go/v2/apierror"},
856+
convertTo: "support.APIErrorToProto",
857+
convertFrom: "support.APIErrorFromProto",
858+
},
852859
}
853860

854861
var protoTypeToExternalType = map[string]*externalType{}
855862

856863
func init() {
857864
var err error
858865
for _, et := range externalTypes {
866+
if et.replaces == "" {
867+
continue
868+
}
859869
et.typeExpr, err = parser.ParseExpr(et.qualifiedName)
860870
if err != nil {
861871
panic(err)

internal/protoveneer/cmd/protoveneer/testdata/basic/basic.pb.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package basic
1616

1717
import (
1818
_ "google.golang.org/genproto/googleapis/api/annotations"
19+
status "google.golang.org/genproto/googleapis/rpc/status"
1920
date "google.golang.org/genproto/googleapis/type/date"
2021
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
2122
"google.golang.org/protobuf/types/known/structpb"
@@ -133,3 +134,9 @@ type Pop struct {
133134
X int
134135
Y unexported
135136
}
137+
138+
// Status converts to itself.
139+
140+
type File struct {
141+
Error *status.Status
142+
}

internal/protoveneer/cmd/protoveneer/testdata/basic/golden

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"cloud.google.com/go/civil"
99
pb "example.com/basic"
1010
"example.com/protoveneer/support"
11+
"github.com/googleapis/gax-go/v2/apierror"
1112
"google.golang.org/protobuf/types/known/timestamppb"
1213
"time"
1314
)
@@ -103,6 +104,28 @@ func (CitationMetadata) fromProto(p *pb.CitationMetadata) *CitationMetadata {
103104
}
104105
}
105106

107+
type File struct {
108+
Error *apierror.APIError
109+
}
110+
111+
func (v *File) toProto() *pb.File {
112+
if v == nil {
113+
return nil
114+
}
115+
return &pb.File{
116+
Error: support.APIErrorToProto(v.Error),
117+
}
118+
}
119+
120+
func (File) fromProto(p *pb.File) *File {
121+
if p == nil {
122+
return nil
123+
}
124+
return &File{
125+
Error: support.APIErrorFromProto(p.Error),
126+
}
127+
}
128+
106129
// FinishReason is the reason why the model stopped generating tokens.
107130
// If empty, the model has not stopped generating the tokens.
108131
type FinishReason int32

internal/protoveneer/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@ go 1.20
55
require (
66
cloud.google.com/go v0.114.0
77
github.com/google/go-cmp v0.6.0
8+
github.com/googleapis/gax-go/v2 v2.12.4
89
google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda
10+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8
11+
google.golang.org/grpc v1.64.0
912
google.golang.org/protobuf v1.34.1
1013
gopkg.in/yaml.v3 v3.0.1
1114
)
1215

1316
require (
1417
github.com/kr/pretty v0.3.1 // indirect
1518
github.com/rogpeppe/go-internal v1.12.0 // indirect
19+
golang.org/x/sys v0.20.0 // indirect
20+
google.golang.org/api v0.180.0 // indirect
1621
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
1722
)

internal/protoveneer/go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J
33
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
44
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
55
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
6+
github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg=
7+
github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI=
68
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
79
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
810
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -14,8 +16,18 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
1416
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
1517
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
1618
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
19+
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
20+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
21+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
22+
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
23+
google.golang.org/api v0.180.0 h1:M2D87Yo0rGBPWpo1orwfCLehUUL6E7/TYe5gvMQWDh4=
24+
google.golang.org/api v0.180.0/go.mod h1:51AiyoEg1MJPSZ9zvklA8VnRILPXxn1iVen9v25XHAE=
1725
google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw=
1826
google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw=
27+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA=
28+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
29+
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
30+
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
1931
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
2032
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
2133
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

internal/protoveneer/support/support.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import (
2020
"time"
2121

2222
"cloud.google.com/go/civil"
23+
"github.com/googleapis/gax-go/v2/apierror"
24+
spb "google.golang.org/genproto/googleapis/rpc/status"
2325
"google.golang.org/genproto/googleapis/type/date"
26+
gstatus "google.golang.org/grpc/status"
2427
"google.golang.org/protobuf/types/known/structpb"
2528
"google.golang.org/protobuf/types/known/timestamppb"
2629
)
@@ -119,3 +122,22 @@ func TimeFromProto(ts *timestamppb.Timestamp) time.Time {
119122
}
120123
return ts.AsTime()
121124
}
125+
126+
// APIErrorToProto converts an APIError to a proto Status.
127+
func APIErrorToProto(ae *apierror.APIError) *spb.Status {
128+
if ae == nil {
129+
return nil
130+
}
131+
return ae.GRPCStatus().Proto()
132+
}
133+
134+
// APIErrorFromProto converts a proto Status to an APIError.
135+
func APIErrorFromProto(s *spb.Status) *apierror.APIError {
136+
err := gstatus.ErrorProto(s)
137+
aerr, ok := apierror.ParseError(err, true)
138+
if !ok {
139+
// Should be impossible.
140+
return nil
141+
}
142+
return aerr
143+
}

internal/protoveneer/support/support_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ import (
1818
"reflect"
1919
"strconv"
2020
"testing"
21+
22+
"github.com/google/go-cmp/cmp"
23+
"github.com/google/go-cmp/cmp/cmpopts"
24+
"google.golang.org/genproto/googleapis/rpc/errdetails"
25+
spb "google.golang.org/genproto/googleapis/rpc/status"
26+
"google.golang.org/protobuf/types/known/anypb"
2127
)
2228

2329
func TestTransformMapValues(t *testing.T) {
@@ -33,3 +39,41 @@ func TestTransformMapValues(t *testing.T) {
3339
t.Errorf("got %v, want %v", got, want)
3440
}
3541
}
42+
43+
func TestAPIError(t *testing.T) {
44+
const (
45+
code = 3 // gRPC "invalid argument"
46+
msg = "message"
47+
reason = "reason"
48+
)
49+
ei := &errdetails.ErrorInfo{Reason: reason}
50+
pbany, err := anypb.New(ei)
51+
if err != nil {
52+
t.Fatal(err)
53+
}
54+
s := &spb.Status{
55+
Code: code,
56+
Message: msg,
57+
Details: []*anypb.Any{pbany},
58+
}
59+
60+
ae := APIErrorFromProto(s)
61+
if ae == nil {
62+
t.Fatal("got nil")
63+
}
64+
gs := ae.GRPCStatus()
65+
if g := gs.Code(); g != code {
66+
t.Errorf("got %d, want %d", g, code)
67+
}
68+
if g := gs.Message(); g != msg {
69+
t.Errorf("got %q, want %q", g, msg)
70+
}
71+
if g := ae.Reason(); g != reason {
72+
t.Errorf("got %q, want %q", g, reason)
73+
}
74+
75+
gps := APIErrorToProto(ae)
76+
if !cmp.Equal(gps, s, cmpopts.IgnoreUnexported(spb.Status{}, anypb.Any{})) {
77+
t.Errorf("\ngot %s\nwant %s", gps, s)
78+
}
79+
}

0 commit comments

Comments
 (0)