From da65825c5ffee0517fab4ddfd87326c15ebf6955 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Tue, 30 Jul 2024 13:16:16 +0300 Subject: [PATCH] Storage: Consolidate error handling (#91167) --- Makefile | 2 +- pkg/registry/apis/dashboard/legacy/storage.go | 57 ++- pkg/registry/apis/dashboard/sub_dto.go | 6 +- pkg/storage/unified/apistore/store.go | 21 +- pkg/storage/unified/apistore/util.go | 30 -- .../unified/entitybridge/entitybridge.go | 16 +- pkg/storage/unified/resource/cdk_backend.go | 36 +- pkg/storage/unified/resource/errors.go | 106 +++++ pkg/storage/unified/resource/noop.go | 14 +- pkg/storage/unified/resource/resource.pb.go | 401 ++++++++++-------- pkg/storage/unified/resource/resource.proto | 9 + pkg/storage/unified/resource/server.go | 121 ++---- pkg/storage/unified/sql/backend.go | 41 +- .../unified/sql/test/integration_test.go | 28 +- 14 files changed, 489 insertions(+), 399 deletions(-) create mode 100644 pkg/storage/unified/resource/errors.go diff --git a/Makefile b/Makefile index 74adf508aa4..fb75f2b7b84 100644 --- a/Makefile +++ b/Makefile @@ -382,7 +382,7 @@ devenv-mysql: protobuf: ## Compile protobuf definitions bash scripts/protobuf-check.sh go install google.golang.org/protobuf/cmd/protoc-gen-go - go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.4.0 buf generate pkg/plugins/backendplugin/pluginextensionv2 --template pkg/plugins/backendplugin/pluginextensionv2/buf.gen.yaml buf generate pkg/plugins/backendplugin/secretsmanagerplugin --template pkg/plugins/backendplugin/secretsmanagerplugin/buf.gen.yaml buf generate pkg/services/store/entity --template pkg/services/store/entity/buf.gen.yaml diff --git a/pkg/registry/apis/dashboard/legacy/storage.go b/pkg/registry/apis/dashboard/legacy/storage.go index 21711f30b96..4c3a87a7c37 100644 --- a/pkg/registry/apis/dashboard/legacy/storage.go +++ b/pkg/registry/apis/dashboard/legacy/storage.go @@ -122,13 +122,15 @@ func (a *dashboardSqlAccess) GetDashboard(ctx context.Context, orgId int64, uid } // Read implements ResourceStoreServer. -func (a *dashboardSqlAccess) Read(ctx context.Context, req *resource.ReadRequest) (*resource.ReadResponse, error) { +func (a *dashboardSqlAccess) ReadResource(ctx context.Context, req *resource.ReadRequest) *resource.ReadResponse { + rsp := &resource.ReadResponse{} info, err := request.ParseNamespace(req.Key.Namespace) if err == nil { err = isDashboardKey(req.Key, true) } if err != nil { - return nil, err + rsp.Error = resource.AsErrorResult(err) + return rsp } version := int64(0) if req.ResourceVersion > 0 { @@ -137,40 +139,44 @@ func (a *dashboardSqlAccess) Read(ctx context.Context, req *resource.ReadRequest dash, rv, err := a.GetDashboard(ctx, info.OrgID, req.Key.Name, version) if err != nil { - return nil, err + rsp.Error = resource.AsErrorResult(err) + return rsp } if dash == nil { - return &resource.ReadResponse{ - Error: &resource.ErrorResult{ - Code: http.StatusNotFound, - }, - }, err + rsp.Error = &resource.ErrorResult{ + Code: http.StatusNotFound, + } } - value, err := json.Marshal(dash) - return &resource.ReadResponse{ - ResourceVersion: rv, - Value: value, - }, err + rsp.ResourceVersion = rv + rsp.Value, err = json.Marshal(dash) + if err != nil { + rsp.Error = resource.AsErrorResult(err) + } + return rsp } // List implements AppendingStore. -func (a *dashboardSqlAccess) PrepareList(ctx context.Context, req *resource.ListRequest) (*resource.ListResponse, error) { +func (a *dashboardSqlAccess) PrepareList(ctx context.Context, req *resource.ListRequest) *resource.ListResponse { + list := &resource.ListResponse{} opts := req.Options info, err := request.ParseNamespace(opts.Key.Namespace) if err == nil { err = isDashboardKey(opts.Key, false) } if err != nil { - return nil, err + list.Error = resource.AsErrorResult(err) + return list } token, err := readContinueToken(req.NextPageToken) if err != nil { - return nil, err + list.Error = resource.AsErrorResult(err) + return list } if token.orgId > 0 && token.orgId != info.OrgID { - return nil, fmt.Errorf("token and orgID mismatch") + list.Error = resource.NewBadRequestError("token and orgID mismatch") + return list } query := &DashboardQuery{ @@ -183,16 +189,17 @@ func (a *dashboardSqlAccess) PrepareList(ctx context.Context, req *resource.List rows, limit, err := a.getRows(ctx, query) if err != nil { - return nil, err + list.Error = resource.AsErrorResult(err) + return list } defer func() { _ = rows.Close() }() totalSize := 0 - list := &resource.ListResponse{} for { row, err := rows.Next() if err != nil || row == nil { - return list, err + list.Error = resource.AsErrorResult(err) + return list } totalSize += row.Bytes @@ -201,12 +208,13 @@ func (a *dashboardSqlAccess) PrepareList(ctx context.Context, req *resource.List // row.token.folder = *query.Requirements.Folder // } list.NextPageToken = row.token.String() // will skip this one but start here next time - return list, err + return list } // TODO -- make it smaller and stick the body as an annotation... val, err := json.Marshal(row.Dash) if err != nil { - return list, err + list.Error = resource.AsErrorResult(err) + return list } list.Items = append(list.Items, &resource.ResourceWrapper{ ResourceVersion: row.RV, @@ -247,6 +255,11 @@ func (a *dashboardSqlAccess) WatchWriteEvents(ctx context.Context) (<-chan *reso return stream, nil } +// Simple wrapper for index implementation +func (a *dashboardSqlAccess) Read(ctx context.Context, req *resource.ReadRequest) (*resource.ReadResponse, error) { + return a.ReadResource(ctx, req), nil +} + func (a *dashboardSqlAccess) History(ctx context.Context, req *resource.HistoryRequest) (*resource.HistoryResponse, error) { info, err := request.ParseNamespace(req.Key.Namespace) if err == nil { diff --git a/pkg/registry/apis/dashboard/sub_dto.go b/pkg/registry/apis/dashboard/sub_dto.go index 0b3a18c1e28..cba01d2724b 100644 --- a/pkg/registry/apis/dashboard/sub_dto.go +++ b/pkg/registry/apis/dashboard/sub_dto.go @@ -99,9 +99,9 @@ func (r *DTOConnector) Connect(ctx context.Context, name string, opts runtime.Ob Name: name, } store := r.builder.legacy.access - rsp, err := store.Read(ctx, &resource.ReadRequest{Key: key}) - if err != nil { - return nil, err + rsp := store.ReadResource(ctx, &resource.ReadRequest{Key: key}) + if rsp.Error != nil { + return nil, resource.GetError(rsp.Error) } dash := &dashboard.Dashboard{} err = json.Unmarshal(rsp.Value, dash) diff --git a/pkg/storage/unified/apistore/store.go b/pkg/storage/unified/apistore/store.go index f81f3b2e198..b7f368d4308 100644 --- a/pkg/storage/unified/apistore/store.go +++ b/pkg/storage/unified/apistore/store.go @@ -143,7 +143,7 @@ func (s *Storage) Create(ctx context.Context, key string, obj runtime.Object, ou if rsp.Error.Code == http.StatusConflict { return storage.NewKeyExistsError(key, 0) } - return fmt.Errorf("other error %+v", rsp.Error) + return resource.GetError(rsp.Error) } if err := copyModifiedObjectToDestination(obj, out); err != nil { @@ -220,9 +220,8 @@ func (s *Storage) Delete( if err != nil { return err } - err = errorWrap(rsp.Error) - if err != nil { - return err + if rsp.Error != nil { + return resource.GetError(rsp.Error) } if err := s.versioner.UpdateObject(out, uint64(rsp.ResourceVersion)); err != nil { return err @@ -385,6 +384,9 @@ func (s *Storage) Watch(ctx context.Context, key string, opts storage.ListOption if err != nil { return nil, err } + if rsp.Error != nil { + return nil, resource.GetError(rsp.Error) + } maybeUpdatedRV = uint64(rsp.ResourceVersion) if maybeUpdatedRV < 1 { return nil, fmt.Errorf("expecting a non-zero resource version") @@ -430,7 +432,7 @@ func (s *Storage) Get(ctx context.Context, key string, opts storage.GetOptions, } return storage.NewKeyNotFoundError(key, req.ResourceVersion) } - return errorWrap(rsp.Error) + return resource.GetError(rsp.Error) } _, _, err = s.codec.Decode(rsp.Value, nil, objPtr) @@ -461,6 +463,9 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti if err != nil { return err } + if rsp.Error != nil { + return resource.GetError(rsp.Error) + } if err := s.validateMinimumResourceVersion(opts.ResourceVersion, uint64(rsp.ResourceVersion)); err != nil { return err @@ -573,7 +578,7 @@ func (s *Storage) GuaranteedUpdate( return apierrors.NewNotFound(s.gr, req.Key.Name) } } else { - return fmt.Errorf("read error %+v", rsp.Error) + return resource.GetError(rsp.Error) } } @@ -637,7 +642,7 @@ func (s *Storage) GuaranteedUpdate( return err } if rsp2.Error != nil { - return fmt.Errorf("backend update error: %+v", rsp2.Error) + return resource.GetError(rsp2.Error) } rv = rsp2.ResourceVersion } else { @@ -650,7 +655,7 @@ func (s *Storage) GuaranteedUpdate( return err } if rsp2.Error != nil { - return fmt.Errorf("backend update error: %+v", rsp2.Error) + return resource.GetError(rsp2.Error) } rv = rsp2.ResourceVersion } diff --git a/pkg/storage/unified/apistore/util.go b/pkg/storage/unified/apistore/util.go index 90eb40412e8..b760cd76fed 100644 --- a/pkg/storage/unified/apistore/util.go +++ b/pkg/storage/unified/apistore/util.go @@ -14,42 +14,12 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/storage" grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic" "github.com/grafana/grafana/pkg/storage/unified/resource" ) -func errorWrap(status *resource.ErrorResult) error { - if status != nil { - err := &apierrors.StatusError{ErrStatus: metav1.Status{ - Status: metav1.StatusFailure, - Code: status.Code, - Reason: metav1.StatusReason(status.Reason), - Message: status.Message, - }} - if status.Details != nil { - err.ErrStatus.Details = &metav1.StatusDetails{ - Group: status.Details.Group, - Kind: status.Details.Kind, - Name: status.Details.Name, - UID: types.UID(status.Details.Uid), - RetryAfterSeconds: status.Details.RetryAfterSeconds, - } - for _, c := range status.Details.Causes { - err.ErrStatus.Details.Causes = append(err.ErrStatus.Details.Causes, metav1.StatusCause{ - Type: metav1.CauseType(c.Reason), - Message: c.Message, - Field: c.Field, - }) - } - } - return err - } - return nil -} - func toListRequest(k *resource.ResourceKey, opts storage.ListOptions) (*resource.ListRequest, storage.SelectionPredicate, error) { predicate := opts.Predicate req := &resource.ListRequest{ diff --git a/pkg/storage/unified/entitybridge/entitybridge.go b/pkg/storage/unified/entitybridge/entitybridge.go index 98a96a18311..b63c4885d76 100644 --- a/pkg/storage/unified/entitybridge/entitybridge.go +++ b/pkg/storage/unified/entitybridge/entitybridge.go @@ -183,22 +183,24 @@ func (b *entityBridge) IsHealthy(ctx context.Context, req *resource.HealthCheckR } // Read implements ResourceServer. -func (b *entityBridge) Read(ctx context.Context, req *resource.ReadRequest) (*resource.ReadResponse, error) { +func (b *entityBridge) ReadResource(ctx context.Context, req *resource.ReadRequest) *resource.ReadResponse { v, err := b.client.Read(ctx, &entity.ReadEntityRequest{ Key: toEntityKey(req.Key), WithBody: true, }) if err != nil { - return nil, err + return &resource.ReadResponse{ + Error: resource.AsErrorResult(err), + } } return &resource.ReadResponse{ ResourceVersion: v.ResourceVersion, Value: v.Body, - }, nil + } } // List implements ResourceServer. -func (b *entityBridge) PrepareList(ctx context.Context, req *resource.ListRequest) (*resource.ListResponse, error) { +func (b *entityBridge) PrepareList(ctx context.Context, req *resource.ListRequest) *resource.ListResponse { key := req.Options.Key query := &entity.EntityListRequest{ NextPageToken: req.NextPageToken, @@ -221,7 +223,9 @@ func (b *entityBridge) PrepareList(ctx context.Context, req *resource.ListReques found, err := b.client.List(ctx, query) if err != nil { - return nil, err + return &resource.ListResponse{ + Error: resource.AsErrorResult(err), + } } rsp := &resource.ListResponse{ @@ -234,5 +238,5 @@ func (b *entityBridge) PrepareList(ctx context.Context, req *resource.ListReques Value: item.Body, }) } - return rsp, nil + return rsp } diff --git a/pkg/storage/unified/resource/cdk_backend.go b/pkg/storage/unified/resource/cdk_backend.go index ca1f7705b18..a5a16bab586 100644 --- a/pkg/storage/unified/resource/cdk_backend.go +++ b/pkg/storage/unified/resource/cdk_backend.go @@ -18,10 +18,8 @@ import ( "gocloud.dev/blob" _ "gocloud.dev/blob/fileblob" _ "gocloud.dev/blob/memblob" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" ) type CDKBackendOptions struct { @@ -135,7 +133,7 @@ func (s *cdkBackend) WriteEvent(ctx context.Context, event WriteEvent) (rv int64 return rv, err } -func (s *cdkBackend) Read(ctx context.Context, req *ReadRequest) (*ReadResponse, error) { +func (s *cdkBackend) ReadResource(ctx context.Context, req *ReadRequest) *ReadResponse { rv := req.ResourceVersion path := s.getPath(req.Key, rv) @@ -163,15 +161,15 @@ func (s *cdkBackend) Read(ctx context.Context, req *ReadRequest) (*ReadResponse, raw, err := s.bucket.ReadAll(ctx, path) if raw == nil && req.ResourceVersion > 0 { if req.ResourceVersion > s.rv.Load() { - return nil, &apierrors.StatusError{ - ErrStatus: metav1.Status{ - Reason: metav1.StatusReasonTimeout, // match etcd behavior + return &ReadResponse{ + Error: &ErrorResult{ Code: http.StatusGatewayTimeout, + Reason: string(metav1.StatusReasonTimeout), // match etcd behavior Message: "ResourceVersion is larger than max", - Details: &metav1.StatusDetails{ - Causes: []metav1.StatusCause{ + Details: &ErrorDetails{ + Causes: []*ErrorCause{ { - Type: metav1.CauseTypeResourceVersionTooLarge, + Reason: string(metav1.CauseTypeResourceVersionTooLarge), Message: fmt.Sprintf("requested: %d, current %d", req.ResourceVersion, s.rv.Load()), }, }, @@ -181,7 +179,7 @@ func (s *cdkBackend) Read(ctx context.Context, req *ReadRequest) (*ReadResponse, } // If the there was an explicit request, get the latest - rsp, _ := s.Read(ctx, &ReadRequest{Key: req.Key}) + rsp := s.ReadResource(ctx, &ReadRequest{Key: req.Key}) if rsp != nil && len(rsp.Value) > 0 { raw = rsp.Value rv = rsp.ResourceVersion @@ -192,15 +190,12 @@ func (s *cdkBackend) Read(ctx context.Context, req *ReadRequest) (*ReadResponse, raw = nil } if raw == nil { - return nil, apierrors.NewNotFound(schema.GroupResource{ - Group: req.Key.Group, - Resource: req.Key.Resource, - }, req.Key.Name) + return &ReadResponse{Error: NewNotFoundError(req.Key)} } return &ReadResponse{ ResourceVersion: rv, Value: raw, - }, err + } } func isDeletedMarker(raw []byte) bool { @@ -214,10 +209,12 @@ func isDeletedMarker(raw []byte) bool { return false } -func (s *cdkBackend) PrepareList(ctx context.Context, req *ListRequest) (*ListResponse, error) { +func (s *cdkBackend) PrepareList(ctx context.Context, req *ListRequest) *ListResponse { resources, err := buildTree(ctx, s, req.Options.Key) if err != nil { - return nil, err + return &ListResponse{ + Error: AsErrorResult(err), + } } rsp := &ListResponse{ @@ -227,7 +224,8 @@ func (s *cdkBackend) PrepareList(ctx context.Context, req *ListRequest) (*ListRe latest := item.versions[0] raw, err := s.bucket.ReadAll(ctx, latest.key) if err != nil { - return nil, err + rsp.Error = AsErrorResult(err) + return rsp } if !isDeletedMarker(raw) { rsp.Items = append(rsp.Items, &ResourceWrapper{ @@ -236,7 +234,7 @@ func (s *cdkBackend) PrepareList(ctx context.Context, req *ListRequest) (*ListRe }) } } - return rsp, nil + return rsp } func (s *cdkBackend) WatchWriteEvents(ctx context.Context) (<-chan *WrittenEvent, error) { diff --git a/pkg/storage/unified/resource/errors.go b/pkg/storage/unified/resource/errors.go new file mode 100644 index 00000000000..088e6683630 --- /dev/null +++ b/pkg/storage/unified/resource/errors.go @@ -0,0 +1,106 @@ +package resource + +import ( + "errors" + "net/http" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// Package-level errors. +var ( + ErrOptimisticLockingFailed = errors.New("optimistic locking failed") + ErrUserNotFoundInContext = errors.New("user not found in context") + ErrNotImplementedYet = errors.New("not implemented yet") +) + +func NewBadRequestError(msg string) *ErrorResult { + return &ErrorResult{ + Message: msg, + Code: http.StatusBadRequest, + Reason: string(metav1.StatusReasonBadRequest), + } +} + +func NewNotFoundError(key *ResourceKey) *ErrorResult { + return &ErrorResult{ + Code: http.StatusNotFound, + Details: &ErrorDetails{ + Group: key.Group, + Kind: key.Resource, // yup, resource as kind same is true in apierrors.NewNotFound() + Name: key.Name, + }, + } +} + +// Convert golang errors to status result errors that can be returned to a client +func AsErrorResult(err error) *ErrorResult { + if err == nil { + return nil + } + + apistatus, ok := err.(apierrors.APIStatus) + if ok { + s := apistatus.Status() + res := &ErrorResult{ + Message: s.Message, + Reason: string(s.Reason), + Code: s.Code, + } + if s.Details != nil { + res.Details = &ErrorDetails{ + Group: s.Details.Group, + Kind: s.Details.Kind, + Name: s.Details.Name, + Uid: string(s.Details.UID), + RetryAfterSeconds: s.Details.RetryAfterSeconds, + } + for _, c := range s.Details.Causes { + res.Details.Causes = append(res.Details.Causes, &ErrorCause{ + Reason: string(c.Type), + Message: c.Message, + Field: c.Field, + }) + } + } + return res + } + + // TODO... better conversion?? + return &ErrorResult{ + Message: err.Error(), + Code: 500, + } +} + +func GetError(res *ErrorResult) error { + if res == nil { + return nil + } + + status := &apierrors.StatusError{ErrStatus: metav1.Status{ + Status: metav1.StatusFailure, + Code: res.Code, + Reason: metav1.StatusReason(res.Reason), + Message: res.Message, + }} + if res.Details != nil { + status.ErrStatus.Details = &metav1.StatusDetails{ + Group: res.Details.Group, + Kind: res.Details.Kind, + Name: res.Details.Name, + UID: types.UID(res.Details.Uid), + RetryAfterSeconds: res.Details.RetryAfterSeconds, + } + for _, c := range res.Details.Causes { + status.ErrStatus.Details.Causes = append(status.ErrStatus.Details.Causes, metav1.StatusCause{ + Type: metav1.CauseType(c.Reason), + Message: c.Message, + Field: c.Field, + }) + } + } + return status +} diff --git a/pkg/storage/unified/resource/noop.go b/pkg/storage/unified/resource/noop.go index 00f4070e7d7..9553c607990 100644 --- a/pkg/storage/unified/resource/noop.go +++ b/pkg/storage/unified/resource/noop.go @@ -14,39 +14,31 @@ var ( // It does nothing except return errors when asked to do anything real type noopService struct{} -// Init implements ResourceServer. +// Init implements LifecycleHooks. func (n *noopService) Init(context.Context) error { return nil } -// Stop implements ResourceServer. +// Stop implements LifecycleHooks. func (n *noopService) Stop(context.Context) error { return nil } -// IsHealthy implements ResourceServer. +// IsHealthy implements DiagnosticsServer func (n *noopService) IsHealthy(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) { return &HealthCheckResponse{ Status: HealthCheckResponse_SERVING, }, nil } -// Read implements ResourceServer. func (n *noopService) Read(context.Context, *ReadRequest) (*ReadResponse, error) { return nil, ErrNotImplementedYet } -// List implements ResourceServer. -func (n *noopService) List(context.Context, *ListRequest) (*ListResponse, error) { - return nil, ErrNotImplementedYet -} - -// History implements ResourceServer. func (n *noopService) History(context.Context, *HistoryRequest) (*HistoryResponse, error) { return nil, ErrNotImplementedYet } -// Origin implements ResourceServer. func (n *noopService) Origin(context.Context, *OriginRequest) (*OriginResponse, error) { return nil, ErrNotImplementedYet } diff --git a/pkg/storage/unified/resource/resource.pb.go b/pkg/storage/unified/resource/resource.pb.go index 8abaf33b9bb..3ca099325ab 100644 --- a/pkg/storage/unified/resource/resource.pb.go +++ b/pkg/storage/unified/resource/resource.pb.go @@ -1393,6 +1393,8 @@ type ListResponse struct { // should not rely on the remainingItemCount to be set or to be exact. // +optional RemainingItemCount int64 `protobuf:"varint,4,opt,name=remaining_item_count,json=remainingItemCount,proto3" json:"remaining_item_count,omitempty"` // 0 won't be set either (no next page token) + // Error details + Error *ErrorResult `protobuf:"bytes,5,opt,name=error,proto3" json:"error,omitempty"` } func (x *ListResponse) Reset() { @@ -1455,6 +1457,13 @@ func (x *ListResponse) GetRemainingItemCount() int64 { return 0 } +func (x *ListResponse) GetError() *ErrorResult { + if x != nil { + return x.Error + } + return nil +} + type WatchRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1690,6 +1699,8 @@ type HistoryResponse struct { NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` // ResourceVersion of the list response ResourceVersion int64 `protobuf:"varint,3,opt,name=resource_version,json=resourceVersion,proto3" json:"resource_version,omitempty"` + // Error details + Error *ErrorResult `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` } func (x *HistoryResponse) Reset() { @@ -1745,6 +1756,13 @@ func (x *HistoryResponse) GetResourceVersion() int64 { return 0 } +func (x *HistoryResponse) GetError() *ErrorResult { + if x != nil { + return x.Error + } + return nil +} + type OriginRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1932,6 +1950,8 @@ type OriginResponse struct { NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` // ResourceVersion of the list response ResourceVersion int64 `protobuf:"varint,3,opt,name=resource_version,json=resourceVersion,proto3" json:"resource_version,omitempty"` + // Error details + Error *ErrorResult `protobuf:"bytes,8,opt,name=error,proto3" json:"error,omitempty"` } func (x *OriginResponse) Reset() { @@ -1987,6 +2007,13 @@ func (x *OriginResponse) GetResourceVersion() int64 { return 0 } +func (x *OriginResponse) GetError() *ErrorResult { + if x != nil { + return x.Error + } + return nil +} + type HealthCheckRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2271,7 +2298,7 @@ var file_resource_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xc4, 0x01, 0x0a, + 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xf1, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, @@ -2284,155 +2311,164 @@ var file_resource_proto_rawDesc = []byte{ 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x22, 0xb9, 0x01, 0x0a, 0x0c, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x73, - 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x49, 0x6e, - 0x69, 0x74, 0x69, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, - 0x61, 0x72, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x57, 0x61, 0x74, 0x63, 0x68, 0x42, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x22, - 0xdf, 0x02, 0x0a, 0x0a, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, - 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2d, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, 0x65, 0x73, + 0x75, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0xb9, 0x01, 0x0a, 0x0c, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x6e, 0x64, + 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x69, + 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x5f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x61, + 0x74, 0x63, 0x68, 0x42, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x22, 0xdf, 0x02, 0x0a, + 0x0a, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, - 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, - 0x73, 0x1a, 0x3a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x52, 0x0a, - 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, - 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, - 0x08, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x4f, 0x4f, 0x4b, - 0x4d, 0x41, 0x52, 0x4b, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x05, 0x22, 0x9a, 0x01, 0x0a, 0x0e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, - 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, - 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x14, 0x0a, 0x05, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, - 0x69, 0x74, 0x12, 0x27, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, - 0x68, 0x6f, 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0b, 0x73, 0x68, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x92, - 0x01, 0x0a, 0x0f, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, - 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, - 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x8e, 0x01, 0x0a, 0x0d, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, - 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x14, 0x0a, - 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x12, 0x27, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x72, - 0x69, 0x67, 0x69, 0x6e, 0x22, 0xe5, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x27, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x16, - 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, - 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1c, - 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x97, 0x01, 0x0a, - 0x0e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x32, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x1a, 0x3a, + 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x52, 0x0a, 0x04, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, + 0x09, 0x0a, 0x05, 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x4d, 0x4f, + 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, + 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x4f, 0x4f, 0x4b, 0x4d, 0x41, 0x52, + 0x4b, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x22, 0x9a, + 0x01, 0x0a, 0x0e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, + 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, + 0x27, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x77, + 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x73, 0x68, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0xbf, 0x01, 0x0a, 0x0f, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2c, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x69, 0x74, - 0x65, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, - 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0xab, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0f, - 0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, - 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x10, 0x03, 0x2a, 0x33, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x10, 0x0a, 0x0c, - 0x4e, 0x6f, 0x74, 0x4f, 0x6c, 0x64, 0x65, 0x72, 0x54, 0x68, 0x61, 0x6e, 0x10, 0x00, 0x12, 0x09, - 0x0a, 0x05, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x01, 0x32, 0xed, 0x02, 0x0a, 0x0d, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x52, - 0x65, 0x61, 0x64, 0x12, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, - 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x17, 0x2e, 0x72, + 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x26, 0x0a, + 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x8e, 0x01, + 0x0a, 0x0d, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, + 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x27, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, + 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x22, 0xe5, + 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x27, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x23, + 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xc4, 0x01, 0x0a, 0x0e, 0x4f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x05, 0x69, 0x74, 0x65, + 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x26, 0x0a, + 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x2e, 0x0a, + 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0xab, 0x01, + 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0d, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, + 0x56, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, + 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x2a, 0x33, 0x0a, 0x14, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x12, 0x10, 0x0a, 0x0c, 0x4e, 0x6f, 0x74, 0x4f, 0x6c, 0x64, 0x65, 0x72, 0x54, + 0x68, 0x61, 0x6e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x01, + 0x32, 0xed, 0x02, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x6f, + 0x72, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x15, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x12, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3b, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x37, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, - 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x32, 0xc3, 0x01, 0x0a, 0x0d, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x35, 0x0a, 0x04, 0x52, - 0x65, 0x61, 0x64, 0x12, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, - 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x17, 0x2e, 0x72, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x12, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x17, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x35, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, + 0x12, 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, + 0x32, 0xc3, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x12, 0x35, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x15, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x4f, 0x72, 0x69, + 0x67, 0x69, 0x6e, 0x12, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, - 0x57, 0x0a, 0x0b, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x48, - 0x0a, 0x09, 0x49, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x1c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, - 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x2f, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x57, 0x0a, 0x0b, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, + 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x48, 0x0a, 0x09, 0x49, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x79, 0x12, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -2499,41 +2535,44 @@ var file_resource_proto_depIdxs = []int32{ 0, // 13: resource.ListRequest.version_match:type_name -> resource.ResourceVersionMatch 18, // 14: resource.ListRequest.options:type_name -> resource.ListOptions 4, // 15: resource.ListResponse.items:type_name -> resource.ResourceWrapper - 18, // 16: resource.WatchRequest.options:type_name -> resource.ListOptions - 1, // 17: resource.WatchEvent.type:type_name -> resource.WatchEvent.Type - 30, // 18: resource.WatchEvent.resource:type_name -> resource.WatchEvent.Resource - 30, // 19: resource.WatchEvent.previous:type_name -> resource.WatchEvent.Resource - 3, // 20: resource.HistoryRequest.key:type_name -> resource.ResourceKey - 5, // 21: resource.HistoryResponse.items:type_name -> resource.ResourceMeta - 3, // 22: resource.OriginRequest.key:type_name -> resource.ResourceKey - 3, // 23: resource.ResourceOriginInfo.key:type_name -> resource.ResourceKey - 26, // 24: resource.OriginResponse.items:type_name -> resource.ResourceOriginInfo - 2, // 25: resource.HealthCheckResponse.status:type_name -> resource.HealthCheckResponse.ServingStatus - 15, // 26: resource.ResourceStore.Read:input_type -> resource.ReadRequest - 9, // 27: resource.ResourceStore.Create:input_type -> resource.CreateRequest - 11, // 28: resource.ResourceStore.Update:input_type -> resource.UpdateRequest - 13, // 29: resource.ResourceStore.Delete:input_type -> resource.DeleteRequest - 19, // 30: resource.ResourceStore.List:input_type -> resource.ListRequest - 21, // 31: resource.ResourceStore.Watch:input_type -> resource.WatchRequest - 15, // 32: resource.ResourceIndex.Read:input_type -> resource.ReadRequest - 23, // 33: resource.ResourceIndex.History:input_type -> resource.HistoryRequest - 25, // 34: resource.ResourceIndex.Origin:input_type -> resource.OriginRequest - 28, // 35: resource.Diagnostics.IsHealthy:input_type -> resource.HealthCheckRequest - 16, // 36: resource.ResourceStore.Read:output_type -> resource.ReadResponse - 10, // 37: resource.ResourceStore.Create:output_type -> resource.CreateResponse - 12, // 38: resource.ResourceStore.Update:output_type -> resource.UpdateResponse - 14, // 39: resource.ResourceStore.Delete:output_type -> resource.DeleteResponse - 20, // 40: resource.ResourceStore.List:output_type -> resource.ListResponse - 22, // 41: resource.ResourceStore.Watch:output_type -> resource.WatchEvent - 16, // 42: resource.ResourceIndex.Read:output_type -> resource.ReadResponse - 24, // 43: resource.ResourceIndex.History:output_type -> resource.HistoryResponse - 27, // 44: resource.ResourceIndex.Origin:output_type -> resource.OriginResponse - 29, // 45: resource.Diagnostics.IsHealthy:output_type -> resource.HealthCheckResponse - 36, // [36:46] is the sub-list for method output_type - 26, // [26:36] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 6, // 16: resource.ListResponse.error:type_name -> resource.ErrorResult + 18, // 17: resource.WatchRequest.options:type_name -> resource.ListOptions + 1, // 18: resource.WatchEvent.type:type_name -> resource.WatchEvent.Type + 30, // 19: resource.WatchEvent.resource:type_name -> resource.WatchEvent.Resource + 30, // 20: resource.WatchEvent.previous:type_name -> resource.WatchEvent.Resource + 3, // 21: resource.HistoryRequest.key:type_name -> resource.ResourceKey + 5, // 22: resource.HistoryResponse.items:type_name -> resource.ResourceMeta + 6, // 23: resource.HistoryResponse.error:type_name -> resource.ErrorResult + 3, // 24: resource.OriginRequest.key:type_name -> resource.ResourceKey + 3, // 25: resource.ResourceOriginInfo.key:type_name -> resource.ResourceKey + 26, // 26: resource.OriginResponse.items:type_name -> resource.ResourceOriginInfo + 6, // 27: resource.OriginResponse.error:type_name -> resource.ErrorResult + 2, // 28: resource.HealthCheckResponse.status:type_name -> resource.HealthCheckResponse.ServingStatus + 15, // 29: resource.ResourceStore.Read:input_type -> resource.ReadRequest + 9, // 30: resource.ResourceStore.Create:input_type -> resource.CreateRequest + 11, // 31: resource.ResourceStore.Update:input_type -> resource.UpdateRequest + 13, // 32: resource.ResourceStore.Delete:input_type -> resource.DeleteRequest + 19, // 33: resource.ResourceStore.List:input_type -> resource.ListRequest + 21, // 34: resource.ResourceStore.Watch:input_type -> resource.WatchRequest + 15, // 35: resource.ResourceIndex.Read:input_type -> resource.ReadRequest + 23, // 36: resource.ResourceIndex.History:input_type -> resource.HistoryRequest + 25, // 37: resource.ResourceIndex.Origin:input_type -> resource.OriginRequest + 28, // 38: resource.Diagnostics.IsHealthy:input_type -> resource.HealthCheckRequest + 16, // 39: resource.ResourceStore.Read:output_type -> resource.ReadResponse + 10, // 40: resource.ResourceStore.Create:output_type -> resource.CreateResponse + 12, // 41: resource.ResourceStore.Update:output_type -> resource.UpdateResponse + 14, // 42: resource.ResourceStore.Delete:output_type -> resource.DeleteResponse + 20, // 43: resource.ResourceStore.List:output_type -> resource.ListResponse + 22, // 44: resource.ResourceStore.Watch:output_type -> resource.WatchEvent + 16, // 45: resource.ResourceIndex.Read:output_type -> resource.ReadResponse + 24, // 46: resource.ResourceIndex.History:output_type -> resource.HistoryResponse + 27, // 47: resource.ResourceIndex.Origin:output_type -> resource.OriginResponse + 29, // 48: resource.Diagnostics.IsHealthy:output_type -> resource.HealthCheckResponse + 39, // [39:49] is the sub-list for method output_type + 29, // [29:39] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name } func init() { file_resource_proto_init() } diff --git a/pkg/storage/unified/resource/resource.proto b/pkg/storage/unified/resource/resource.proto index 988e048a385..a8d95fca989 100644 --- a/pkg/storage/unified/resource/resource.proto +++ b/pkg/storage/unified/resource/resource.proto @@ -277,6 +277,9 @@ message ListResponse { // should not rely on the remainingItemCount to be set or to be exact. // +optional int64 remaining_item_count = 4; // 0 won't be set either (no next page token) + + // Error details + ErrorResult error = 5; } message WatchRequest { @@ -343,6 +346,9 @@ message HistoryResponse { // ResourceVersion of the list response int64 resource_version = 3; + + // Error details + ErrorResult error = 4; } message OriginRequest { @@ -390,6 +396,9 @@ message OriginResponse { // ResourceVersion of the list response int64 resource_version = 3; + + // Error details + ErrorResult error = 4; } message HealthCheckRequest { diff --git a/pkg/storage/unified/resource/server.go b/pkg/storage/unified/resource/server.go index 22b69ff4d31..545d3da42b0 100644 --- a/pkg/storage/unified/resource/server.go +++ b/pkg/storage/unified/resource/server.go @@ -3,7 +3,6 @@ package resource import ( context "context" "encoding/json" - "errors" "fmt" "log/slog" "net/http" @@ -20,16 +19,7 @@ import ( "github.com/grafana/grafana/pkg/apimachinery/utils" ) -// Package-level errors. -var ( - ErrNotFound = errors.New("resource not found") - ErrOptimisticLockingFailed = errors.New("optimistic locking failed") - ErrUserNotFoundInContext = errors.New("user not found in context") - ErrUnableToReadResourceJSON = errors.New("unable to read resource json") - ErrNotImplementedYet = errors.New("not implemented yet") -) - -// ResourceServer implements all services +// ResourceServer implements all gRPC services type ResourceServer interface { ResourceStoreServer ResourceIndexServer @@ -46,15 +36,15 @@ type StorageBackend interface { // Return the revisionVersion for this event or error WriteEvent(context.Context, WriteEvent) (int64, error) - // Read a value from storage optionally at an explicit version - Read(context.Context, *ReadRequest) (*ReadResponse, error) + // Read a resource from storage optionally at an explicit version + ReadResource(context.Context, *ReadRequest) *ReadResponse // When the ResourceServer executes a List request, it will first // query the backend for potential results. All results will be // checked against the kubernetes requirements before finally returning // results. The list options can be used to improve performance // but are the the final answer. - PrepareList(context.Context, *ListRequest) (*ListResponse, error) + PrepareList(context.Context, *ListRequest) *ListResponse // Get all events from the store // For HA setups, this will be more events than the local WriteEvent above! @@ -294,7 +284,7 @@ func (s *server) Create(ctx context.Context, req *CreateRequest) (*CreateRespons } rsp := &CreateResponse{} - found, _ := s.backend.Read(ctx, &ReadRequest{Key: req.Key}) + found := s.backend.ReadResource(ctx, &ReadRequest{Key: req.Key}) if found != nil && len(found.Value) > 0 { rsp.Error = &ErrorResult{ Code: http.StatusConflict, @@ -305,54 +295,15 @@ func (s *server) Create(ctx context.Context, req *CreateRequest) (*CreateRespons event, err := s.newEvent(ctx, req.Key, req.Value, nil) if err != nil { - rsp.Error, err = errToStatus(err) - return rsp, err + rsp.Error = AsErrorResult(err) + return rsp, nil } rsp.ResourceVersion, err = s.backend.WriteEvent(ctx, *event) if err != nil { - rsp.Error, err = errToStatus(err) + rsp.Error = AsErrorResult(err) } - return rsp, err -} - -// Convert golang errors to status result errors that can be returned to a client -func errToStatus(err error) (*ErrorResult, error) { - if err != nil { - apistatus, ok := err.(apierrors.APIStatus) - if ok { - s := apistatus.Status() - res := &ErrorResult{ - Message: s.Message, - Reason: string(s.Reason), - Code: s.Code, - } - if s.Details != nil { - res.Details = &ErrorDetails{ - Group: s.Details.Group, - Kind: s.Details.Kind, - Name: s.Details.Name, - Uid: string(s.Details.UID), - RetryAfterSeconds: s.Details.RetryAfterSeconds, - } - for _, c := range s.Details.Causes { - res.Details.Causes = append(res.Details.Causes, &ErrorCause{ - Reason: string(c.Type), - Message: c.Message, - Field: c.Field, - }) - } - } - return res, nil - } - - // TODO... better conversion?? - return &ErrorResult{ - Message: err.Error(), - Code: 500, - }, nil - } - return nil, err + return rsp, nil } func (s *server) Update(ctx context.Context, req *UpdateRequest) (*UpdateResponse, error) { @@ -365,18 +316,19 @@ func (s *server) Update(ctx context.Context, req *UpdateRequest) (*UpdateRespons rsp := &UpdateResponse{} if req.ResourceVersion < 0 { - rsp.Error, _ = errToStatus(apierrors.NewBadRequest("update must include the previous version")) + rsp.Error = AsErrorResult(apierrors.NewBadRequest("update must include the previous version")) return rsp, nil } - latest, err := s.backend.Read(ctx, &ReadRequest{ + latest := s.backend.ReadResource(ctx, &ReadRequest{ Key: req.Key, }) - if err != nil { - return nil, err + if latest.Error != nil { + return rsp, nil } if latest.Value == nil { - return nil, apierrors.NewBadRequest("current value does not exist") + rsp.Error = NewBadRequestError("current value does not exist") + return rsp, nil } if req.ResourceVersion > 0 && latest.ResourceVersion != req.ResourceVersion { @@ -385,7 +337,7 @@ func (s *server) Update(ctx context.Context, req *UpdateRequest) (*UpdateRespons event, err := s.newEvent(ctx, req.Key, req.Value, latest.Value) if err != nil { - rsp.Error, err = errToStatus(err) + rsp.Error = AsErrorResult(err) return rsp, err } @@ -393,11 +345,10 @@ func (s *server) Update(ctx context.Context, req *UpdateRequest) (*UpdateRespons event.PreviousRV = latest.ResourceVersion rsp.ResourceVersion, err = s.backend.WriteEvent(ctx, *event) - rsp.Error, err = errToStatus(err) if err != nil { - rsp.Error, err = errToStatus(err) + rsp.Error = AsErrorResult(err) } - return rsp, err + return rsp, nil } func (s *server) Delete(ctx context.Context, req *DeleteRequest) (*DeleteResponse, error) { @@ -413,14 +364,16 @@ func (s *server) Delete(ctx context.Context, req *DeleteRequest) (*DeleteRespons return nil, apierrors.NewBadRequest("update must include the previous version") } - latest, err := s.backend.Read(ctx, &ReadRequest{ + latest := s.backend.ReadResource(ctx, &ReadRequest{ Key: req.Key, }) - if err != nil { - return nil, err + if latest.Error != nil { + rsp.Error = latest.Error + return rsp, nil } if req.ResourceVersion > 0 && latest.ResourceVersion != req.ResourceVersion { - return nil, ErrOptimisticLockingFailed + rsp.Error = AsErrorResult(ErrOptimisticLockingFailed) + return rsp, nil } now := metav1.NewTime(time.UnixMilli(s.now())) @@ -460,8 +413,10 @@ func (s *server) Delete(ctx context.Context, req *DeleteRequest) (*DeleteRespons } rsp.ResourceVersion, err = s.backend.WriteEvent(ctx, event) - rsp.Error, err = errToStatus(err) - return rsp, err + if err != nil { + rsp.Error = AsErrorResult(err) + } + return rsp, nil } func (s *server) Read(ctx context.Context, req *ReadRequest) (*ReadResponse, error) { @@ -470,22 +425,16 @@ func (s *server) Read(ctx context.Context, req *ReadRequest) (*ReadResponse, err } // if req.Key.Group == "" { - // status, _ := errToStatus(apierrors.NewBadRequest("missing group")) + // status, _ := AsErrorResult(apierrors.NewBadRequest("missing group")) // return &ReadResponse{Status: status}, nil // } if req.Key.Resource == "" { - status, _ := errToStatus(apierrors.NewBadRequest("missing resource")) - return &ReadResponse{Error: status}, nil + return &ReadResponse{Error: NewBadRequestError("missing resource")}, nil } - rsp, err := s.backend.Read(ctx, req) - if err != nil { - if rsp == nil { - rsp = &ReadResponse{} - } - rsp.Error, err = errToStatus(err) - } - return rsp, err + rsp := s.backend.ReadResource(ctx, req) + // TODO, check folder permissions etc + return rsp, nil } func (s *server) List(ctx context.Context, req *ListRequest) (*ListResponse, error) { @@ -493,9 +442,9 @@ func (s *server) List(ctx context.Context, req *ListRequest) (*ListResponse, err return nil, err } - rsp, err := s.backend.PrepareList(ctx, req) + rsp := s.backend.PrepareList(ctx, req) // Status??? - return rsp, err + return rsp, nil } func (s *server) initWatcher() error { diff --git a/pkg/storage/unified/sql/backend.go b/pkg/storage/unified/sql/backend.go index ddd9f057243..7f4de06694c 100644 --- a/pkg/storage/unified/sql/backend.go +++ b/pkg/storage/unified/sql/backend.go @@ -17,8 +17,6 @@ import ( "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace/noop" "google.golang.org/protobuf/proto" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" ) const trace_prefix = "sql.resource." @@ -295,7 +293,7 @@ func (b *backend) delete(ctx context.Context, event resource.WriteEvent) (int64, return newVersion, err } -func (b *backend) Read(ctx context.Context, req *resource.ReadRequest) (*resource.ReadResponse, error) { +func (b *backend) ReadResource(ctx context.Context, req *resource.ReadRequest) *resource.ReadResponse { _, span := b.tracer.Start(ctx, trace_prefix+".Read") defer span.End() @@ -315,23 +313,24 @@ func (b *backend) Read(ctx context.Context, req *resource.ReadRequest) (*resourc res, err := dbutil.QueryRow(ctx, b.db, sr, readReq) if errors.Is(err, sql.ErrNoRows) { - return nil, apierrors.NewNotFound(schema.GroupResource{ - Group: req.Key.Group, - Resource: req.Key.Resource, - }, req.Key.Name) + return &resource.ReadResponse{ + Error: resource.NewNotFoundError(req.Key), + } } else if err != nil { - return nil, fmt.Errorf("get resource version: %w", err) + return &resource.ReadResponse{Error: resource.AsErrorResult(err)} } - return &res.ReadResponse, nil + return &res.ReadResponse } -func (b *backend) PrepareList(ctx context.Context, req *resource.ListRequest) (*resource.ListResponse, error) { +func (b *backend) PrepareList(ctx context.Context, req *resource.ListRequest) *resource.ListResponse { _, span := b.tracer.Start(ctx, trace_prefix+"List") defer span.End() if req.Options == nil || req.Options.Key.Group == "" || req.Options.Key.Resource == "" { - return nil, fmt.Errorf("missing group or resource") + return &resource.ListResponse{ + Error: resource.NewBadRequestError("missing group or resource"), + } } // TODO: think about how to handler VersionMatch. We should be able to use latest for the first page (only). @@ -345,7 +344,7 @@ func (b *backend) PrepareList(ctx context.Context, req *resource.ListRequest) (* } // listLatest fetches the resources from the resource table. -func (b *backend) listLatest(ctx context.Context, req *resource.ListRequest) (*resource.ListResponse, error) { +func (b *backend) listLatest(ctx context.Context, req *resource.ListRequest) *resource.ListResponse { out := &resource.ListResponse{ ResourceVersion: 0, } @@ -387,19 +386,23 @@ func (b *backend) listLatest(ctx context.Context, req *resource.ListRequest) (*r return nil }) - - return out, err + if err != nil { + out.Error = resource.AsErrorResult(err) + } + return out } // listAtRevision fetches the resources from the resource_history table at a specific revision. -func (b *backend) listAtRevision(ctx context.Context, req *resource.ListRequest) (*resource.ListResponse, error) { +func (b *backend) listAtRevision(ctx context.Context, req *resource.ListRequest) *resource.ListResponse { // Get the RV rv := req.ResourceVersion offset := int64(0) if req.NextPageToken != "" { continueToken, err := GetContinueToken(req.NextPageToken) if err != nil { - return nil, fmt.Errorf("get continue token: %w", err) + return &resource.ListResponse{ + Error: resource.AsErrorResult(fmt.Errorf("get continue token: %w", err)), + } } rv = continueToken.ResourceVersion offset = continueToken.StartOffset @@ -443,8 +446,10 @@ func (b *backend) listAtRevision(ctx context.Context, req *resource.ListRequest) return nil }) - - return out, err + if err != nil { + out.Error = resource.AsErrorResult(err) + } + return out } func (b *backend) WatchWriteEvents(ctx context.Context) (<-chan *resource.WrittenEvent, error) { diff --git a/pkg/storage/unified/sql/test/integration_test.go b/pkg/storage/unified/sql/test/integration_test.go index fd5500fe4a3..c1c10dfac4f 100644 --- a/pkg/storage/unified/sql/test/integration_test.go +++ b/pkg/storage/unified/sql/test/integration_test.go @@ -88,14 +88,14 @@ func TestIntegrationBackendHappyPath(t *testing.T) { }) t.Run("Read latest item 2", func(t *testing.T) { - resp, err := store.Read(ctx, &resource.ReadRequest{Key: resourceKey("item2")}) + resp := store.ReadResource(ctx, &resource.ReadRequest{Key: resourceKey("item2")}) require.NoError(t, err) require.Equal(t, int64(4), resp.ResourceVersion) require.Equal(t, "item2 MODIFIED", string(resp.Value)) }) t.Run("Read early verion of item2", func(t *testing.T) { - resp, err := store.Read(ctx, &resource.ReadRequest{ + resp := store.ReadResource(ctx, &resource.ReadRequest{ Key: resourceKey("item2"), ResourceVersion: 3, // item2 was created at rv=2 and updated at rv=4 }) @@ -105,7 +105,7 @@ func TestIntegrationBackendHappyPath(t *testing.T) { }) t.Run("PrepareList latest", func(t *testing.T) { - resp, err := store.PrepareList(ctx, &resource.ListRequest{ + resp := store.PrepareList(ctx, &resource.ListRequest{ Options: &resource.ListOptions{ Key: &resource.ResourceKey{ Namespace: "namespace", @@ -188,7 +188,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { _, _ = writeEvent(ctx, store, "item3", resource.WatchEvent_DELETED) // rv=7 _, _ = writeEvent(ctx, store, "item6", resource.WatchEvent_ADDED) // rv=8 t.Run("fetch all latest", func(t *testing.T) { - res, err := store.PrepareList(ctx, &resource.ListRequest{ + res := store.PrepareList(ctx, &resource.ListRequest{ Options: &resource.ListOptions{ Key: &resource.ResourceKey{ Group: "group", @@ -196,7 +196,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }, }, }) - require.NoError(t, err) + require.Nil(t, res.Error) require.Len(t, res.Items, 5) // should be sorted by resource version DESC require.Equal(t, "item6 ADDED", string(res.Items[0].Value)) @@ -209,7 +209,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }) t.Run("list latest first page ", func(t *testing.T) { - res, err := store.PrepareList(ctx, &resource.ListRequest{ + res := store.PrepareList(ctx, &resource.ListRequest{ Limit: 3, Options: &resource.ListOptions{ Key: &resource.ResourceKey{ @@ -218,7 +218,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }, }, }) - require.NoError(t, err) + require.Nil(t, res.Error) require.Len(t, res.Items, 3) continueToken, err := sql.GetContinueToken(res.NextPageToken) require.NoError(t, err) @@ -230,7 +230,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }) t.Run("list at revision", func(t *testing.T) { - res, err := store.PrepareList(ctx, &resource.ListRequest{ + res := store.PrepareList(ctx, &resource.ListRequest{ ResourceVersion: 4, Options: &resource.ListOptions{ Key: &resource.ResourceKey{ @@ -239,7 +239,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }, }, }) - require.NoError(t, err) + require.Nil(t, res.Error) require.Len(t, res.Items, 4) require.Equal(t, "item4 ADDED", string(res.Items[0].Value)) require.Equal(t, "item3 ADDED", string(res.Items[1].Value)) @@ -249,7 +249,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }) t.Run("fetch first page at revision with limit", func(t *testing.T) { - res, err := store.PrepareList(ctx, &resource.ListRequest{ + res := store.PrepareList(ctx, &resource.ListRequest{ Limit: 3, ResourceVersion: 7, Options: &resource.ListOptions{ @@ -259,7 +259,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }, }, }) - require.NoError(t, err) + require.Nil(t, res.Error) require.Len(t, res.Items, 3) t.Log(res.Items) require.Equal(t, "item2 MODIFIED", string(res.Items[0].Value)) @@ -277,7 +277,7 @@ func TestIntegrationBackendPrepareList(t *testing.T) { ResourceVersion: 8, StartOffset: 2, } - res, err := store.PrepareList(ctx, &resource.ListRequest{ + res := store.PrepareList(ctx, &resource.ListRequest{ NextPageToken: continueToken.String(), Limit: 2, Options: &resource.ListOptions{ @@ -287,12 +287,12 @@ func TestIntegrationBackendPrepareList(t *testing.T) { }, }, }) - require.NoError(t, err) + require.Nil(t, res.Error) require.Len(t, res.Items, 2) require.Equal(t, "item5 ADDED", string(res.Items[0].Value)) require.Equal(t, "item4 ADDED", string(res.Items[1].Value)) - continueToken, err = sql.GetContinueToken(res.NextPageToken) + continueToken, err := sql.GetContinueToken(res.NextPageToken) require.NoError(t, err) require.Equal(t, int64(8), continueToken.ResourceVersion) require.Equal(t, int64(4), continueToken.StartOffset)