podman

Форк
0
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.
28
package status
29

30
import (
31
	"context"
32
	"errors"
33
	"fmt"
34

35
	spb "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
45
type Status = status.Status
46

47
// New returns a Status representing c and msg.
48
func New(c codes.Code, msg string) *Status {
49
	return status.New(c, msg)
50
}
51

52
// Newf returns New(c, fmt.Sprintf(format, a...)).
53
func Newf(c codes.Code, format string, a ...any) *Status {
54
	return New(c, fmt.Sprintf(format, a...))
55
}
56

57
// Error returns an error representing c and msg.  If c is OK, returns nil.
58
func Error(c codes.Code, msg string) error {
59
	return New(c, msg).Err()
60
}
61

62
// Errorf returns Error(c, fmt.Sprintf(format, a...)).
63
func Errorf(c codes.Code, format string, a ...any) error {
64
	return Error(c, fmt.Sprintf(format, a...))
65
}
66

67
// ErrorProto returns an error representing s.  If s.Code is OK, returns nil.
68
func ErrorProto(s *spb.Status) error {
69
	return FromProto(s).Err()
70
}
71

72
// FromProto returns a Status representing s.
73
func FromProto(s *spb.Status) *Status {
74
	return 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.
96
func FromError(err error) (s *Status, ok bool) {
97
	if err == nil {
98
		return nil, true
99
	}
100
	type grpcstatus interface{ GRPCStatus() *Status }
101
	if gs, ok := err.(grpcstatus); ok {
102
		grpcStatus := gs.GRPCStatus()
103
		if 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.
108
			return New(codes.Unknown, err.Error()), false
109
		}
110
		return grpcStatus, true
111
	}
112
	var gs grpcstatus
113
	if errors.As(err, &gs) {
114
		grpcStatus := gs.GRPCStatus()
115
		if 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.
120
			return New(codes.Unknown, err.Error()), false
121
		}
122
		p := grpcStatus.Proto()
123
		p.Message = err.Error()
124
		return status.FromProto(p), true
125
	}
126
	return 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.
131
func Convert(err error) *Status {
132
	s, _ := FromError(err)
133
	return 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.
139
func Code(err error) codes.Code {
140
	// Don't use FromError to avoid allocation of OK status.
141
	if err == nil {
142
		return codes.OK
143
	}
144

145
	return 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.
151
func FromContextError(err error) *Status {
152
	if err == nil {
153
		return nil
154
	}
155
	if errors.Is(err, context.DeadlineExceeded) {
156
		return New(codes.DeadlineExceeded, err.Error())
157
	}
158
	if errors.Is(err, context.Canceled) {
159
		return New(codes.Canceled, err.Error())
160
	}
161
	return New(codes.Unknown, err.Error())
162
}
163

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.