mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit with typed errors support
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
203
vendor/github.com/moby/buildkit/util/grpcerrors/grpcerrors.go
generated
vendored
Normal file
203
vendor/github.com/moby/buildkit/util/grpcerrors/grpcerrors.go
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
package grpcerrors
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/containerd/typeurl"
|
||||
gogotypes "github.com/gogo/protobuf/types"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/moby/buildkit/util/stack"
|
||||
"github.com/sirupsen/logrus"
|
||||
spb "google.golang.org/genproto/googleapis/rpc/status"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type TypedError interface {
|
||||
ToProto() TypedErrorProto
|
||||
}
|
||||
|
||||
type TypedErrorProto interface {
|
||||
proto.Message
|
||||
WrapError(error) error
|
||||
}
|
||||
|
||||
func ToGRPC(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
st, ok := AsGRPCStatus(err)
|
||||
if !ok || st == nil {
|
||||
st = status.New(Code(err), err.Error())
|
||||
}
|
||||
if st.Code() != Code(err) {
|
||||
pb := st.Proto()
|
||||
pb.Code = int32(Code(err))
|
||||
st = status.FromProto(pb)
|
||||
}
|
||||
|
||||
var details []proto.Message
|
||||
|
||||
for _, st := range stack.Traces(err) {
|
||||
details = append(details, st)
|
||||
}
|
||||
|
||||
each(err, func(err error) {
|
||||
if te, ok := err.(TypedError); ok {
|
||||
details = append(details, te.ToProto())
|
||||
}
|
||||
})
|
||||
|
||||
if len(details) > 0 {
|
||||
if st2, err := withDetails(st, details...); err == nil {
|
||||
st = st2
|
||||
}
|
||||
}
|
||||
|
||||
return st.Err()
|
||||
}
|
||||
|
||||
func withDetails(s *status.Status, details ...proto.Message) (*status.Status, error) {
|
||||
if s.Code() == codes.OK {
|
||||
return nil, errors.New("no error details for status with code OK")
|
||||
}
|
||||
p := s.Proto()
|
||||
for _, detail := range details {
|
||||
url, err := typeurl.TypeURL(detail)
|
||||
if err != nil {
|
||||
logrus.Warnf("ignoring typed error %T: not registered", detail)
|
||||
continue
|
||||
}
|
||||
dt, err := json.Marshal(detail)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Details = append(p.Details, &any.Any{TypeUrl: url, Value: dt})
|
||||
}
|
||||
return status.FromProto(p), nil
|
||||
}
|
||||
|
||||
func Code(err error) codes.Code {
|
||||
if se, ok := err.(interface {
|
||||
Code() codes.Code
|
||||
}); ok {
|
||||
return se.Code()
|
||||
}
|
||||
|
||||
if se, ok := err.(interface {
|
||||
GRPCStatus() *status.Status
|
||||
}); ok {
|
||||
return se.GRPCStatus().Code()
|
||||
}
|
||||
|
||||
wrapped, ok := err.(interface {
|
||||
Unwrap() error
|
||||
})
|
||||
if ok {
|
||||
return Code(wrapped.Unwrap())
|
||||
}
|
||||
|
||||
return status.FromContextError(err).Code()
|
||||
}
|
||||
|
||||
func WrapCode(err error, code codes.Code) error {
|
||||
return &withCode{error: err, code: code}
|
||||
}
|
||||
|
||||
func AsGRPCStatus(err error) (*status.Status, bool) {
|
||||
if err == nil {
|
||||
return nil, true
|
||||
}
|
||||
if se, ok := err.(interface {
|
||||
GRPCStatus() *status.Status
|
||||
}); ok {
|
||||
return se.GRPCStatus(), true
|
||||
}
|
||||
|
||||
wrapped, ok := err.(interface {
|
||||
Unwrap() error
|
||||
})
|
||||
if ok {
|
||||
return AsGRPCStatus(wrapped.Unwrap())
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func FromGRPC(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
st, ok := status.FromError(err)
|
||||
if !ok {
|
||||
return err
|
||||
}
|
||||
|
||||
pb := st.Proto()
|
||||
|
||||
n := &spb.Status{
|
||||
Code: pb.Code,
|
||||
Message: pb.Message,
|
||||
}
|
||||
|
||||
details := make([]TypedErrorProto, 0, len(pb.Details))
|
||||
stacks := make([]*stack.Stack, 0, len(pb.Details))
|
||||
|
||||
// details that we don't understand are copied as proto
|
||||
for _, d := range pb.Details {
|
||||
m, err := typeurl.UnmarshalAny(gogoAny(d))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
switch v := m.(type) {
|
||||
case *stack.Stack:
|
||||
stacks = append(stacks, v)
|
||||
case TypedErrorProto:
|
||||
details = append(details, v)
|
||||
default:
|
||||
n.Details = append(n.Details, d)
|
||||
}
|
||||
}
|
||||
|
||||
err = status.FromProto(n).Err()
|
||||
|
||||
for _, s := range stacks {
|
||||
if s != nil {
|
||||
err = stack.Wrap(err, *s)
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range details {
|
||||
err = d.WrapError(err)
|
||||
}
|
||||
|
||||
return stack.Enable(err)
|
||||
}
|
||||
|
||||
type withCode struct {
|
||||
code codes.Code
|
||||
error
|
||||
}
|
||||
|
||||
func (e *withCode) Unwrap() error {
|
||||
return e.error
|
||||
}
|
||||
|
||||
func each(err error, fn func(error)) {
|
||||
fn(err)
|
||||
if wrapped, ok := err.(interface {
|
||||
Unwrap() error
|
||||
}); ok {
|
||||
each(wrapped.Unwrap(), fn)
|
||||
}
|
||||
}
|
||||
|
||||
func gogoAny(in *any.Any) *gogotypes.Any {
|
||||
return &gogotypes.Any{
|
||||
TypeUrl: in.TypeUrl,
|
||||
Value: in.Value,
|
||||
}
|
||||
}
|
28
vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go
generated
vendored
Normal file
28
vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
package grpcerrors
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
resp, err = handler(ctx, req)
|
||||
if err != nil {
|
||||
err = ToGRPC(err)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
return ToGRPC(handler(srv, ss))
|
||||
}
|
||||
|
||||
func UnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
return FromGRPC(invoker(ctx, method, req, reply, cc, opts...))
|
||||
}
|
||||
|
||||
func StreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
s, err := streamer(ctx, desc, cc, method, opts...)
|
||||
return s, ToGRPC(err)
|
||||
}
|
Reference in New Issue
Block a user