podman
162 строки · 5.4 Кб
1/*
2*
3* Copyright 2017 gRPC authors.
4*
5* Licensed under the Apache License, Version 2.0 (the "License");
6* you may not use this file except in compliance with the License.
7* You may obtain a copy of the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS,
13* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14* See the License for the specific language governing permissions and
15* limitations under the License.
16*
17*/
18
19// Package status implements errors returned by gRPC. These errors are
20// serialized and transmitted on the wire between server and client, and allow
21// for additional data to be transmitted via the Details field in the status
22// proto. gRPC service handlers should return an error created by this
23// package, and gRPC clients should expect a corresponding error to be
24// returned from the RPC call.
25//
26// This package upholds the invariants that a non-nil error may not
27// contain an OK code, and an OK code must result in a nil error.
28package status
29
30import (
31"context"
32"errors"
33"fmt"
34
35spb "google.golang.org/genproto/googleapis/rpc/status"
36
37"google.golang.org/grpc/codes"
38"google.golang.org/grpc/internal/status"
39)
40
41// Status references google.golang.org/grpc/internal/status. It represents an
42// RPC status code, message, and details. It is immutable and should be
43// created with New, Newf, or FromProto.
44// https://godoc.org/google.golang.org/grpc/internal/status
45type Status = status.Status
46
47// New returns a Status representing c and msg.
48func New(c codes.Code, msg string) *Status {
49return status.New(c, msg)
50}
51
52// Newf returns New(c, fmt.Sprintf(format, a...)).
53func Newf(c codes.Code, format string, a ...any) *Status {
54return New(c, fmt.Sprintf(format, a...))
55}
56
57// Error returns an error representing c and msg. If c is OK, returns nil.
58func Error(c codes.Code, msg string) error {
59return New(c, msg).Err()
60}
61
62// Errorf returns Error(c, fmt.Sprintf(format, a...)).
63func Errorf(c codes.Code, format string, a ...any) error {
64return Error(c, fmt.Sprintf(format, a...))
65}
66
67// ErrorProto returns an error representing s. If s.Code is OK, returns nil.
68func ErrorProto(s *spb.Status) error {
69return FromProto(s).Err()
70}
71
72// FromProto returns a Status representing s.
73func FromProto(s *spb.Status) *Status {
74return status.FromProto(s)
75}
76
77// FromError returns a Status representation of err.
78//
79// - If err was produced by this package or implements the method `GRPCStatus()
80// *Status` and `GRPCStatus()` does not return nil, or if err wraps a type
81// satisfying this, the Status from `GRPCStatus()` is returned. For wrapped
82// errors, the message returned contains the entire err.Error() text and not
83// just the wrapped status. In that case, ok is true.
84//
85// - If err is nil, a Status is returned with codes.OK and no message, and ok
86// is true.
87//
88// - If err implements the method `GRPCStatus() *Status` and `GRPCStatus()`
89// returns nil (which maps to Codes.OK), or if err wraps a type
90// satisfying this, a Status is returned with codes.Unknown and err's
91// Error() message, and ok is false.
92//
93// - Otherwise, err is an error not compatible with this package. In this
94// case, a Status is returned with codes.Unknown and err's Error() message,
95// and ok is false.
96func FromError(err error) (s *Status, ok bool) {
97if err == nil {
98return nil, true
99}
100type grpcstatus interface{ GRPCStatus() *Status }
101if gs, ok := err.(grpcstatus); ok {
102grpcStatus := gs.GRPCStatus()
103if grpcStatus == nil {
104// Error has status nil, which maps to codes.OK. There
105// is no sensible behavior for this, so we turn it into
106// an error with codes.Unknown and discard the existing
107// status.
108return New(codes.Unknown, err.Error()), false
109}
110return grpcStatus, true
111}
112var gs grpcstatus
113if errors.As(err, &gs) {
114grpcStatus := gs.GRPCStatus()
115if grpcStatus == nil {
116// Error wraps an error that has status nil, which maps
117// to codes.OK. There is no sensible behavior for this,
118// so we turn it into an error with codes.Unknown and
119// discard the existing status.
120return New(codes.Unknown, err.Error()), false
121}
122p := grpcStatus.Proto()
123p.Message = err.Error()
124return status.FromProto(p), true
125}
126return New(codes.Unknown, err.Error()), false
127}
128
129// Convert is a convenience function which removes the need to handle the
130// boolean return value from FromError.
131func Convert(err error) *Status {
132s, _ := FromError(err)
133return s
134}
135
136// Code returns the Code of the error if it is a Status error or if it wraps a
137// Status error. If that is not the case, it returns codes.OK if err is nil, or
138// codes.Unknown otherwise.
139func Code(err error) codes.Code {
140// Don't use FromError to avoid allocation of OK status.
141if err == nil {
142return codes.OK
143}
144
145return Convert(err).Code()
146}
147
148// FromContextError converts a context error or wrapped context error into a
149// Status. It returns a Status with codes.OK if err is nil, or a Status with
150// codes.Unknown if err is non-nil and not a context error.
151func FromContextError(err error) *Status {
152if err == nil {
153return nil
154}
155if errors.Is(err, context.DeadlineExceeded) {
156return New(codes.DeadlineExceeded, err.Error())
157}
158if errors.Is(err, context.Canceled) {
159return New(codes.Canceled, err.Error())
160}
161return New(codes.Unknown, err.Error())
162}
163