From 9f6144059af06b23e5053cee4ab67533d512054b Mon Sep 17 00:00:00 2001 From: Dan Cech Date: Mon, 11 Dec 2023 18:26:05 +0100 Subject: [PATCH] Storage: Switch from tenant to namespace & remove GRN (#79250) * remove GRN and switch tenant to namespace * clean up remaining references * simplify and remove inconsistency in With* parameters * parse listing keys so we can use db index * bump the schema version --------- Co-authored-by: Ryan McKinley --- .github/CODEOWNERS | 1 - Makefile | 1 - pkg/infra/grn/doc.go | 13 - pkg/infra/grn/errors.go | 9 - pkg/infra/grn/generate.sh | 24 - pkg/infra/grn/grn.go | 87 - pkg/infra/grn/grn.pb.go | 185 --- pkg/infra/grn/grn.proto | 24 - pkg/infra/grn/grn_test.go | 84 - .../storage/entity/storage.go | 24 +- .../grafana-apiserver/storage/entity/utils.go | 119 +- pkg/services/store/entity/client_wrapper.go | 16 - pkg/services/store/entity/dummy/fake_store.go | 9 - pkg/services/store/entity/entity.pb.go | 1398 ++++++----------- pkg/services/store/entity/entity.proto | 126 +- pkg/services/store/entity/entity_grpc.pb.go | 180 +-- pkg/services/store/entity/key.go | 61 + .../entity/migrations/entity_store_mig.go | 19 +- pkg/services/store/entity/models.go | 3 + .../store/entity/sqlstash/folder_support.go | 20 +- .../entity/sqlstash/sql_storage_server.go | 688 ++------ .../entity/tests/server_integration_test.go | 216 ++- pkg/services/store/entity/utils.go | 9 - pkg/services/store/resolver/service.go | 2 +- 24 files changed, 906 insertions(+), 2412 deletions(-) delete mode 100644 pkg/infra/grn/doc.go delete mode 100644 pkg/infra/grn/errors.go delete mode 100755 pkg/infra/grn/generate.sh delete mode 100644 pkg/infra/grn/grn.go delete mode 100644 pkg/infra/grn/grn.pb.go delete mode 100644 pkg/infra/grn/grn.proto delete mode 100644 pkg/infra/grn/grn_test.go create mode 100644 pkg/services/store/entity/key.go delete mode 100644 pkg/services/store/entity/utils.go diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a78c8be5cd9..77965604ce7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -84,7 +84,6 @@ /pkg/ifaces/ @grafana/backend-platform /pkg/infra/appcontext/ @grafana/backend-platform /pkg/infra/db/ @grafana/backend-platform -/pkg/infra/grn/ @grafana/backend-platform /pkg/infra/localcache/ @grafana/backend-platform /pkg/infra/log/ @grafana/backend-platform /pkg/infra/metrics/ @grafana/backend-platform diff --git a/Makefile b/Makefile index 1e9bfbf8134..9d209f0ec1f 100644 --- a/Makefile +++ b/Makefile @@ -308,7 +308,6 @@ protobuf: ## Compile protobuf definitions bash pkg/plugins/backendplugin/pluginextensionv2/generate.sh bash pkg/plugins/backendplugin/secretsmanagerplugin/generate.sh bash pkg/services/store/entity/generate.sh - bash pkg/infra/grn/generate.sh clean: ## Clean up intermediate build artifacts. @echo "cleaning" diff --git a/pkg/infra/grn/doc.go b/pkg/infra/grn/doc.go deleted file mode 100644 index ba6e88698c0..00000000000 --- a/pkg/infra/grn/doc.go +++ /dev/null @@ -1,13 +0,0 @@ -// package GRN provides utilities for working with Grafana Resource Names -// (GRNs). - -// A GRN is an identifier which encodes all data necessary to retrieve a given -// resource from its respective service. - -// A GRN string is expressed in the format: -// -// grn:${tenant_id}:${group}/${kind}/${id} -// -// The format of the final id is defined by the owning service and not -// validated by the GRN parser. Prefer using UIDs where possible. -package grn diff --git a/pkg/infra/grn/errors.go b/pkg/infra/grn/errors.go deleted file mode 100644 index 3fe17a7306c..00000000000 --- a/pkg/infra/grn/errors.go +++ /dev/null @@ -1,9 +0,0 @@ -package grn - -import ( - "github.com/grafana/grafana/pkg/util/errutil" -) - -var ( - ErrInvalidGRN = errutil.ValidationFailed("grn.InvalidGRN") -) diff --git a/pkg/infra/grn/generate.sh b/pkg/infra/grn/generate.sh deleted file mode 100755 index 849ac461b54..00000000000 --- a/pkg/infra/grn/generate.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# To compile all protobuf files in this repository, run -# "make protobuf" at the top-level. - -set -eu - -DST_DIR=./ - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -cd "$DIR" - -protoc \ - -I ./ \ - -I ../../../ \ - --go_out=${DST_DIR} \ - --go_opt=paths=source_relative \ - --go-grpc_out=${DST_DIR} \ - --go-grpc_opt=paths=source_relative \ - --go-grpc_opt=require_unimplemented_servers=false \ - *.proto diff --git a/pkg/infra/grn/grn.go b/pkg/infra/grn/grn.go deleted file mode 100644 index 3faf14c26d7..00000000000 --- a/pkg/infra/grn/grn.go +++ /dev/null @@ -1,87 +0,0 @@ -package grn - -import ( - "fmt" - "strconv" - "strings" -) - -// ParseStr attempts to parse a string into a GRN. It returns an error if the -// given string does not match the GRN format, but does not validate the values. -// grn::// -// No component of the GRN may contain a colon -// The TenantID is optional, but must be an integer string if specified -// The ResourceGroup, ResourceKind and ResourceIdentifier must be non-empty strings -// The ResourceGroup and ResourceKind may not contain slashes -// The ResourceIdentifier may contain slashes -func ParseStr(str string) (*GRN, error) { - ret := &GRN{} - - parts := strings.Split(str, ":") - if len(parts) != 3 { - return ret, ErrInvalidGRN.Errorf("%q is not a complete GRN", str) - } - - if parts[0] != "grn" { - return ret, ErrInvalidGRN.Errorf("%q does not look like a GRN", str) - } - - if parts[1] != "" { - tID, err := strconv.ParseInt(parts[1], 10, 64) - if err != nil { - return ret, ErrInvalidGRN.Errorf("Tenant ID segment cannot be converted to an integer") - } - - ret.TenantID = tID - } - - // split the rest of the GRN into Group, Kind and Identifier - parts = strings.SplitN(parts[2], "/", 3) - if len(parts) != 3 { - return ret, ErrInvalidGRN.Errorf("%q is not a complete GRN", str) - } - - ret.ResourceGroup = parts[0] - ret.ResourceKind = parts[1] - ret.ResourceIdentifier = parts[2] - - if ret.ResourceGroup == "" { - return ret, ErrInvalidGRN.Errorf("Cannot find resource group in GRN %q", str) - } - if ret.ResourceKind == "" { - return ret, ErrInvalidGRN.Errorf("Cannot find resource kind in GRN %q", str) - } - if ret.ResourceIdentifier == "" { - return ret, ErrInvalidGRN.Errorf("Cannot find resource identifier in GRN %q", str) - } - - return ret, nil -} - -// MustParseStr is a wrapper around ParseStr that panics if the given input is -// not a valid GRN. This is intended for use in tests. -func MustParseStr(str string) *GRN { - grn, err := ParseStr(str) - if err != nil { - panic("bad grn!") - } - return grn -} - -// ToGRNString returns a string representation of a grn in the format -// grn:tenantID:kind/resourceIdentifier -func (g *GRN) ToGRNString() string { - return fmt.Sprintf("grn:%d:%s/%s/%s", g.TenantID, g.ResourceGroup, g.ResourceKind, g.ResourceIdentifier) -} - -// Check if the two GRNs reference to the same object -// we can not use simple `*x == *b` because of the internal settings -func (g *GRN) Equal(b *GRN) bool { - if b == nil { - return false - } - return g == b || (g.TenantID == b.TenantID && - g.ResourceGroup == b.ResourceGroup && - g.ResourceKind == b.ResourceKind && - g.ResourceIdentifier == b.ResourceIdentifier) -} diff --git a/pkg/infra/grn/grn.pb.go b/pkg/infra/grn/grn.pb.go deleted file mode 100644 index e4d82a178f5..00000000000 --- a/pkg/infra/grn/grn.pb.go +++ /dev/null @@ -1,185 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc v4.23.4 -// source: grn.proto - -package grn - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type GRN struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // TenantID contains the ID of the tenant (in hosted grafana) or - // organization (in other environments) the resource belongs to. This field - // may be omitted for global Grafana resources which are not associated with - // an organization. - TenantID int64 `protobuf:"varint,1,opt,name=TenantID,proto3" json:"TenantID,omitempty"` - // The kind of resource being identified, for e.g. "dashboard" or "user". - // The caller is responsible for validating the value. - ResourceKind string `protobuf:"bytes,3,opt,name=ResourceKind,proto3" json:"ResourceKind,omitempty"` - // ResourceIdentifier is used by the underlying service to identify the - // resource. - ResourceIdentifier string `protobuf:"bytes,4,opt,name=ResourceIdentifier,proto3" json:"ResourceIdentifier,omitempty"` - // The group represents the specific resource group the resource belongs to. - // This is a unique value for each plugin and maps to the k8s Group - ResourceGroup string `protobuf:"bytes,5,opt,name=ResourceGroup,proto3" json:"ResourceGroup,omitempty"` -} - -func (x *GRN) Reset() { - *x = GRN{} - if protoimpl.UnsafeEnabled { - mi := &file_grn_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRN) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRN) ProtoMessage() {} - -func (x *GRN) ProtoReflect() protoreflect.Message { - mi := &file_grn_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRN.ProtoReflect.Descriptor instead. -func (*GRN) Descriptor() ([]byte, []int) { - return file_grn_proto_rawDescGZIP(), []int{0} -} - -func (x *GRN) GetTenantID() int64 { - if x != nil { - return x.TenantID - } - return 0 -} - -func (x *GRN) GetResourceKind() string { - if x != nil { - return x.ResourceKind - } - return "" -} - -func (x *GRN) GetResourceIdentifier() string { - if x != nil { - return x.ResourceIdentifier - } - return "" -} - -func (x *GRN) GetResourceGroup() string { - if x != nil { - return x.ResourceGroup - } - return "" -} - -var File_grn_proto protoreflect.FileDescriptor - -var file_grn_proto_rawDesc = []byte{ - 0x0a, 0x09, 0x67, 0x72, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x67, 0x72, 0x6e, - 0x22, 0x9b, 0x01, 0x0a, 0x03, 0x47, 0x52, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x6e, 0x61, - 0x6e, 0x74, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x54, 0x65, 0x6e, 0x61, - 0x6e, 0x74, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x2a, - 0x5a, 0x28, 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, 0x69, 0x6e, 0x66, 0x72, 0x61, 0x2f, 0x67, 0x72, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_grn_proto_rawDescOnce sync.Once - file_grn_proto_rawDescData = file_grn_proto_rawDesc -) - -func file_grn_proto_rawDescGZIP() []byte { - file_grn_proto_rawDescOnce.Do(func() { - file_grn_proto_rawDescData = protoimpl.X.CompressGZIP(file_grn_proto_rawDescData) - }) - return file_grn_proto_rawDescData -} - -var file_grn_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_grn_proto_goTypes = []interface{}{ - (*GRN)(nil), // 0: grn.GRN -} -var file_grn_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_grn_proto_init() } -func file_grn_proto_init() { - if File_grn_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_grn_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRN); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_grn_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_grn_proto_goTypes, - DependencyIndexes: file_grn_proto_depIdxs, - MessageInfos: file_grn_proto_msgTypes, - }.Build() - File_grn_proto = out.File - file_grn_proto_rawDesc = nil - file_grn_proto_goTypes = nil - file_grn_proto_depIdxs = nil -} diff --git a/pkg/infra/grn/grn.proto b/pkg/infra/grn/grn.proto deleted file mode 100644 index c3c21210e56..00000000000 --- a/pkg/infra/grn/grn.proto +++ /dev/null @@ -1,24 +0,0 @@ -syntax = "proto3"; -package grn; - -option go_package = "github.com/grafana/grafana/pkg/infra/grn"; - -message GRN { - // TenantID contains the ID of the tenant (in hosted grafana) or - // organization (in other environments) the resource belongs to. This field - // may be omitted for global Grafana resources which are not associated with - // an organization. - int64 TenantID = 1; - - // The kind of resource being identified, for e.g. "dashboard" or "user". - // The caller is responsible for validating the value. - string ResourceKind = 3; - - // ResourceIdentifier is used by the underlying service to identify the - // resource. - string ResourceIdentifier = 4; - - // The group represents the specific resource group the resource belongs to. - // This is a unique value for each plugin and maps to the k8s Group - string ResourceGroup = 5; -} diff --git a/pkg/infra/grn/grn_test.go b/pkg/infra/grn/grn_test.go deleted file mode 100644 index c20a82a4a13..00000000000 --- a/pkg/infra/grn/grn_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package grn - -import ( - "fmt" - "testing" - - "github.com/google/go-cmp/cmp" -) - -func TestParseGRNStr(t *testing.T) { - tests := []struct { - input string - expect *GRN - expectErr bool - }{ - { // empty - "", - &GRN{}, - true, - }, - { // too few parts - "grn:dashboards", - &GRN{}, - true, - }, - { // too many parts - "grn::dashboards:user:orgs:otherthings:hello:stillgoing", - &GRN{}, - true, - }, - { // Does not look like a GRN - "hrn:grafana::123:dashboards/foo", - &GRN{}, - true, - }, - { // Missing Kind - "grn::foo", - &GRN{}, - true, - }, - { // Missing Group - "grn::foo/Bar", - &GRN{}, - true, - }, - { // good! - "grn::core.grafana.com/Role/Admin", - &GRN{TenantID: 0, ResourceGroup: "core.grafana.com", ResourceKind: "Role", ResourceIdentifier: "Admin"}, - false, - }, - { // good! - "grn::core.grafana.com/Role/Admin/with/some/slashes", - &GRN{TenantID: 0, ResourceGroup: "core.grafana.com", ResourceKind: "Role", ResourceIdentifier: "Admin/with/some/slashes"}, - false, - }, - { // good! - "grn:123456789:core.grafana.com/Role/Admin/with/some/slashes", - &GRN{TenantID: 123456789, ResourceGroup: "core.grafana.com", ResourceKind: "Role", ResourceIdentifier: "Admin/with/some/slashes"}, - false, - }, - { // Weird, but valid. - "grn::core.grafana.com/Role///Admin/with/leading/slashes", - &GRN{TenantID: 0, ResourceGroup: "core.grafana.com", ResourceKind: "Role", ResourceIdentifier: "//Admin/with/leading/slashes"}, - false, - }, - } - - for _, test := range tests { - t.Run(fmt.Sprintf("ParseStr(%q)", test.input), func(t *testing.T) { - got, err := ParseStr(test.input) - if test.expectErr && err == nil { - t.Fatal("wrong result. Expected error, got success") - } - - if err != nil && !test.expectErr { - t.Fatalf("wrong result. Expected success, got error %s", err.Error()) - } - - if !cmp.Equal(test.expect, got) { - t.Fatalf("wrong result. Wanted %s, got %s\n", test.expect.String(), got.String()) - } - }) - } -} diff --git a/pkg/services/grafana-apiserver/storage/entity/storage.go b/pkg/services/grafana-apiserver/storage/entity/storage.go index c39a689d976..c6c56beae74 100644 --- a/pkg/services/grafana-apiserver/storage/entity/storage.go +++ b/pkg/services/grafana-apiserver/storage/entity/storage.go @@ -89,7 +89,7 @@ func (s *Storage) Create(ctx context.Context, key string, obj runtime.Object, ou // Replace the default name generation strategy if metaAccessor.GetGenerateName() != "" { - k, err := ParseKey(key) + k, err := entityStore.ParseKey(key) if err != nil { return err } @@ -138,18 +138,13 @@ func (s *Storage) Create(ctx context.Context, key string, obj runtime.Object, ou // current version of the object to avoid read operation from storage to get it. // However, the implementations have to retry in case suggestion is stale. func (s *Storage) Delete(ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions, validateDeletion storage.ValidateObjectFunc, cachedExistingObject runtime.Object) error { - grn, err := keyToGRN(key) - if err != nil { - return apierrors.NewInternalError(err) - } - previousVersion := "" if preconditions != nil && preconditions.ResourceVersion != nil { previousVersion = *preconditions.ResourceVersion } rsp, err := s.store.Delete(ctx, &entityStore.DeleteEntityRequest{ - GRN: grn, + Key: key, PreviousVersion: previousVersion, }) if err != nil { @@ -182,17 +177,15 @@ func (s *Storage) Watch(ctx context.Context, key string, opts storage.ListOption // match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'. func (s *Storage) Get(ctx context.Context, key string, opts storage.GetOptions, objPtr runtime.Object) error { rsp, err := s.store.Read(ctx, &entityStore.ReadEntityRequest{ - Key: key, - WithMeta: true, - WithBody: true, - WithStatus: true, - WithSummary: true, + Key: key, + WithBody: true, + WithStatus: true, }) if err != nil { return err } - if rsp.GRN == nil { + if rsp.Key == "" { if opts.IgnoreNotFound { return nil } @@ -227,8 +220,7 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti rsp, err := s.store.List(ctx, &entityStore.EntityListRequest{ Key: []string{key}, WithBody: true, - WithLabels: true, - WithFields: true, + WithStatus: true, NextPageToken: opts.Predicate.Continue, Limit: opts.Predicate.Limit, // TODO push label/field matching down to storage @@ -340,8 +332,6 @@ func (s *Storage) guaranteedUpdate( return err } - // e.GRN.ResourceKind = destination.GetObjectKind().GroupVersionKind().Kind - previousVersion := "" if preconditions != nil && preconditions.ResourceVersion != nil { previousVersion = *preconditions.ResourceVersion diff --git a/pkg/services/grafana-apiserver/storage/entity/utils.go b/pkg/services/grafana-apiserver/storage/entity/utils.go index 3be9258665e..cb285006ee8 100644 --- a/pkg/services/grafana-apiserver/storage/entity/utils.go +++ b/pkg/services/grafana-apiserver/storage/entity/utils.go @@ -2,10 +2,7 @@ package entity import ( "encoding/json" - "fmt" "reflect" - "strconv" - "strings" "time" "k8s.io/apimachinery/pkg/api/meta" @@ -14,102 +11,10 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/endpoints/request" - "github.com/grafana/grafana/pkg/infra/grn" "github.com/grafana/grafana/pkg/kinds" entityStore "github.com/grafana/grafana/pkg/services/store/entity" ) -type Key struct { - Group string - Resource string - Namespace string - Name string - Subresource string -} - -func ParseKey(key string) (*Key, error) { - // ////(/) - parts := strings.SplitN(key, "/", 6) - if len(parts) != 5 && len(parts) != 6 { - return nil, fmt.Errorf("invalid key (expecting 4 or 5 parts) " + key) - } - - if parts[0] != "" { - return nil, fmt.Errorf("invalid key (expecting leading slash) " + key) - } - - k := &Key{ - Group: parts[1], - Resource: parts[2], - Namespace: parts[3], - Name: parts[4], - } - - if len(parts) == 6 { - k.Subresource = parts[5] - } - - return k, nil -} - -func (k *Key) String() string { - if len(k.Subresource) > 0 { - return fmt.Sprintf("/%s/%s/%s/%s/%s", k.Group, k.Resource, k.Namespace, k.Name, k.Subresource) - } - return fmt.Sprintf("/%s/%s/%s/%s", k.Group, k.Resource, k.Namespace, k.Name) -} - -func (k *Key) IsEqual(other *Key) bool { - return k.Group == other.Group && - k.Resource == other.Resource && - k.Namespace == other.Namespace && - k.Name == other.Name && - k.Subresource == other.Subresource -} - -func (k *Key) TenantID() (int64, error) { - if k.Namespace == "default" { - return 1, nil - } - tid := strings.Split(k.Namespace, "-") - if len(tid) != 2 || !(tid[0] == "org" || tid[0] == "tenant") { - return 0, fmt.Errorf("invalid namespace, expected org|tenant-${#}") - } - intVar, err := strconv.ParseInt(tid[1], 10, 64) - if err != nil { - return 0, fmt.Errorf("invalid namespace, expected number") - } - return intVar, nil -} - -func (k *Key) ToGRN() (*grn.GRN, error) { - tid, err := k.TenantID() - if err != nil { - return nil, err - } - - fullResource := k.Resource - if k.Subresource != "" { - fullResource = fmt.Sprintf("%s/%s", k.Resource, k.Subresource) - } - - return &grn.GRN{ - ResourceGroup: k.Group, - ResourceKind: fullResource, - ResourceIdentifier: k.Name, - TenantID: tid, - }, nil -} - -// Convert an etcd key to GRN style -func keyToGRN(key string) (*grn.GRN, error) { - k, err := ParseKey(key) - if err != nil { - return nil, err - } - return k.ToGRN() -} - // this is terrible... but just making it work!!!! func entityToResource(rsp *entityStore.Entity, res runtime.Object) error { var err error @@ -119,10 +24,6 @@ func entityToResource(rsp *entityStore.Entity, res runtime.Object) error { return err } - if rsp.GRN == nil { - return fmt.Errorf("invalid entity, missing GRN") - } - if len(rsp.Meta) > 0 { err = json.Unmarshal(rsp.Meta, res) if err != nil { @@ -130,12 +31,8 @@ func entityToResource(rsp *entityStore.Entity, res runtime.Object) error { } } - metaAccessor.SetName(rsp.GRN.ResourceIdentifier) - if rsp.GRN.TenantID != 1 { - metaAccessor.SetNamespace(fmt.Sprintf("tenant-%d", rsp.GRN.TenantID)) - } else { - metaAccessor.SetNamespace("default") // org 1 - } + metaAccessor.SetName(rsp.Uid) + metaAccessor.SetNamespace(rsp.Namespace) metaAccessor.SetUID(types.UID(rsp.Guid)) metaAccessor.SetResourceVersion(rsp.Version) metaAccessor.SetCreationTimestamp(metav1.Unix(rsp.CreatedAt/1000, rsp.CreatedAt%1000*1000000)) @@ -202,18 +99,16 @@ func resourceToEntity(key string, res runtime.Object, requestInfo *request.Reque return nil, err } - g, err := keyToGRN(key) - if err != nil { - return nil, err - } - grafanaAccessor := kinds.MetaAccessor(metaAccessor) rsp := &entityStore.Entity{ - GRN: g, + Group: requestInfo.APIGroup, GroupVersion: requestInfo.APIVersion, + Resource: requestInfo.Resource, + Subresource: requestInfo.Subresource, + Namespace: metaAccessor.GetNamespace(), Key: key, - Name: metaAccessor.GetName(), + Uid: metaAccessor.GetName(), Guid: string(metaAccessor.GetUID()), Version: metaAccessor.GetResourceVersion(), Folder: grafanaAccessor.GetFolder(), diff --git a/pkg/services/store/entity/client_wrapper.go b/pkg/services/store/entity/client_wrapper.go index a0a085057a5..d4dadae9414 100644 --- a/pkg/services/store/entity/client_wrapper.go +++ b/pkg/services/store/entity/client_wrapper.go @@ -33,13 +33,6 @@ func (c *entityStoreClientWrapper) BatchRead(ctx context.Context, in *BatchReadE } return c.EntityStoreClient.BatchRead(ctx, in) } -func (c *entityStoreClientWrapper) Write(ctx context.Context, in *WriteEntityRequest) (*WriteEntityResponse, error) { - ctx, err := c.wrapContext(ctx) - if err != nil { - return nil, err - } - return c.EntityStoreClient.Write(ctx, in) -} func (c *entityStoreClientWrapper) Create(ctx context.Context, in *CreateEntityRequest) (*CreateEntityResponse, error) { ctx, err := c.wrapContext(ctx) if err != nil { @@ -96,15 +89,6 @@ func (c *entityStoreClientWrapper) wrapContext(ctx context.Context) (context.Con return ctx, nil } -// TEMPORARY... while we split this into a new service (see below) -func (c *entityStoreClientWrapper) AdminWrite(ctx context.Context, in *AdminWriteEntityRequest) (*WriteEntityResponse, error) { - ctx, err := c.wrapContext(ctx) - if err != nil { - return nil, err - } - return c.EntityStoreClient.AdminWrite(ctx, in) -} - func NewEntityStoreClientWrapper(cc grpc.ClientConnInterface) EntityStoreServer { return &entityStoreClientWrapper{&entityStoreClient{cc}} } diff --git a/pkg/services/store/entity/dummy/fake_store.go b/pkg/services/store/entity/dummy/fake_store.go index 6ab834c2b51..d0410e4da80 100644 --- a/pkg/services/store/entity/dummy/fake_store.go +++ b/pkg/services/store/entity/dummy/fake_store.go @@ -9,7 +9,6 @@ import ( // Make sure we implement both store + admin var _ entity.EntityStoreServer = &fakeEntityStore{} -var _ entity.EntityStoreAdminServer = &fakeEntityStore{} func ProvideFakeEntityServer() entity.EntityStoreServer { return &fakeEntityStore{} @@ -17,14 +16,6 @@ func ProvideFakeEntityServer() entity.EntityStoreServer { type fakeEntityStore struct{} -func (i fakeEntityStore) AdminWrite(ctx context.Context, r *entity.AdminWriteEntityRequest) (*entity.WriteEntityResponse, error) { - return nil, fmt.Errorf("unimplemented") -} - -func (i fakeEntityStore) Write(ctx context.Context, r *entity.WriteEntityRequest) (*entity.WriteEntityResponse, error) { - return nil, fmt.Errorf("unimplemented") -} - func (i fakeEntityStore) Create(ctx context.Context, r *entity.CreateEntityRequest) (*entity.CreateEntityResponse, error) { return nil, fmt.Errorf("unimplemented") } diff --git a/pkg/services/store/entity/entity.pb.go b/pkg/services/store/entity/entity.pb.go index 3f810074a1e..a8cdf691255 100644 --- a/pkg/services/store/entity/entity.pb.go +++ b/pkg/services/store/entity/entity.pb.go @@ -7,7 +7,6 @@ package entity import ( - grn "github.com/grafana/grafana/pkg/infra/grn" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -21,59 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// Status enumeration -type WriteEntityResponse_Status int32 - -const ( - WriteEntityResponse_ERROR WriteEntityResponse_Status = 0 - WriteEntityResponse_CREATED WriteEntityResponse_Status = 1 - WriteEntityResponse_UPDATED WriteEntityResponse_Status = 2 - WriteEntityResponse_UNCHANGED WriteEntityResponse_Status = 3 -) - -// Enum value maps for WriteEntityResponse_Status. -var ( - WriteEntityResponse_Status_name = map[int32]string{ - 0: "ERROR", - 1: "CREATED", - 2: "UPDATED", - 3: "UNCHANGED", - } - WriteEntityResponse_Status_value = map[string]int32{ - "ERROR": 0, - "CREATED": 1, - "UPDATED": 2, - "UNCHANGED": 3, - } -) - -func (x WriteEntityResponse_Status) Enum() *WriteEntityResponse_Status { - p := new(WriteEntityResponse_Status) - *p = x - return p -} - -func (x WriteEntityResponse_Status) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (WriteEntityResponse_Status) Descriptor() protoreflect.EnumDescriptor { - return file_entity_proto_enumTypes[0].Descriptor() -} - -func (WriteEntityResponse_Status) Type() protoreflect.EnumType { - return &file_entity_proto_enumTypes[0] -} - -func (x WriteEntityResponse_Status) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use WriteEntityResponse_Status.Descriptor instead. -func (WriteEntityResponse_Status) EnumDescriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{8, 0} -} - // Status enumeration type CreateEntityResponse_Status int32 @@ -105,11 +51,11 @@ func (x CreateEntityResponse_Status) String() string { } func (CreateEntityResponse_Status) Descriptor() protoreflect.EnumDescriptor { - return file_entity_proto_enumTypes[1].Descriptor() + return file_entity_proto_enumTypes[0].Descriptor() } func (CreateEntityResponse_Status) Type() protoreflect.EnumType { - return &file_entity_proto_enumTypes[1] + return &file_entity_proto_enumTypes[0] } func (x CreateEntityResponse_Status) Number() protoreflect.EnumNumber { @@ -118,7 +64,7 @@ func (x CreateEntityResponse_Status) Number() protoreflect.EnumNumber { // Deprecated: Use CreateEntityResponse_Status.Descriptor instead. func (CreateEntityResponse_Status) EnumDescriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{10, 0} + return file_entity_proto_rawDescGZIP(), []int{7, 0} } // Status enumeration @@ -155,11 +101,11 @@ func (x UpdateEntityResponse_Status) String() string { } func (UpdateEntityResponse_Status) Descriptor() protoreflect.EnumDescriptor { - return file_entity_proto_enumTypes[2].Descriptor() + return file_entity_proto_enumTypes[1].Descriptor() } func (UpdateEntityResponse_Status) Type() protoreflect.EnumType { - return &file_entity_proto_enumTypes[2] + return &file_entity_proto_enumTypes[1] } func (x UpdateEntityResponse_Status) Number() protoreflect.EnumNumber { @@ -168,7 +114,7 @@ func (x UpdateEntityResponse_Status) Number() protoreflect.EnumNumber { // Deprecated: Use UpdateEntityResponse_Status.Descriptor instead. func (UpdateEntityResponse_Status) EnumDescriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{12, 0} + return file_entity_proto_rawDescGZIP(), []int{9, 0} } // Status enumeration @@ -205,11 +151,11 @@ func (x DeleteEntityResponse_Status) String() string { } func (DeleteEntityResponse_Status) Descriptor() protoreflect.EnumDescriptor { - return file_entity_proto_enumTypes[3].Descriptor() + return file_entity_proto_enumTypes[2].Descriptor() } func (DeleteEntityResponse_Status) Type() protoreflect.EnumType { - return &file_entity_proto_enumTypes[3] + return &file_entity_proto_enumTypes[2] } func (x DeleteEntityResponse_Status) Number() protoreflect.EnumNumber { @@ -218,7 +164,7 @@ func (x DeleteEntityResponse_Status) Number() protoreflect.EnumNumber { // Deprecated: Use DeleteEntityResponse_Status.Descriptor instead. func (DeleteEntityResponse_Status) EnumDescriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{14, 0} + return file_entity_proto_rawDescGZIP(), []int{11, 0} } // Status enumeration @@ -255,11 +201,11 @@ func (x EntityWatchResponse_Action) String() string { } func (EntityWatchResponse_Action) Descriptor() protoreflect.EnumDescriptor { - return file_entity_proto_enumTypes[4].Descriptor() + return file_entity_proto_enumTypes[3].Descriptor() } func (EntityWatchResponse_Action) Type() protoreflect.EnumType { - return &file_entity_proto_enumTypes[4] + return &file_entity_proto_enumTypes[3] } func (x EntityWatchResponse_Action) Number() protoreflect.EnumNumber { @@ -268,7 +214,7 @@ func (x EntityWatchResponse_Action) Number() protoreflect.EnumNumber { // Deprecated: Use EntityWatchResponse_Action.Descriptor instead. func (EntityWatchResponse_Action) EnumDescriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{21, 0} + return file_entity_proto_rawDescGZIP(), []int{18, 0} } // The canonical entity/document data -- this represents the raw bytes and storage level metadata @@ -281,9 +227,17 @@ type Entity struct { Guid string `protobuf:"bytes,1,opt,name=guid,proto3" json:"guid,omitempty"` // The resourceVersion -- it will change whenever anythign on the object is saved Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - // Entity identifier -- tenant_id, kind, uid - GRN *grn.GRN `protobuf:"bytes,3,opt,name=GRN,proto3" json:"GRN,omitempty"` - // group version of the entity + // group + Group string `protobuf:"bytes,24,opt,name=group,proto3" json:"group,omitempty"` + // kind resource + Resource string `protobuf:"bytes,25,opt,name=resource,proto3" json:"resource,omitempty"` + // namespace + Namespace string `protobuf:"bytes,26,opt,name=namespace,proto3" json:"namespace,omitempty"` + // k8s name + Uid string `protobuf:"bytes,27,opt,name=uid,proto3" json:"uid,omitempty"` + // subresource + Subresource string `protobuf:"bytes,28,opt,name=subresource,proto3" json:"subresource,omitempty"` + // group version GroupVersion string `protobuf:"bytes,23,opt,name=group_version,json=groupVersion,proto3" json:"group_version,omitempty"` // k8s key value Key string `protobuf:"bytes,22,opt,name=key,proto3" json:"key,omitempty"` @@ -371,11 +325,39 @@ func (x *Entity) GetVersion() string { return "" } -func (x *Entity) GetGRN() *grn.GRN { +func (x *Entity) GetGroup() string { if x != nil { - return x.GRN + return x.Group } - return nil + return "" +} + +func (x *Entity) GetResource() string { + if x != nil { + return x.Resource + } + return "" +} + +func (x *Entity) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Entity) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +func (x *Entity) GetSubresource() string { + if x != nil { + return x.Subresource + } + return "" } func (x *Entity) GetGroupVersion() string { @@ -659,18 +641,13 @@ type ReadEntityRequest struct { unknownFields protoimpl.UnknownFields // Entity identifier - GRN *grn.GRN `protobuf:"bytes,1,opt,name=GRN,proto3" json:"GRN,omitempty"` - Key string `protobuf:"bytes,7,opt,name=key,proto3" json:"key,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // Fetch an explicit version (default is latest) Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - // Include the full meta bytes - WithMeta bool `protobuf:"varint,3,opt,name=with_meta,json=withMeta,proto3" json:"with_meta,omitempty"` - // Include the full body bytes + // Include the full body WithBody bool `protobuf:"varint,4,opt,name=with_body,json=withBody,proto3" json:"with_body,omitempty"` - // Include the status bytes (ignored for now) + // Include the status WithStatus bool `protobuf:"varint,5,opt,name=with_status,json=withStatus,proto3" json:"with_status,omitempty"` - // Include derived summary metadata - WithSummary bool `protobuf:"varint,6,opt,name=with_summary,json=withSummary,proto3" json:"with_summary,omitempty"` } func (x *ReadEntityRequest) Reset() { @@ -705,13 +682,6 @@ func (*ReadEntityRequest) Descriptor() ([]byte, []int) { return file_entity_proto_rawDescGZIP(), []int{3} } -func (x *ReadEntityRequest) GetGRN() *grn.GRN { - if x != nil { - return x.GRN - } - return nil -} - func (x *ReadEntityRequest) GetKey() string { if x != nil { return x.Key @@ -726,13 +696,6 @@ func (x *ReadEntityRequest) GetVersion() string { return "" } -func (x *ReadEntityRequest) GetWithMeta() bool { - if x != nil { - return x.WithMeta - } - return false -} - func (x *ReadEntityRequest) GetWithBody() bool { if x != nil { return x.WithBody @@ -747,13 +710,6 @@ func (x *ReadEntityRequest) GetWithStatus() bool { return false } -func (x *ReadEntityRequest) GetWithSummary() bool { - if x != nil { - return x.WithSummary - } - return false -} - type BatchReadEntityRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -848,200 +804,6 @@ func (x *BatchReadEntityResponse) GetResults() []*Entity { return nil } -type WriteEntityRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Entity details - Entity *Entity `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"` - // Used for optimistic locking. If missing, the previous version will be replaced regardless - PreviousVersion string `protobuf:"bytes,2,opt,name=previous_version,json=previousVersion,proto3" json:"previous_version,omitempty"` -} - -func (x *WriteEntityRequest) Reset() { - *x = WriteEntityRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WriteEntityRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WriteEntityRequest) ProtoMessage() {} - -func (x *WriteEntityRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WriteEntityRequest.ProtoReflect.Descriptor instead. -func (*WriteEntityRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{6} -} - -func (x *WriteEntityRequest) GetEntity() *Entity { - if x != nil { - return x.Entity - } - return nil -} - -func (x *WriteEntityRequest) GetPreviousVersion() string { - if x != nil { - return x.PreviousVersion - } - return "" -} - -// This operation is useful when syncing a resource from external sources -// that have more accurate metadata information (git, or an archive). -// This process can bypass the forced checks that -type AdminWriteEntityRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Entity details - Entity *Entity `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"` - // Used for optimistic locking. If missing, the previous version will be replaced regardless - // This may not be used along with an explicit version in the request - PreviousVersion string `protobuf:"bytes,2,opt,name=previous_version,json=previousVersion,proto3" json:"previous_version,omitempty"` - // Request that all previous versions are removed from the history - // This will make sense for systems that manage history explicitly externallay - ClearHistory bool `protobuf:"varint,3,opt,name=clear_history,json=clearHistory,proto3" json:"clear_history,omitempty"` -} - -func (x *AdminWriteEntityRequest) Reset() { - *x = AdminWriteEntityRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AdminWriteEntityRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AdminWriteEntityRequest) ProtoMessage() {} - -func (x *AdminWriteEntityRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AdminWriteEntityRequest.ProtoReflect.Descriptor instead. -func (*AdminWriteEntityRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{7} -} - -func (x *AdminWriteEntityRequest) GetEntity() *Entity { - if x != nil { - return x.Entity - } - return nil -} - -func (x *AdminWriteEntityRequest) GetPreviousVersion() string { - if x != nil { - return x.PreviousVersion - } - return "" -} - -func (x *AdminWriteEntityRequest) GetClearHistory() bool { - if x != nil { - return x.ClearHistory - } - return false -} - -type WriteEntityResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Error info -- if exists, the save did not happen - Error *EntityErrorInfo `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` - // Entity details - Entity *Entity `protobuf:"bytes,2,opt,name=entity,proto3" json:"entity,omitempty"` - // Status code - Status WriteEntityResponse_Status `protobuf:"varint,3,opt,name=status,proto3,enum=entity.WriteEntityResponse_Status" json:"status,omitempty"` -} - -func (x *WriteEntityResponse) Reset() { - *x = WriteEntityResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WriteEntityResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WriteEntityResponse) ProtoMessage() {} - -func (x *WriteEntityResponse) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WriteEntityResponse.ProtoReflect.Descriptor instead. -func (*WriteEntityResponse) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{8} -} - -func (x *WriteEntityResponse) GetError() *EntityErrorInfo { - if x != nil { - return x.Error - } - return nil -} - -func (x *WriteEntityResponse) GetEntity() *Entity { - if x != nil { - return x.Entity - } - return nil -} - -func (x *WriteEntityResponse) GetStatus() WriteEntityResponse_Status { - if x != nil { - return x.Status - } - return WriteEntityResponse_ERROR -} - type CreateEntityRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1054,7 +816,7 @@ type CreateEntityRequest struct { func (x *CreateEntityRequest) Reset() { *x = CreateEntityRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[9] + mi := &file_entity_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1067,7 +829,7 @@ func (x *CreateEntityRequest) String() string { func (*CreateEntityRequest) ProtoMessage() {} func (x *CreateEntityRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[9] + mi := &file_entity_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1080,7 +842,7 @@ func (x *CreateEntityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateEntityRequest.ProtoReflect.Descriptor instead. func (*CreateEntityRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{9} + return file_entity_proto_rawDescGZIP(), []int{6} } func (x *CreateEntityRequest) GetEntity() *Entity { @@ -1106,7 +868,7 @@ type CreateEntityResponse struct { func (x *CreateEntityResponse) Reset() { *x = CreateEntityResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[10] + mi := &file_entity_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1119,7 +881,7 @@ func (x *CreateEntityResponse) String() string { func (*CreateEntityResponse) ProtoMessage() {} func (x *CreateEntityResponse) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[10] + mi := &file_entity_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1132,7 +894,7 @@ func (x *CreateEntityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateEntityResponse.ProtoReflect.Descriptor instead. func (*CreateEntityResponse) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{10} + return file_entity_proto_rawDescGZIP(), []int{7} } func (x *CreateEntityResponse) GetError() *EntityErrorInfo { @@ -1170,7 +932,7 @@ type UpdateEntityRequest struct { func (x *UpdateEntityRequest) Reset() { *x = UpdateEntityRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[11] + mi := &file_entity_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1183,7 +945,7 @@ func (x *UpdateEntityRequest) String() string { func (*UpdateEntityRequest) ProtoMessage() {} func (x *UpdateEntityRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[11] + mi := &file_entity_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1196,7 +958,7 @@ func (x *UpdateEntityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateEntityRequest.ProtoReflect.Descriptor instead. func (*UpdateEntityRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{11} + return file_entity_proto_rawDescGZIP(), []int{8} } func (x *UpdateEntityRequest) GetEntity() *Entity { @@ -1229,7 +991,7 @@ type UpdateEntityResponse struct { func (x *UpdateEntityResponse) Reset() { *x = UpdateEntityResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[12] + mi := &file_entity_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1242,7 +1004,7 @@ func (x *UpdateEntityResponse) String() string { func (*UpdateEntityResponse) ProtoMessage() {} func (x *UpdateEntityResponse) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[12] + mi := &file_entity_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1255,7 +1017,7 @@ func (x *UpdateEntityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateEntityResponse.ProtoReflect.Descriptor instead. func (*UpdateEntityResponse) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{12} + return file_entity_proto_rawDescGZIP(), []int{9} } func (x *UpdateEntityResponse) GetError() *EntityErrorInfo { @@ -1285,8 +1047,7 @@ type DeleteEntityRequest struct { unknownFields protoimpl.UnknownFields // Entity identifier - GRN *grn.GRN `protobuf:"bytes,1,opt,name=GRN,proto3" json:"GRN,omitempty"` - Key string `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // Used for optimistic locking. If missing, the current version will be deleted regardless PreviousVersion string `protobuf:"bytes,2,opt,name=previous_version,json=previousVersion,proto3" json:"previous_version,omitempty"` } @@ -1294,7 +1055,7 @@ type DeleteEntityRequest struct { func (x *DeleteEntityRequest) Reset() { *x = DeleteEntityRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[13] + mi := &file_entity_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1307,7 +1068,7 @@ func (x *DeleteEntityRequest) String() string { func (*DeleteEntityRequest) ProtoMessage() {} func (x *DeleteEntityRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[13] + mi := &file_entity_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1320,14 +1081,7 @@ func (x *DeleteEntityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteEntityRequest.ProtoReflect.Descriptor instead. func (*DeleteEntityRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{13} -} - -func (x *DeleteEntityRequest) GetGRN() *grn.GRN { - if x != nil { - return x.GRN - } - return nil + return file_entity_proto_rawDescGZIP(), []int{10} } func (x *DeleteEntityRequest) GetKey() string { @@ -1360,7 +1114,7 @@ type DeleteEntityResponse struct { func (x *DeleteEntityResponse) Reset() { *x = DeleteEntityResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[14] + mi := &file_entity_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1373,7 +1127,7 @@ func (x *DeleteEntityResponse) String() string { func (*DeleteEntityResponse) ProtoMessage() {} func (x *DeleteEntityResponse) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[14] + mi := &file_entity_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1386,7 +1140,7 @@ func (x *DeleteEntityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteEntityResponse.ProtoReflect.Descriptor instead. func (*DeleteEntityResponse) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{14} + return file_entity_proto_rawDescGZIP(), []int{11} } func (x *DeleteEntityResponse) GetError() *EntityErrorInfo { @@ -1416,7 +1170,7 @@ type EntityHistoryRequest struct { unknownFields protoimpl.UnknownFields // Entity identifier - GRN *grn.GRN `protobuf:"bytes,1,opt,name=GRN,proto3" json:"GRN,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // Maximum number of items to return Limit int64 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"` // Starting from the requested page @@ -1426,7 +1180,7 @@ type EntityHistoryRequest struct { func (x *EntityHistoryRequest) Reset() { *x = EntityHistoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[15] + mi := &file_entity_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1439,7 +1193,7 @@ func (x *EntityHistoryRequest) String() string { func (*EntityHistoryRequest) ProtoMessage() {} func (x *EntityHistoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[15] + mi := &file_entity_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1452,14 +1206,14 @@ func (x *EntityHistoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EntityHistoryRequest.ProtoReflect.Descriptor instead. func (*EntityHistoryRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{15} + return file_entity_proto_rawDescGZIP(), []int{12} } -func (x *EntityHistoryRequest) GetGRN() *grn.GRN { +func (x *EntityHistoryRequest) GetKey() string { if x != nil { - return x.GRN + return x.Key } - return nil + return "" } func (x *EntityHistoryRequest) GetLimit() int64 { @@ -1482,7 +1236,7 @@ type EntityHistoryResponse struct { unknownFields protoimpl.UnknownFields // Entity identifier - GRN *grn.GRN `protobuf:"bytes,1,opt,name=GRN,proto3" json:"GRN,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // Entity metadata without the raw bytes Versions []*Entity `protobuf:"bytes,2,rep,name=versions,proto3" json:"versions,omitempty"` // More results exist... pass this in the next request @@ -1492,7 +1246,7 @@ type EntityHistoryResponse struct { func (x *EntityHistoryResponse) Reset() { *x = EntityHistoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[16] + mi := &file_entity_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1505,7 +1259,7 @@ func (x *EntityHistoryResponse) String() string { func (*EntityHistoryResponse) ProtoMessage() {} func (x *EntityHistoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[16] + mi := &file_entity_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1518,14 +1272,14 @@ func (x *EntityHistoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EntityHistoryResponse.ProtoReflect.Descriptor instead. func (*EntityHistoryResponse) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{16} + return file_entity_proto_rawDescGZIP(), []int{13} } -func (x *EntityHistoryResponse) GetGRN() *grn.GRN { +func (x *EntityHistoryResponse) GetKey() string { if x != nil { - return x.GRN + return x.Key } - return nil + return "" } func (x *EntityHistoryResponse) GetVersions() []*Entity { @@ -1553,8 +1307,10 @@ type EntityListRequest struct { Limit int64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` // Free text query string -- mileage may vary :) Query string `protobuf:"bytes,3,opt,name=query,proto3" json:"query,omitempty"` - // limit to a specific kind (empty is all) - Kind []string `protobuf:"bytes,4,rep,name=kind,proto3" json:"kind,omitempty"` + // limit to a specific group (empty is all) + Group []string `protobuf:"bytes,9,rep,name=group,proto3" json:"group,omitempty"` + // limit to a specific resource (empty is all) + Resource []string `protobuf:"bytes,4,rep,name=resource,proto3" json:"resource,omitempty"` // limit to a specific key Key []string `protobuf:"bytes,11,rep,name=key,proto3" json:"key,omitempty"` // Limit results to items in a specific folder @@ -1566,15 +1322,13 @@ type EntityListRequest struct { // Return the full body in each payload WithBody bool `protobuf:"varint,8,opt,name=with_body,json=withBody,proto3" json:"with_body,omitempty"` // Return the full body in each payload - WithLabels bool `protobuf:"varint,9,opt,name=with_labels,json=withLabels,proto3" json:"with_labels,omitempty"` - // Return the full body in each payload - WithFields bool `protobuf:"varint,10,opt,name=with_fields,json=withFields,proto3" json:"with_fields,omitempty"` + WithStatus bool `protobuf:"varint,10,opt,name=with_status,json=withStatus,proto3" json:"with_status,omitempty"` } func (x *EntityListRequest) Reset() { *x = EntityListRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[17] + mi := &file_entity_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1587,7 +1341,7 @@ func (x *EntityListRequest) String() string { func (*EntityListRequest) ProtoMessage() {} func (x *EntityListRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[17] + mi := &file_entity_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1600,7 +1354,7 @@ func (x *EntityListRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EntityListRequest.ProtoReflect.Descriptor instead. func (*EntityListRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{17} + return file_entity_proto_rawDescGZIP(), []int{14} } func (x *EntityListRequest) GetNextPageToken() string { @@ -1624,9 +1378,16 @@ func (x *EntityListRequest) GetQuery() string { return "" } -func (x *EntityListRequest) GetKind() []string { +func (x *EntityListRequest) GetGroup() []string { if x != nil { - return x.Kind + return x.Group + } + return nil +} + +func (x *EntityListRequest) GetResource() []string { + if x != nil { + return x.Resource } return nil } @@ -1666,16 +1427,9 @@ func (x *EntityListRequest) GetWithBody() bool { return false } -func (x *EntityListRequest) GetWithLabels() bool { +func (x *EntityListRequest) GetWithStatus() bool { if x != nil { - return x.WithLabels - } - return false -} - -func (x *EntityListRequest) GetWithFields() bool { - if x != nil { - return x.WithFields + return x.WithStatus } return false } @@ -1690,7 +1444,7 @@ type ReferenceRequest struct { // Maximum number of items to return Limit int64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` // Free text query string -- mileage may vary :) - Kind string `protobuf:"bytes,3,opt,name=kind,proto3" json:"kind,omitempty"` + Resource string `protobuf:"bytes,3,opt,name=resource,proto3" json:"resource,omitempty"` // Free text query string -- mileage may vary :) Uid string `protobuf:"bytes,4,opt,name=uid,proto3" json:"uid,omitempty"` } @@ -1698,7 +1452,7 @@ type ReferenceRequest struct { func (x *ReferenceRequest) Reset() { *x = ReferenceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[18] + mi := &file_entity_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1711,7 +1465,7 @@ func (x *ReferenceRequest) String() string { func (*ReferenceRequest) ProtoMessage() {} func (x *ReferenceRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[18] + mi := &file_entity_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1724,7 +1478,7 @@ func (x *ReferenceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReferenceRequest.ProtoReflect.Descriptor instead. func (*ReferenceRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{18} + return file_entity_proto_rawDescGZIP(), []int{15} } func (x *ReferenceRequest) GetNextPageToken() string { @@ -1741,9 +1495,9 @@ func (x *ReferenceRequest) GetLimit() int64 { return 0 } -func (x *ReferenceRequest) GetKind() string { +func (x *ReferenceRequest) GetResource() string { if x != nil { - return x.Kind + return x.Resource } return "" } @@ -1768,7 +1522,7 @@ type EntityListResponse struct { func (x *EntityListResponse) Reset() { *x = EntityListResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[19] + mi := &file_entity_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1781,7 +1535,7 @@ func (x *EntityListResponse) String() string { func (*EntityListResponse) ProtoMessage() {} func (x *EntityListResponse) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[19] + mi := &file_entity_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1794,7 +1548,7 @@ func (x *EntityListResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EntityListResponse.ProtoReflect.Descriptor instead. func (*EntityListResponse) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{19} + return file_entity_proto_rawDescGZIP(), []int{16} } func (x *EntityListResponse) GetResults() []*Entity { @@ -1819,25 +1573,23 @@ type EntityWatchRequest struct { // Timestamp of last changes. Empty will default to Since int64 `protobuf:"varint,1,opt,name=since,proto3" json:"since,omitempty"` // Watch sppecific entities - GRN []*grn.GRN `protobuf:"bytes,2,rep,name=GRN,proto3" json:"GRN,omitempty"` - // limit to a specific kind (empty is all) - Kind []string `protobuf:"bytes,3,rep,name=kind,proto3" json:"kind,omitempty"` + Key []string `protobuf:"bytes,2,rep,name=key,proto3" json:"key,omitempty"` + // limit to a specific resource (empty is all) + Resource []string `protobuf:"bytes,3,rep,name=resource,proto3" json:"resource,omitempty"` // Limit results to items in a specific folder Folder string `protobuf:"bytes,4,opt,name=folder,proto3" json:"folder,omitempty"` // Must match all labels Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Return the full body in each payload WithBody bool `protobuf:"varint,6,opt,name=with_body,json=withBody,proto3" json:"with_body,omitempty"` - // Return the full body in each payload - WithLabels bool `protobuf:"varint,7,opt,name=with_labels,json=withLabels,proto3" json:"with_labels,omitempty"` - // Return the full body in each payload - WithFields bool `protobuf:"varint,8,opt,name=with_fields,json=withFields,proto3" json:"with_fields,omitempty"` + // Return the full status in each payload + WithStatus bool `protobuf:"varint,7,opt,name=with_status,json=withStatus,proto3" json:"with_status,omitempty"` } func (x *EntityWatchRequest) Reset() { *x = EntityWatchRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[20] + mi := &file_entity_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1850,7 +1602,7 @@ func (x *EntityWatchRequest) String() string { func (*EntityWatchRequest) ProtoMessage() {} func (x *EntityWatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[20] + mi := &file_entity_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1863,7 +1615,7 @@ func (x *EntityWatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EntityWatchRequest.ProtoReflect.Descriptor instead. func (*EntityWatchRequest) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{20} + return file_entity_proto_rawDescGZIP(), []int{17} } func (x *EntityWatchRequest) GetSince() int64 { @@ -1873,16 +1625,16 @@ func (x *EntityWatchRequest) GetSince() int64 { return 0 } -func (x *EntityWatchRequest) GetGRN() []*grn.GRN { +func (x *EntityWatchRequest) GetKey() []string { if x != nil { - return x.GRN + return x.Key } return nil } -func (x *EntityWatchRequest) GetKind() []string { +func (x *EntityWatchRequest) GetResource() []string { if x != nil { - return x.Kind + return x.Resource } return nil } @@ -1908,16 +1660,9 @@ func (x *EntityWatchRequest) GetWithBody() bool { return false } -func (x *EntityWatchRequest) GetWithLabels() bool { +func (x *EntityWatchRequest) GetWithStatus() bool { if x != nil { - return x.WithLabels - } - return false -} - -func (x *EntityWatchRequest) GetWithFields() bool { - if x != nil { - return x.WithFields + return x.WithStatus } return false } @@ -1938,7 +1683,7 @@ type EntityWatchResponse struct { func (x *EntityWatchResponse) Reset() { *x = EntityWatchResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[21] + mi := &file_entity_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1951,7 +1696,7 @@ func (x *EntityWatchResponse) String() string { func (*EntityWatchResponse) ProtoMessage() {} func (x *EntityWatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[21] + mi := &file_entity_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1964,7 +1709,7 @@ func (x *EntityWatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EntityWatchResponse.ProtoReflect.Descriptor instead. func (*EntityWatchResponse) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{21} + return file_entity_proto_rawDescGZIP(), []int{18} } func (x *EntityWatchResponse) GetTimestamp() int64 { @@ -2016,7 +1761,7 @@ type EntitySummary struct { func (x *EntitySummary) Reset() { *x = EntitySummary{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[22] + mi := &file_entity_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2029,7 +1774,7 @@ func (x *EntitySummary) String() string { func (*EntitySummary) ProtoMessage() {} func (x *EntitySummary) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[22] + mi := &file_entity_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2042,7 +1787,7 @@ func (x *EntitySummary) ProtoReflect() protoreflect.Message { // Deprecated: Use EntitySummary.ProtoReflect.Descriptor instead. func (*EntitySummary) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{22} + return file_entity_proto_rawDescGZIP(), []int{19} } func (x *EntitySummary) GetUID() string { @@ -2143,7 +1888,7 @@ type EntityExternalReference struct { func (x *EntityExternalReference) Reset() { *x = EntityExternalReference{} if protoimpl.UnsafeEnabled { - mi := &file_entity_proto_msgTypes[23] + mi := &file_entity_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2156,7 +1901,7 @@ func (x *EntityExternalReference) String() string { func (*EntityExternalReference) ProtoMessage() {} func (x *EntityExternalReference) ProtoReflect() protoreflect.Message { - mi := &file_entity_proto_msgTypes[23] + mi := &file_entity_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2169,7 +1914,7 @@ func (x *EntityExternalReference) ProtoReflect() protoreflect.Message { // Deprecated: Use EntityExternalReference.ProtoReflect.Descriptor instead. func (*EntityExternalReference) Descriptor() ([]byte, []int) { - return file_entity_proto_rawDescGZIP(), []int{23} + return file_entity_proto_rawDescGZIP(), []int{20} } func (x *EntityExternalReference) GetFamily() string { @@ -2197,165 +1942,132 @@ var File_entity_proto protoreflect.FileDescriptor var file_entity_proto_rawDesc = []byte{ 0x0a, 0x0c, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x1a, 0x17, 0x70, 0x6b, 0x67, 0x2f, 0x69, 0x6e, 0x66, 0x72, - 0x61, 0x2f, 0x67, 0x72, 0x6e, 0x2f, 0x67, 0x72, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xaa, 0x06, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x75, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x75, 0x69, 0x64, 0x12, 0x18, - 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x03, 0x47, 0x52, 0x4e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x67, 0x72, 0x6e, 0x2e, 0x47, 0x52, 0x4e, 0x52, - 0x03, 0x47, 0x52, 0x4e, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, - 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, - 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x45, - 0x54, 0x61, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x45, 0x54, 0x61, 0x67, 0x12, - 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x1d, 0x0a, - 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x30, 0x0a, 0x06, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, - 0x6c, 0x75, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x12, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x32, 0x0a, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x4c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x12, 0x32, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, - 0x15, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x1a, 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x50, 0x0a, 0x10, - 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x62, - 0x0a, 0x0f, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4a, 0x73, - 0x6f, 0x6e, 0x22, 0xd9, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x47, 0x52, 0x4e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x67, 0x72, 0x6e, 0x2e, 0x47, 0x52, 0x4e, 0x52, - 0x03, 0x47, 0x52, 0x4e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x69, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, - 0x09, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x77, 0x69, 0x74, 0x68, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0a, 0x77, 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x49, - 0x0a, 0x16, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x62, 0x61, 0x74, 0x63, - 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x2e, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x52, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x22, 0x43, 0x0a, 0x17, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x67, - 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x29, 0x0a, 0x10, - 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x91, 0x01, 0x0a, 0x17, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x70, - 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f, - 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x63, - 0x6c, 0x65, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0xe6, 0x01, 0x0a, 0x13, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3c, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, - 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, - 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, - 0x45, 0x44, 0x10, 0x03, 0x22, 0x3d, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x22, 0xcc, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43, 0x72, 0x65, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x92, 0x07, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x67, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x1a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, + 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, + 0x6c, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x64, + 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x45, 0x54, + 0x61, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x45, 0x54, 0x61, 0x67, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x1d, 0x0a, 0x0a, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x30, 0x0a, 0x06, 0x6f, 0x72, + 0x69, 0x67, 0x69, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, + 0x75, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x12, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x32, 0x0a, 0x06, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x4c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, + 0x12, 0x32, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x15, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x1a, 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x50, 0x0a, 0x10, 0x45, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x62, 0x0a, + 0x0f, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4a, 0x73, 0x6f, + 0x6e, 0x22, 0x7d, 0x0a, 0x11, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x69, 0x74, 0x68, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x1f, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x22, 0x49, 0x0a, 0x16, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x22, 0x43, 0x0a, 0x17, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, + 0x22, 0x3d, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, + 0xcc, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, + 0x3b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x23, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x20, 0x0a, 0x06, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x22, 0x68, + 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x29, 0x0a, + 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, + 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xdb, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x22, 0x20, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, - 0x10, 0x01, 0x22, 0x68, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, - 0x76, 0x69, 0x6f, 0x75, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xdb, 0x01, 0x0a, - 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2f, 0x0a, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0b, - 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x55, - 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x02, 0x22, 0x6e, 0x0a, 0x13, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x47, 0x52, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, - 0x2e, 0x67, 0x72, 0x6e, 0x2e, 0x47, 0x52, 0x4e, 0x52, 0x03, 0x47, 0x52, 0x4e, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, + 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x43, 0x48, 0x41, + 0x4e, 0x47, 0x45, 0x44, 0x10, 0x02, 0x22, 0x52, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xda, 0x01, 0x0a, 0x14, 0x44, @@ -2372,54 +2084,53 @@ var file_entity_proto_rawDesc = []byte{ 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2e, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x54, - 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x22, 0x70, 0x0a, 0x14, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x22, 0x66, 0x0a, 0x14, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1a, 0x0a, 0x03, 0x47, 0x52, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x67, - 0x72, 0x6e, 0x2e, 0x47, 0x52, 0x4e, 0x52, 0x03, 0x47, 0x52, 0x4e, 0x12, 0x14, 0x0a, 0x05, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, - 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x03, 0x47, 0x52, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x08, 0x2e, 0x67, 0x72, 0x6e, 0x2e, 0x47, 0x52, 0x4e, 0x52, 0x03, 0x47, 0x52, 0x4e, 0x12, - 0x2a, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, - 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x22, 0x92, 0x03, 0x0a, 0x11, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, - 0x73, 0x74, 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, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x06, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6f, - 0x72, 0x74, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x12, 0x1b, - 0x0a, 0x09, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x77, 0x69, 0x74, 0x68, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1f, 0x0a, 0x0b, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x39, 0x0a, - 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x76, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 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, 0x12, 0x0a, 0x04, 0x6b, 0x69, - 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x10, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, + 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, + 0x7d, 0x0a, 0x15, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x08, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, + 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8f, + 0x03, 0x0a, 0x11, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 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, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1a, + 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, + 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, + 0x6c, 0x64, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x69, 0x74, 0x68, 0x5f, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x69, 0x74, 0x68, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x7e, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 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, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x66, 0x0a, 0x12, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, @@ -2427,135 +2138,118 @@ var file_entity_proto_rawDesc = []byte{ 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 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, 0x22, 0xcc, 0x02, 0x0a, 0x12, 0x45, 0x6e, 0x74, + 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa9, 0x02, 0x0a, 0x12, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 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, 0x1a, 0x0a, 0x03, 0x47, 0x52, 0x4e, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x67, 0x72, 0x6e, 0x2e, 0x47, 0x52, 0x4e, 0x52, 0x03, 0x47, 0x52, - 0x4e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x3e, 0x0a, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, - 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1b, 0x0a, - 0x09, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x77, 0x69, 0x74, 0x68, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0a, 0x77, 0x69, 0x74, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x39, 0x0a, 0x0b, - 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc8, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x26, 0x0a, - 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x22, 0x2f, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, - 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, - 0x10, 0x02, 0x22, 0xa2, 0x04, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x55, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x39, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, - 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, - 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x2d, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, - 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x39, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, - 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, - 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, - 0x12, 0x3f, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x0b, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39, 0x0a, 0x0b, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x65, 0x0a, 0x17, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x73, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x06, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x77, + 0x69, 0x74, 0x68, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x77, 0x69, 0x74, 0x68, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x77, + 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc8, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x26, 0x0a, 0x06, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, + 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, + 0xa2, 0x04, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x55, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, + 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x64, + 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x73, 0x6c, 0x75, 0x67, 0x12, 0x2d, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x12, 0x39, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x09, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x2d, + 0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x3f, 0x0a, + 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, - 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x32, 0xb6, - 0x05, 0x0a, 0x0b, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x31, - 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, - 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x12, 0x4c, 0x0a, 0x09, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x12, 0x1e, - 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, - 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, - 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, - 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x40, 0x0a, 0x05, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x43, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x63, 0x65, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x1a, 0x39, + 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x65, 0x0a, 0x17, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x32, 0xa8, 0x04, 0x0a, 0x0b, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x52, + 0x65, 0x61, 0x64, 0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x52, 0x65, 0x61, + 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, + 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x4c, + 0x0a, 0x09, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x12, 0x1e, 0x2e, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x64, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x06, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x43, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x46, 0x0a, 0x07, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x6e, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, - 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4a, 0x0a, 0x0a, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x5e, 0x0a, 0x10, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x4a, 0x0a, 0x0a, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x36, 0x5a, 0x34, 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, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x42, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1a, 0x2e, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x36, 0x5a, 0x34, 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, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2570,113 +2264,91 @@ func file_entity_proto_rawDescGZIP() []byte { return file_entity_proto_rawDescData } -var file_entity_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_entity_proto_msgTypes = make([]protoimpl.MessageInfo, 30) +var file_entity_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_entity_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_entity_proto_goTypes = []interface{}{ - (WriteEntityResponse_Status)(0), // 0: entity.WriteEntityResponse.Status - (CreateEntityResponse_Status)(0), // 1: entity.CreateEntityResponse.Status - (UpdateEntityResponse_Status)(0), // 2: entity.UpdateEntityResponse.Status - (DeleteEntityResponse_Status)(0), // 3: entity.DeleteEntityResponse.Status - (EntityWatchResponse_Action)(0), // 4: entity.EntityWatchResponse.Action - (*Entity)(nil), // 5: entity.Entity - (*EntityOriginInfo)(nil), // 6: entity.EntityOriginInfo - (*EntityErrorInfo)(nil), // 7: entity.EntityErrorInfo - (*ReadEntityRequest)(nil), // 8: entity.ReadEntityRequest - (*BatchReadEntityRequest)(nil), // 9: entity.BatchReadEntityRequest - (*BatchReadEntityResponse)(nil), // 10: entity.BatchReadEntityResponse - (*WriteEntityRequest)(nil), // 11: entity.WriteEntityRequest - (*AdminWriteEntityRequest)(nil), // 12: entity.AdminWriteEntityRequest - (*WriteEntityResponse)(nil), // 13: entity.WriteEntityResponse - (*CreateEntityRequest)(nil), // 14: entity.CreateEntityRequest - (*CreateEntityResponse)(nil), // 15: entity.CreateEntityResponse - (*UpdateEntityRequest)(nil), // 16: entity.UpdateEntityRequest - (*UpdateEntityResponse)(nil), // 17: entity.UpdateEntityResponse - (*DeleteEntityRequest)(nil), // 18: entity.DeleteEntityRequest - (*DeleteEntityResponse)(nil), // 19: entity.DeleteEntityResponse - (*EntityHistoryRequest)(nil), // 20: entity.EntityHistoryRequest - (*EntityHistoryResponse)(nil), // 21: entity.EntityHistoryResponse - (*EntityListRequest)(nil), // 22: entity.EntityListRequest - (*ReferenceRequest)(nil), // 23: entity.ReferenceRequest - (*EntityListResponse)(nil), // 24: entity.EntityListResponse - (*EntityWatchRequest)(nil), // 25: entity.EntityWatchRequest - (*EntityWatchResponse)(nil), // 26: entity.EntityWatchResponse - (*EntitySummary)(nil), // 27: entity.EntitySummary - (*EntityExternalReference)(nil), // 28: entity.EntityExternalReference - nil, // 29: entity.Entity.LabelsEntry - nil, // 30: entity.Entity.FieldsEntry - nil, // 31: entity.EntityListRequest.LabelsEntry - nil, // 32: entity.EntityWatchRequest.LabelsEntry - nil, // 33: entity.EntitySummary.LabelsEntry - nil, // 34: entity.EntitySummary.FieldsEntry - (*grn.GRN)(nil), // 35: grn.GRN + (CreateEntityResponse_Status)(0), // 0: entity.CreateEntityResponse.Status + (UpdateEntityResponse_Status)(0), // 1: entity.UpdateEntityResponse.Status + (DeleteEntityResponse_Status)(0), // 2: entity.DeleteEntityResponse.Status + (EntityWatchResponse_Action)(0), // 3: entity.EntityWatchResponse.Action + (*Entity)(nil), // 4: entity.Entity + (*EntityOriginInfo)(nil), // 5: entity.EntityOriginInfo + (*EntityErrorInfo)(nil), // 6: entity.EntityErrorInfo + (*ReadEntityRequest)(nil), // 7: entity.ReadEntityRequest + (*BatchReadEntityRequest)(nil), // 8: entity.BatchReadEntityRequest + (*BatchReadEntityResponse)(nil), // 9: entity.BatchReadEntityResponse + (*CreateEntityRequest)(nil), // 10: entity.CreateEntityRequest + (*CreateEntityResponse)(nil), // 11: entity.CreateEntityResponse + (*UpdateEntityRequest)(nil), // 12: entity.UpdateEntityRequest + (*UpdateEntityResponse)(nil), // 13: entity.UpdateEntityResponse + (*DeleteEntityRequest)(nil), // 14: entity.DeleteEntityRequest + (*DeleteEntityResponse)(nil), // 15: entity.DeleteEntityResponse + (*EntityHistoryRequest)(nil), // 16: entity.EntityHistoryRequest + (*EntityHistoryResponse)(nil), // 17: entity.EntityHistoryResponse + (*EntityListRequest)(nil), // 18: entity.EntityListRequest + (*ReferenceRequest)(nil), // 19: entity.ReferenceRequest + (*EntityListResponse)(nil), // 20: entity.EntityListResponse + (*EntityWatchRequest)(nil), // 21: entity.EntityWatchRequest + (*EntityWatchResponse)(nil), // 22: entity.EntityWatchResponse + (*EntitySummary)(nil), // 23: entity.EntitySummary + (*EntityExternalReference)(nil), // 24: entity.EntityExternalReference + nil, // 25: entity.Entity.LabelsEntry + nil, // 26: entity.Entity.FieldsEntry + nil, // 27: entity.EntityListRequest.LabelsEntry + nil, // 28: entity.EntityWatchRequest.LabelsEntry + nil, // 29: entity.EntitySummary.LabelsEntry + nil, // 30: entity.EntitySummary.FieldsEntry } var file_entity_proto_depIdxs = []int32{ - 35, // 0: entity.Entity.GRN:type_name -> grn.GRN - 6, // 1: entity.Entity.origin:type_name -> entity.EntityOriginInfo - 29, // 2: entity.Entity.labels:type_name -> entity.Entity.LabelsEntry - 30, // 3: entity.Entity.fields:type_name -> entity.Entity.FieldsEntry - 7, // 4: entity.Entity.errors:type_name -> entity.EntityErrorInfo - 35, // 5: entity.ReadEntityRequest.GRN:type_name -> grn.GRN - 8, // 6: entity.BatchReadEntityRequest.batch:type_name -> entity.ReadEntityRequest - 5, // 7: entity.BatchReadEntityResponse.results:type_name -> entity.Entity - 5, // 8: entity.WriteEntityRequest.entity:type_name -> entity.Entity - 5, // 9: entity.AdminWriteEntityRequest.entity:type_name -> entity.Entity - 7, // 10: entity.WriteEntityResponse.error:type_name -> entity.EntityErrorInfo - 5, // 11: entity.WriteEntityResponse.entity:type_name -> entity.Entity - 0, // 12: entity.WriteEntityResponse.status:type_name -> entity.WriteEntityResponse.Status - 5, // 13: entity.CreateEntityRequest.entity:type_name -> entity.Entity - 7, // 14: entity.CreateEntityResponse.error:type_name -> entity.EntityErrorInfo - 5, // 15: entity.CreateEntityResponse.entity:type_name -> entity.Entity - 1, // 16: entity.CreateEntityResponse.status:type_name -> entity.CreateEntityResponse.Status - 5, // 17: entity.UpdateEntityRequest.entity:type_name -> entity.Entity - 7, // 18: entity.UpdateEntityResponse.error:type_name -> entity.EntityErrorInfo - 5, // 19: entity.UpdateEntityResponse.entity:type_name -> entity.Entity - 2, // 20: entity.UpdateEntityResponse.status:type_name -> entity.UpdateEntityResponse.Status - 35, // 21: entity.DeleteEntityRequest.GRN:type_name -> grn.GRN - 7, // 22: entity.DeleteEntityResponse.error:type_name -> entity.EntityErrorInfo - 5, // 23: entity.DeleteEntityResponse.entity:type_name -> entity.Entity - 3, // 24: entity.DeleteEntityResponse.status:type_name -> entity.DeleteEntityResponse.Status - 35, // 25: entity.EntityHistoryRequest.GRN:type_name -> grn.GRN - 35, // 26: entity.EntityHistoryResponse.GRN:type_name -> grn.GRN - 5, // 27: entity.EntityHistoryResponse.versions:type_name -> entity.Entity - 31, // 28: entity.EntityListRequest.labels:type_name -> entity.EntityListRequest.LabelsEntry - 5, // 29: entity.EntityListResponse.results:type_name -> entity.Entity - 35, // 30: entity.EntityWatchRequest.GRN:type_name -> grn.GRN - 32, // 31: entity.EntityWatchRequest.labels:type_name -> entity.EntityWatchRequest.LabelsEntry - 5, // 32: entity.EntityWatchResponse.entity:type_name -> entity.Entity - 4, // 33: entity.EntityWatchResponse.action:type_name -> entity.EntityWatchResponse.Action - 33, // 34: entity.EntitySummary.labels:type_name -> entity.EntitySummary.LabelsEntry - 7, // 35: entity.EntitySummary.error:type_name -> entity.EntityErrorInfo - 34, // 36: entity.EntitySummary.fields:type_name -> entity.EntitySummary.FieldsEntry - 27, // 37: entity.EntitySummary.nested:type_name -> entity.EntitySummary - 28, // 38: entity.EntitySummary.references:type_name -> entity.EntityExternalReference - 8, // 39: entity.EntityStore.Read:input_type -> entity.ReadEntityRequest - 9, // 40: entity.EntityStore.BatchRead:input_type -> entity.BatchReadEntityRequest - 11, // 41: entity.EntityStore.Write:input_type -> entity.WriteEntityRequest - 14, // 42: entity.EntityStore.Create:input_type -> entity.CreateEntityRequest - 16, // 43: entity.EntityStore.Update:input_type -> entity.UpdateEntityRequest - 18, // 44: entity.EntityStore.Delete:input_type -> entity.DeleteEntityRequest - 20, // 45: entity.EntityStore.History:input_type -> entity.EntityHistoryRequest - 22, // 46: entity.EntityStore.List:input_type -> entity.EntityListRequest - 25, // 47: entity.EntityStore.Watch:input_type -> entity.EntityWatchRequest - 12, // 48: entity.EntityStore.AdminWrite:input_type -> entity.AdminWriteEntityRequest - 12, // 49: entity.EntityStoreAdmin.AdminWrite:input_type -> entity.AdminWriteEntityRequest - 5, // 50: entity.EntityStore.Read:output_type -> entity.Entity - 10, // 51: entity.EntityStore.BatchRead:output_type -> entity.BatchReadEntityResponse - 13, // 52: entity.EntityStore.Write:output_type -> entity.WriteEntityResponse - 15, // 53: entity.EntityStore.Create:output_type -> entity.CreateEntityResponse - 17, // 54: entity.EntityStore.Update:output_type -> entity.UpdateEntityResponse - 19, // 55: entity.EntityStore.Delete:output_type -> entity.DeleteEntityResponse - 21, // 56: entity.EntityStore.History:output_type -> entity.EntityHistoryResponse - 24, // 57: entity.EntityStore.List:output_type -> entity.EntityListResponse - 26, // 58: entity.EntityStore.Watch:output_type -> entity.EntityWatchResponse - 13, // 59: entity.EntityStore.AdminWrite:output_type -> entity.WriteEntityResponse - 13, // 60: entity.EntityStoreAdmin.AdminWrite:output_type -> entity.WriteEntityResponse - 50, // [50:61] is the sub-list for method output_type - 39, // [39:50] is the sub-list for method input_type - 39, // [39:39] is the sub-list for extension type_name - 39, // [39:39] is the sub-list for extension extendee - 0, // [0:39] is the sub-list for field type_name + 5, // 0: entity.Entity.origin:type_name -> entity.EntityOriginInfo + 25, // 1: entity.Entity.labels:type_name -> entity.Entity.LabelsEntry + 26, // 2: entity.Entity.fields:type_name -> entity.Entity.FieldsEntry + 6, // 3: entity.Entity.errors:type_name -> entity.EntityErrorInfo + 7, // 4: entity.BatchReadEntityRequest.batch:type_name -> entity.ReadEntityRequest + 4, // 5: entity.BatchReadEntityResponse.results:type_name -> entity.Entity + 4, // 6: entity.CreateEntityRequest.entity:type_name -> entity.Entity + 6, // 7: entity.CreateEntityResponse.error:type_name -> entity.EntityErrorInfo + 4, // 8: entity.CreateEntityResponse.entity:type_name -> entity.Entity + 0, // 9: entity.CreateEntityResponse.status:type_name -> entity.CreateEntityResponse.Status + 4, // 10: entity.UpdateEntityRequest.entity:type_name -> entity.Entity + 6, // 11: entity.UpdateEntityResponse.error:type_name -> entity.EntityErrorInfo + 4, // 12: entity.UpdateEntityResponse.entity:type_name -> entity.Entity + 1, // 13: entity.UpdateEntityResponse.status:type_name -> entity.UpdateEntityResponse.Status + 6, // 14: entity.DeleteEntityResponse.error:type_name -> entity.EntityErrorInfo + 4, // 15: entity.DeleteEntityResponse.entity:type_name -> entity.Entity + 2, // 16: entity.DeleteEntityResponse.status:type_name -> entity.DeleteEntityResponse.Status + 4, // 17: entity.EntityHistoryResponse.versions:type_name -> entity.Entity + 27, // 18: entity.EntityListRequest.labels:type_name -> entity.EntityListRequest.LabelsEntry + 4, // 19: entity.EntityListResponse.results:type_name -> entity.Entity + 28, // 20: entity.EntityWatchRequest.labels:type_name -> entity.EntityWatchRequest.LabelsEntry + 4, // 21: entity.EntityWatchResponse.entity:type_name -> entity.Entity + 3, // 22: entity.EntityWatchResponse.action:type_name -> entity.EntityWatchResponse.Action + 29, // 23: entity.EntitySummary.labels:type_name -> entity.EntitySummary.LabelsEntry + 6, // 24: entity.EntitySummary.error:type_name -> entity.EntityErrorInfo + 30, // 25: entity.EntitySummary.fields:type_name -> entity.EntitySummary.FieldsEntry + 23, // 26: entity.EntitySummary.nested:type_name -> entity.EntitySummary + 24, // 27: entity.EntitySummary.references:type_name -> entity.EntityExternalReference + 7, // 28: entity.EntityStore.Read:input_type -> entity.ReadEntityRequest + 8, // 29: entity.EntityStore.BatchRead:input_type -> entity.BatchReadEntityRequest + 10, // 30: entity.EntityStore.Create:input_type -> entity.CreateEntityRequest + 12, // 31: entity.EntityStore.Update:input_type -> entity.UpdateEntityRequest + 14, // 32: entity.EntityStore.Delete:input_type -> entity.DeleteEntityRequest + 16, // 33: entity.EntityStore.History:input_type -> entity.EntityHistoryRequest + 18, // 34: entity.EntityStore.List:input_type -> entity.EntityListRequest + 21, // 35: entity.EntityStore.Watch:input_type -> entity.EntityWatchRequest + 4, // 36: entity.EntityStore.Read:output_type -> entity.Entity + 9, // 37: entity.EntityStore.BatchRead:output_type -> entity.BatchReadEntityResponse + 11, // 38: entity.EntityStore.Create:output_type -> entity.CreateEntityResponse + 13, // 39: entity.EntityStore.Update:output_type -> entity.UpdateEntityResponse + 15, // 40: entity.EntityStore.Delete:output_type -> entity.DeleteEntityResponse + 17, // 41: entity.EntityStore.History:output_type -> entity.EntityHistoryResponse + 20, // 42: entity.EntityStore.List:output_type -> entity.EntityListResponse + 22, // 43: entity.EntityStore.Watch:output_type -> entity.EntityWatchResponse + 36, // [36:44] is the sub-list for method output_type + 28, // [28:36] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name } func init() { file_entity_proto_init() } @@ -2758,42 +2430,6 @@ func file_entity_proto_init() { } } file_entity_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WriteEntityRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_entity_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AdminWriteEntityRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_entity_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WriteEntityResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_entity_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateEntityRequest); i { case 0: return &v.state @@ -2805,7 +2441,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateEntityResponse); i { case 0: return &v.state @@ -2817,7 +2453,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpdateEntityRequest); i { case 0: return &v.state @@ -2829,7 +2465,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpdateEntityResponse); i { case 0: return &v.state @@ -2841,7 +2477,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteEntityRequest); i { case 0: return &v.state @@ -2853,7 +2489,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteEntityResponse); i { case 0: return &v.state @@ -2865,7 +2501,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntityHistoryRequest); i { case 0: return &v.state @@ -2877,7 +2513,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntityHistoryResponse); i { case 0: return &v.state @@ -2889,7 +2525,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntityListRequest); i { case 0: return &v.state @@ -2901,7 +2537,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReferenceRequest); i { case 0: return &v.state @@ -2913,7 +2549,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntityListResponse); i { case 0: return &v.state @@ -2925,7 +2561,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntityWatchRequest); i { case 0: return &v.state @@ -2937,7 +2573,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntityWatchResponse); i { case 0: return &v.state @@ -2949,7 +2585,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntitySummary); i { case 0: return &v.state @@ -2961,7 +2597,7 @@ func file_entity_proto_init() { return nil } } - file_entity_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_entity_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EntityExternalReference); i { case 0: return &v.state @@ -2979,10 +2615,10 @@ func file_entity_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_entity_proto_rawDesc, - NumEnums: 5, - NumMessages: 30, + NumEnums: 4, + NumMessages: 27, NumExtensions: 0, - NumServices: 2, + NumServices: 1, }, GoTypes: file_entity_proto_goTypes, DependencyIndexes: file_entity_proto_depIdxs, diff --git a/pkg/services/store/entity/entity.proto b/pkg/services/store/entity/entity.proto index 69df0a3cf40..b1bae978155 100644 --- a/pkg/services/store/entity/entity.proto +++ b/pkg/services/store/entity/entity.proto @@ -3,8 +3,6 @@ package entity; option go_package = "github.com/grafana/grafana/pkg/services/store/entity"; -import "pkg/infra/grn/grn.proto"; - // The canonical entity/document data -- this represents the raw bytes and storage level metadata message Entity { @@ -14,10 +12,18 @@ message Entity { // The resourceVersion -- it will change whenever anythign on the object is saved string version = 2; - // Entity identifier -- tenant_id, kind, uid - grn.GRN GRN = 3; - - // group version of the entity + // group + string group = 24; + // kind resource + string resource = 25; + // namespace + string namespace = 26; + // k8s name + string uid = 27; + // subresource + string subresource = 28; + + // group version string group_version = 23; // k8s key value @@ -109,28 +115,20 @@ message EntityErrorInfo { message ReadEntityRequest { // Entity identifier - grn.GRN GRN = 1; - - string key = 7; + string key = 1; // Fetch an explicit version (default is latest) string version = 2; - // Include the full meta bytes - bool with_meta = 3; - - // Include the full body bytes + // Include the full body bool with_body = 4; - // Include the status bytes (ignored for now) + // Include the status bool with_status = 5; - - // Include derived summary metadata - bool with_summary = 6; } //------------------------------------------------------ -// Make many read requests at once (by Kind+ID+version) +// Make many read requests at once (by key+version) //------------------------------------------------------ message BatchReadEntityRequest { @@ -141,53 +139,6 @@ message BatchReadEntityResponse { repeated Entity results = 1; } -//----------------------------------------------- -// Write request/response -//----------------------------------------------- - -message WriteEntityRequest { - // Entity details - Entity entity = 1; - - // Used for optimistic locking. If missing, the previous version will be replaced regardless - string previous_version = 2; -} - -// This operation is useful when syncing a resource from external sources -// that have more accurate metadata information (git, or an archive). -// This process can bypass the forced checks that -message AdminWriteEntityRequest { - // Entity details - Entity entity = 1; - - // Used for optimistic locking. If missing, the previous version will be replaced regardless - // This may not be used along with an explicit version in the request - string previous_version = 2; - - // Request that all previous versions are removed from the history - // This will make sense for systems that manage history explicitly externallay - bool clear_history = 3; -} - -message WriteEntityResponse { - // Error info -- if exists, the save did not happen - EntityErrorInfo error = 1; - - // Entity details - Entity entity = 2; - - // Status code - Status status = 3; - - // Status enumeration - enum Status { - ERROR = 0; - CREATED = 1; - UPDATED = 2; - UNCHANGED = 3; - } -} - //----------------------------------------------- // Create request/response //----------------------------------------------- @@ -250,9 +201,7 @@ message UpdateEntityResponse { message DeleteEntityRequest { // Entity identifier - grn.GRN GRN = 1; - - string key = 3; + string key = 1; // Used for optimistic locking. If missing, the current version will be deleted regardless string previous_version = 2; @@ -282,7 +231,7 @@ message DeleteEntityResponse { message EntityHistoryRequest { // Entity identifier - grn.GRN GRN = 1; + string key = 1; // Maximum number of items to return int64 limit = 3; @@ -293,7 +242,7 @@ message EntityHistoryRequest { message EntityHistoryResponse { // Entity identifier - grn.GRN GRN = 1; + string key = 1; // Entity metadata without the raw bytes repeated Entity versions = 2; @@ -317,8 +266,11 @@ message EntityListRequest { // Free text query string -- mileage may vary :) string query = 3; - // limit to a specific kind (empty is all) - repeated string kind = 4; + // limit to a specific group (empty is all) + repeated string group = 9; + + // limit to a specific resource (empty is all) + repeated string resource = 4; // limit to a specific key repeated string key = 11; @@ -336,10 +288,7 @@ message EntityListRequest { bool with_body = 8; // Return the full body in each payload - bool with_labels = 9; - - // Return the full body in each payload - bool with_fields = 10; + bool with_status = 10; } message ReferenceRequest { @@ -350,7 +299,7 @@ message ReferenceRequest { int64 limit = 2; // Free text query string -- mileage may vary :) - string kind = 3; + string resource = 3; // Free text query string -- mileage may vary :) string uid = 4; @@ -372,10 +321,10 @@ message EntityWatchRequest { int64 since = 1; // Watch sppecific entities - repeated grn.GRN GRN = 2; + repeated string key = 2; - // limit to a specific kind (empty is all) - repeated string kind = 3; + // limit to a specific resource (empty is all) + repeated string resource = 3; // Limit results to items in a specific folder string folder = 4; @@ -386,11 +335,8 @@ message EntityWatchRequest { // Return the full body in each payload bool with_body = 6; - // Return the full body in each payload - bool with_labels = 7; - - // Return the full body in each payload - bool with_fields = 8; + // Return the full status in each payload + bool with_status = 7; } message EntityWatchResponse { @@ -465,20 +411,10 @@ message EntityExternalReference { service EntityStore { rpc Read(ReadEntityRequest) returns (Entity); rpc BatchRead(BatchReadEntityRequest) returns (BatchReadEntityResponse); - rpc Write(WriteEntityRequest) returns (WriteEntityResponse); rpc Create(CreateEntityRequest) returns (CreateEntityResponse); rpc Update(UpdateEntityRequest) returns (UpdateEntityResponse); rpc Delete(DeleteEntityRequest) returns (DeleteEntityResponse); rpc History(EntityHistoryRequest) returns (EntityHistoryResponse); rpc List(EntityListRequest) returns (EntityListResponse); rpc Watch(EntityWatchRequest) returns (stream EntityWatchResponse); - - // TEMPORARY... while we split this into a new service (see below) - rpc AdminWrite(AdminWriteEntityRequest) returns (WriteEntityResponse); -} - -// The admin service extends the basic entity store interface, but provides -// more explicit control that can support bulk operations like efficient git sync -service EntityStoreAdmin { - rpc AdminWrite(AdminWriteEntityRequest) returns (WriteEntityResponse); } diff --git a/pkg/services/store/entity/entity_grpc.pb.go b/pkg/services/store/entity/entity_grpc.pb.go index a741a62d179..49342299546 100644 --- a/pkg/services/store/entity/entity_grpc.pb.go +++ b/pkg/services/store/entity/entity_grpc.pb.go @@ -19,16 +19,14 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - EntityStore_Read_FullMethodName = "/entity.EntityStore/Read" - EntityStore_BatchRead_FullMethodName = "/entity.EntityStore/BatchRead" - EntityStore_Write_FullMethodName = "/entity.EntityStore/Write" - EntityStore_Create_FullMethodName = "/entity.EntityStore/Create" - EntityStore_Update_FullMethodName = "/entity.EntityStore/Update" - EntityStore_Delete_FullMethodName = "/entity.EntityStore/Delete" - EntityStore_History_FullMethodName = "/entity.EntityStore/History" - EntityStore_List_FullMethodName = "/entity.EntityStore/List" - EntityStore_Watch_FullMethodName = "/entity.EntityStore/Watch" - EntityStore_AdminWrite_FullMethodName = "/entity.EntityStore/AdminWrite" + EntityStore_Read_FullMethodName = "/entity.EntityStore/Read" + EntityStore_BatchRead_FullMethodName = "/entity.EntityStore/BatchRead" + EntityStore_Create_FullMethodName = "/entity.EntityStore/Create" + EntityStore_Update_FullMethodName = "/entity.EntityStore/Update" + EntityStore_Delete_FullMethodName = "/entity.EntityStore/Delete" + EntityStore_History_FullMethodName = "/entity.EntityStore/History" + EntityStore_List_FullMethodName = "/entity.EntityStore/List" + EntityStore_Watch_FullMethodName = "/entity.EntityStore/Watch" ) // EntityStoreClient is the client API for EntityStore service. @@ -37,15 +35,12 @@ const ( type EntityStoreClient interface { Read(ctx context.Context, in *ReadEntityRequest, opts ...grpc.CallOption) (*Entity, error) BatchRead(ctx context.Context, in *BatchReadEntityRequest, opts ...grpc.CallOption) (*BatchReadEntityResponse, error) - Write(ctx context.Context, in *WriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) Create(ctx context.Context, in *CreateEntityRequest, opts ...grpc.CallOption) (*CreateEntityResponse, error) Update(ctx context.Context, in *UpdateEntityRequest, opts ...grpc.CallOption) (*UpdateEntityResponse, error) Delete(ctx context.Context, in *DeleteEntityRequest, opts ...grpc.CallOption) (*DeleteEntityResponse, error) History(ctx context.Context, in *EntityHistoryRequest, opts ...grpc.CallOption) (*EntityHistoryResponse, error) List(ctx context.Context, in *EntityListRequest, opts ...grpc.CallOption) (*EntityListResponse, error) Watch(ctx context.Context, in *EntityWatchRequest, opts ...grpc.CallOption) (EntityStore_WatchClient, error) - // TEMPORARY... while we split this into a new service (see below) - AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) } type entityStoreClient struct { @@ -74,15 +69,6 @@ func (c *entityStoreClient) BatchRead(ctx context.Context, in *BatchReadEntityRe return out, nil } -func (c *entityStoreClient) Write(ctx context.Context, in *WriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) { - out := new(WriteEntityResponse) - err := c.cc.Invoke(ctx, EntityStore_Write_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *entityStoreClient) Create(ctx context.Context, in *CreateEntityRequest, opts ...grpc.CallOption) (*CreateEntityResponse, error) { out := new(CreateEntityResponse) err := c.cc.Invoke(ctx, EntityStore_Create_FullMethodName, in, out, opts...) @@ -160,30 +146,18 @@ func (x *entityStoreWatchClient) Recv() (*EntityWatchResponse, error) { return m, nil } -func (c *entityStoreClient) AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) { - out := new(WriteEntityResponse) - err := c.cc.Invoke(ctx, EntityStore_AdminWrite_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // EntityStoreServer is the server API for EntityStore service. // All implementations should embed UnimplementedEntityStoreServer // for forward compatibility type EntityStoreServer interface { Read(context.Context, *ReadEntityRequest) (*Entity, error) BatchRead(context.Context, *BatchReadEntityRequest) (*BatchReadEntityResponse, error) - Write(context.Context, *WriteEntityRequest) (*WriteEntityResponse, error) Create(context.Context, *CreateEntityRequest) (*CreateEntityResponse, error) Update(context.Context, *UpdateEntityRequest) (*UpdateEntityResponse, error) Delete(context.Context, *DeleteEntityRequest) (*DeleteEntityResponse, error) History(context.Context, *EntityHistoryRequest) (*EntityHistoryResponse, error) List(context.Context, *EntityListRequest) (*EntityListResponse, error) Watch(*EntityWatchRequest, EntityStore_WatchServer) error - // TEMPORARY... while we split this into a new service (see below) - AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error) } // UnimplementedEntityStoreServer should be embedded to have forward compatible implementations. @@ -196,9 +170,6 @@ func (UnimplementedEntityStoreServer) Read(context.Context, *ReadEntityRequest) func (UnimplementedEntityStoreServer) BatchRead(context.Context, *BatchReadEntityRequest) (*BatchReadEntityResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method BatchRead not implemented") } -func (UnimplementedEntityStoreServer) Write(context.Context, *WriteEntityRequest) (*WriteEntityResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Write not implemented") -} func (UnimplementedEntityStoreServer) Create(context.Context, *CreateEntityRequest) (*CreateEntityResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Create not implemented") } @@ -217,9 +188,6 @@ func (UnimplementedEntityStoreServer) List(context.Context, *EntityListRequest) func (UnimplementedEntityStoreServer) Watch(*EntityWatchRequest, EntityStore_WatchServer) error { return status.Errorf(codes.Unimplemented, "method Watch not implemented") } -func (UnimplementedEntityStoreServer) AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AdminWrite not implemented") -} // UnsafeEntityStoreServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to EntityStoreServer will @@ -268,24 +236,6 @@ func _EntityStore_BatchRead_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } -func _EntityStore_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(WriteEntityRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(EntityStoreServer).Write(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: EntityStore_Write_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(EntityStoreServer).Write(ctx, req.(*WriteEntityRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _EntityStore_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateEntityRequest) if err := dec(in); err != nil { @@ -397,24 +347,6 @@ func (x *entityStoreWatchServer) Send(m *EntityWatchResponse) error { return x.ServerStream.SendMsg(m) } -func _EntityStore_AdminWrite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AdminWriteEntityRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(EntityStoreServer).AdminWrite(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: EntityStore_AdminWrite_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(EntityStoreServer).AdminWrite(ctx, req.(*AdminWriteEntityRequest)) - } - return interceptor(ctx, in, info, handler) -} - // EntityStore_ServiceDesc is the grpc.ServiceDesc for EntityStore service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -430,10 +362,6 @@ var EntityStore_ServiceDesc = grpc.ServiceDesc{ MethodName: "BatchRead", Handler: _EntityStore_BatchRead_Handler, }, - { - MethodName: "Write", - Handler: _EntityStore_Write_Handler, - }, { MethodName: "Create", Handler: _EntityStore_Create_Handler, @@ -454,10 +382,6 @@ var EntityStore_ServiceDesc = grpc.ServiceDesc{ MethodName: "List", Handler: _EntityStore_List_Handler, }, - { - MethodName: "AdminWrite", - Handler: _EntityStore_AdminWrite_Handler, - }, }, Streams: []grpc.StreamDesc{ { @@ -468,91 +392,3 @@ var EntityStore_ServiceDesc = grpc.ServiceDesc{ }, Metadata: "entity.proto", } - -const ( - EntityStoreAdmin_AdminWrite_FullMethodName = "/entity.EntityStoreAdmin/AdminWrite" -) - -// EntityStoreAdminClient is the client API for EntityStoreAdmin service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type EntityStoreAdminClient interface { - AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) -} - -type entityStoreAdminClient struct { - cc grpc.ClientConnInterface -} - -func NewEntityStoreAdminClient(cc grpc.ClientConnInterface) EntityStoreAdminClient { - return &entityStoreAdminClient{cc} -} - -func (c *entityStoreAdminClient) AdminWrite(ctx context.Context, in *AdminWriteEntityRequest, opts ...grpc.CallOption) (*WriteEntityResponse, error) { - out := new(WriteEntityResponse) - err := c.cc.Invoke(ctx, EntityStoreAdmin_AdminWrite_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// EntityStoreAdminServer is the server API for EntityStoreAdmin service. -// All implementations should embed UnimplementedEntityStoreAdminServer -// for forward compatibility -type EntityStoreAdminServer interface { - AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error) -} - -// UnimplementedEntityStoreAdminServer should be embedded to have forward compatible implementations. -type UnimplementedEntityStoreAdminServer struct { -} - -func (UnimplementedEntityStoreAdminServer) AdminWrite(context.Context, *AdminWriteEntityRequest) (*WriteEntityResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AdminWrite not implemented") -} - -// UnsafeEntityStoreAdminServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to EntityStoreAdminServer will -// result in compilation errors. -type UnsafeEntityStoreAdminServer interface { - mustEmbedUnimplementedEntityStoreAdminServer() -} - -func RegisterEntityStoreAdminServer(s grpc.ServiceRegistrar, srv EntityStoreAdminServer) { - s.RegisterService(&EntityStoreAdmin_ServiceDesc, srv) -} - -func _EntityStoreAdmin_AdminWrite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AdminWriteEntityRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(EntityStoreAdminServer).AdminWrite(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: EntityStoreAdmin_AdminWrite_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(EntityStoreAdminServer).AdminWrite(ctx, req.(*AdminWriteEntityRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// EntityStoreAdmin_ServiceDesc is the grpc.ServiceDesc for EntityStoreAdmin service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var EntityStoreAdmin_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "entity.EntityStoreAdmin", - HandlerType: (*EntityStoreAdminServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "AdminWrite", - Handler: _EntityStoreAdmin_AdminWrite_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "entity.proto", -} diff --git a/pkg/services/store/entity/key.go b/pkg/services/store/entity/key.go new file mode 100644 index 00000000000..775f31860ce --- /dev/null +++ b/pkg/services/store/entity/key.go @@ -0,0 +1,61 @@ +package entity + +import ( + "fmt" + "strings" +) + +type Key struct { + Group string + Resource string + Namespace string + Name string + Subresource string +} + +func ParseKey(key string) (*Key, error) { + // ///(/(/)) + parts := strings.SplitN(key, "/", 6) + if len(parts) < 4 { + return nil, fmt.Errorf("invalid key (expecting at least 3 parts): %s", key) + } + + if parts[0] != "" { + return nil, fmt.Errorf("invalid key (expecting leading slash): %s", key) + } + + k := &Key{ + Group: parts[1], + Resource: parts[2], + Namespace: parts[3], + } + + if len(parts) > 4 { + k.Name = parts[4] + } + + if len(parts) > 5 { + k.Subresource = parts[5] + } + + return k, nil +} + +func (k *Key) String() string { + s := k.Group + "/" + k.Resource + "/" + k.Namespace + if len(k.Name) > 0 { + s += "/" + k.Name + if len(k.Subresource) > 0 { + s += "/" + k.Subresource + } + } + return s +} + +func (k *Key) IsEqual(other *Key) bool { + return k.Group == other.Group && + k.Resource == other.Resource && + k.Namespace == other.Namespace && + k.Name == other.Name && + k.Subresource == other.Subresource +} diff --git a/pkg/services/store/entity/migrations/entity_store_mig.go b/pkg/services/store/entity/migrations/entity_store_mig.go index adb9819c115..9d421abbb5c 100644 --- a/pkg/services/store/entity/migrations/entity_store_mig.go +++ b/pkg/services/store/entity/migrations/entity_store_mig.go @@ -7,7 +7,7 @@ import ( ) func initEntityTables(mg *migrator.Migrator) string { - marker := "Initialize entity tables (v005)" // changing this key wipe+rewrite everything + marker := "Initialize entity tables (v006)" // changing this key wipe+rewrite everything mg.AddMigration(marker, &migrator.RawSQLMigration{}) tables := []migrator.Table{} @@ -19,11 +19,12 @@ func initEntityTables(mg *migrator.Migrator) string { {Name: "version", Type: migrator.DB_NVarchar, Length: 128, Nullable: false}, // The entity identifier - {Name: "tenant_id", Type: migrator.DB_BigInt, Nullable: false}, {Name: "key", Type: migrator.DB_Text, Nullable: false}, + // k8s namespace names must be RFC1123 label names, 63 characters or less + {Name: "namespace", Type: migrator.DB_NVarchar, Length: 63, Nullable: false}, {Name: "group", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, {Name: "group_version", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, - {Name: "kind", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, + {Name: "resource", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, {Name: "uid", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, {Name: "folder", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, // uid of folder @@ -59,7 +60,7 @@ func initEntityTables(mg *migrator.Migrator) string { {Name: "errors", Type: migrator.DB_Text, Nullable: true}, // JSON object }, Indices: []*migrator.Index{ - {Cols: []string{"tenant_id", "kind", "uid"}, Type: migrator.UniqueIndex}, + {Cols: []string{"namespace", "group", "resource", "uid"}, Type: migrator.UniqueIndex}, {Cols: []string{"folder"}, Type: migrator.IndexType}, }, }) @@ -73,11 +74,12 @@ func initEntityTables(mg *migrator.Migrator) string { {Name: "version", Type: migrator.DB_NVarchar, Length: 128, Nullable: false}, // The entity identifier - {Name: "tenant_id", Type: migrator.DB_BigInt, Nullable: false}, {Name: "key", Type: migrator.DB_Text, Nullable: false}, + // k8s namespace names must be RFC1123 label names, 63 characters or less + {Name: "namespace", Type: migrator.DB_NVarchar, Length: 63, Nullable: false}, {Name: "group", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, {Name: "group_version", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, - {Name: "kind", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, + {Name: "resource", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, {Name: "uid", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, {Name: "folder", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, // uid of folder @@ -115,7 +117,7 @@ func initEntityTables(mg *migrator.Migrator) string { }, Indices: []*migrator.Index{ {Cols: []string{"guid", "version"}, Type: migrator.UniqueIndex}, - {Cols: []string{"tenant_id", "kind", "uid", "version"}, Type: migrator.UniqueIndex}, + {Cols: []string{"namespace", "group", "resource", "uid", "version"}, Type: migrator.UniqueIndex}, }, }) @@ -124,7 +126,8 @@ func initEntityTables(mg *migrator.Migrator) string { Name: "entity_folder", Columns: []*migrator.Column{ {Name: "guid", Type: migrator.DB_NVarchar, Length: 36, Nullable: false, IsPrimaryKey: true}, - + {Name: "namespace", Type: migrator.DB_NVarchar, Length: 63, Nullable: false}, + {Name: "uid", Type: migrator.DB_NVarchar, Length: 190, Nullable: false}, {Name: "slug_path", Type: migrator.DB_Text, Nullable: false}, // /slug/slug/slug/ {Name: "tree", Type: migrator.DB_Text, Nullable: false}, // JSON []{uid, title} {Name: "depth", Type: migrator.DB_Int, Nullable: false}, // starts at 1 diff --git a/pkg/services/store/entity/models.go b/pkg/services/store/entity/models.go index e973282ebee..8522afd2eec 100644 --- a/pkg/services/store/entity/models.go +++ b/pkg/services/store/entity/models.go @@ -7,6 +7,9 @@ import context "context" //----------------------------------------------------------------------------------------------------- const ( + FolderGroupName = "folder.grafana.app" + FolderResourceName = "folders" + StandardKindDashboard = "dashboard" StandardKindPlaylist = "playlist" StandardKindFolder = "folder" diff --git a/pkg/services/store/entity/sqlstash/folder_support.go b/pkg/services/store/entity/sqlstash/folder_support.go index 0a3670f8a48..a3ab1927cc0 100644 --- a/pkg/services/store/entity/sqlstash/folder_support.go +++ b/pkg/services/store/entity/sqlstash/folder_support.go @@ -34,17 +34,17 @@ type folderInfo struct { // This will replace all entries in `entity_folder` // This is pretty heavy weight, but it does give us a sorted folder list // NOTE: this could be done async with a mutex/lock? reconciler pattern -func updateFolderTree(ctx context.Context, tx *session.SessionTx, tenantId int64) error { - _, err := tx.Exec(ctx, "DELETE FROM entity_folder WHERE tenant_id=?", tenantId) +func updateFolderTree(ctx context.Context, tx *session.SessionTx, namespace string) error { + _, err := tx.Exec(ctx, "DELETE FROM entity_folder WHERE namespace=?", namespace) if err != nil { return err } query := "SELECT guid,uid,folder,name,slug" + " FROM entity" + - " WHERE kind=? AND tenant_id=?" + + " WHERE group=? AND resource=? AND namespace=?" + " ORDER BY slug asc" - args := []interface{}{entity.StandardKindFolder, tenantId} + args := []interface{}{entity.FolderGroupName, entity.FolderResourceName, namespace} all := []*folderInfo{} rows, err := tx.Query(ctx, query, args...) @@ -69,13 +69,13 @@ func updateFolderTree(ctx context.Context, tx *session.SessionTx, tenantId int64 return err } - err = insertFolderInfo(ctx, tx, tenantId, root, false) + err = insertFolderInfo(ctx, tx, namespace, root, false) if err != nil { return err } for _, folder := range lost { - err = insertFolderInfo(ctx, tx, tenantId, folder, true) + err = insertFolderInfo(ctx, tx, namespace, folder, true) if err != nil { return err } @@ -137,14 +137,14 @@ func setMPTTOrder(folder *folderInfo, stack []*folderInfo, idx int32) (int32, er return folder.right, nil } -func insertFolderInfo(ctx context.Context, tx *session.SessionTx, tenantId int64, folder *folderInfo, isDetached bool) error { +func insertFolderInfo(ctx context.Context, tx *session.SessionTx, namespace string, folder *folderInfo, isDetached bool) error { js, _ := json.Marshal(folder.stack) _, err := tx.Exec(ctx, `INSERT INTO entity_folder `+ - "(guid, tenant_id, uid, slug_path, tree, depth, lft, rgt, detached) "+ + "(guid, namespace, uid, slug_path, tree, depth, lft, rgt, detached) "+ `VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, folder.Guid, - tenantId, + namespace, folder.UID, folder.SlugPath, string(js), @@ -158,7 +158,7 @@ func insertFolderInfo(ctx context.Context, tx *session.SessionTx, tenantId int64 } for _, sub := range folder.children { - err := insertFolderInfo(ctx, tx, tenantId, sub, isDetached) + err := insertFolderInfo(ctx, tx, namespace, sub, isDetached) if err != nil { return err } diff --git a/pkg/services/store/entity/sqlstash/sql_storage_server.go b/pkg/services/store/entity/sqlstash/sql_storage_server.go index 583bae5701d..fee6dcceabc 100644 --- a/pkg/services/store/entity/sqlstash/sql_storage_server.go +++ b/pkg/services/store/entity/sqlstash/sql_storage_server.go @@ -15,7 +15,6 @@ import ( "github.com/bwmarrin/snowflake" "github.com/google/uuid" "github.com/grafana/grafana/pkg/infra/appcontext" - "github.com/grafana/grafana/pkg/infra/grn" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/session" @@ -33,7 +32,6 @@ type EntityDB interface { // Make sure we implement both store + admin var _ entity.EntityStoreServer = &sqlEntityServer{} -var _ entity.EntityStoreAdminServer = &sqlEntityServer{} func ProvideSQLEntityServer(db EntityDB /*, cfg *setting.Cfg */) (entity.EntityStoreServer, error) { snode, err := snowflake.NewNode(rand.Int63n(1024)) @@ -91,24 +89,22 @@ func (s *sqlEntityServer) getReadFields(r *entity.ReadEntityRequest) []string { fields := []string{ "guid", "key", - "tenant_id", "group", "group_version", "kind", "uid", "folder", // GRN + folder + "namespace", "group", "group_version", "resource", "uid", "folder", "version", "size", "etag", "errors", // errors are always returned "created_at", "created_by", "updated_at", "updated_by", - "origin", "origin_key", "origin_ts"} + "origin", "origin_key", "origin_ts", + "meta", + "name", "slug", "description", "labels", "fields", + } if r.WithBody { fields = append(fields, `body`) } - if r.WithMeta { - fields = append(fields, `meta`) - } - if r.WithSummary { - fields = append(fields, "name", "slug", "description", "labels", "fields") - } if r.WithStatus { fields = append(fields, "status") } + return fields } @@ -126,9 +122,8 @@ func (s *sqlEntityServer) getReadSelect(r *entity.ReadEntityRequest) (string, er return "SELECT " + strings.Join(quotedFields, ","), nil } -func (s *sqlEntityServer) rowToReadEntityResponse(ctx context.Context, rows *sql.Rows, r *entity.ReadEntityRequest) (*entity.Entity, error) { +func (s *sqlEntityServer) rowToEntity(ctx context.Context, rows *sql.Rows, r *entity.ReadEntityRequest) (*entity.Entity, error) { raw := &entity.Entity{ - GRN: &grn.GRN{}, Origin: &entity.EntityOriginInfo{}, } @@ -139,21 +134,17 @@ func (s *sqlEntityServer) rowToReadEntityResponse(ctx context.Context, rows *sql args := []any{ &raw.Guid, &raw.Key, - &raw.GRN.TenantID, &raw.GRN.ResourceGroup, &raw.GroupVersion, &raw.GRN.ResourceKind, &raw.GRN.ResourceIdentifier, &raw.Folder, + &raw.Namespace, &raw.Group, &raw.GroupVersion, &raw.Resource, &raw.Uid, &raw.Folder, &raw.Version, &raw.Size, &raw.ETag, &errors, &raw.CreatedAt, &raw.CreatedBy, &raw.UpdatedAt, &raw.UpdatedBy, &raw.Origin.Source, &raw.Origin.Key, &raw.Origin.Time, + &raw.Meta, + &raw.Name, &raw.Slug, &raw.Description, &labels, &fields, } if r.WithBody { args = append(args, &raw.Body) } - if r.WithMeta { - args = append(args, &raw.Meta) - } - if r.WithSummary { - args = append(args, &raw.Name, &raw.Slug, &raw.Description, &labels, &fields) - } if r.WithStatus { args = append(args, &raw.Status) } @@ -177,38 +168,6 @@ func (s *sqlEntityServer) rowToReadEntityResponse(ctx context.Context, rows *sql return raw, nil } -func (s *sqlEntityServer) validateGRN(ctx context.Context, grn *grn.GRN) (*grn.GRN, error) { - if grn == nil { - return nil, fmt.Errorf("missing GRN") - } - user, err := appcontext.User(ctx) - if err != nil { - return nil, err - } - if grn.TenantID == 0 { - grn.TenantID = user.OrgID - } else if grn.TenantID != user.OrgID { - return nil, fmt.Errorf("tenant ID does not match userID: %+v", grn) - } - - if grn.ResourceGroup == "" { - return nil, fmt.Errorf("GRN missing ResourceGroup: %+v", grn) - } - if grn.ResourceKind == "" { - return nil, fmt.Errorf("GRN missing ResourceKind: %+v", grn) - } - if grn.ResourceIdentifier == "" { - return nil, fmt.Errorf("GRN missing ResourceIdentifier: %+v", grn) - } - if len(grn.ResourceIdentifier) > 64 { - return nil, fmt.Errorf("GRN ResourceIdentifier is too long (>64): %+v", grn) - } - if strings.ContainsAny(grn.ResourceIdentifier, "/#$@?") { - return nil, fmt.Errorf("invalid character in GRN: %+v", grn) - } - return grn, nil -} - func (s *sqlEntityServer) Read(ctx context.Context, r *entity.ReadEntityRequest) (*entity.Entity, error) { if err := s.Init(); err != nil { return nil, err @@ -222,22 +181,21 @@ func (s *sqlEntityServer) read(ctx context.Context, tx session.SessionQuerier, r where := []string{} args := []any{} - if r.Key != "" { - where = append(where, s.dialect.Quote("key")+"=?") - args = append(args, r.Key) - } else { - grn, err := s.validateGRN(ctx, r.GRN) - if err != nil { - return nil, err - } + if r.Key == "" { + return nil, fmt.Errorf("missing key") + } - where = append(where, "(tenant_id=? AND kind=? AND uid=?)") - args = append(args, grn.TenantID, grn.ResourceKind, grn.ResourceIdentifier) + key, err := entity.ParseKey(r.Key) + if err != nil { + return nil, err } + where = append(where, s.dialect.Quote("namespace")+"=?", s.dialect.Quote("group")+"=?", s.dialect.Quote("resource")+"=?", s.dialect.Quote("uid")+"=?") + args = append(args, key.Namespace, key.Group, key.Resource, key.Name) + if r.Version != "" { table = "entity_history" - where = append(where, "version=?") + where = append(where, s.dialect.Quote("version")+"=?") args = append(args, r.Version) } @@ -253,6 +211,8 @@ func (s *sqlEntityServer) read(ctx context.Context, tx session.SessionQuerier, r query += " FROM " + table + " WHERE " + strings.Join(where, " AND ") + s.log.Debug("read", "query", query, "args", args) + rows, err := tx.Query(ctx, query, args...) if err != nil { return nil, err @@ -263,7 +223,7 @@ func (s *sqlEntityServer) read(ctx context.Context, tx session.SessionQuerier, r return &entity.Entity{}, nil } - return s.rowToReadEntityResponse(ctx, rows, r) + return s.rowToEntity(ctx, rows, r) } func (s *sqlEntityServer) BatchRead(ctx context.Context, b *entity.BatchReadEntityRequest) (*entity.BatchReadEntityResponse, error) { @@ -276,23 +236,17 @@ func (s *sqlEntityServer) BatchRead(ctx context.Context, b *entity.BatchReadEnti constraints := []string{} for _, r := range b.Batch { - if r.WithBody != first.WithBody || r.WithSummary != first.WithSummary { + if r.WithBody != first.WithBody || r.WithStatus != first.WithStatus { return nil, fmt.Errorf("requests must want the same things") } - if r.Key != "" { - constraints = append(constraints, s.dialect.Quote("key")+"=?") - args = append(args, r.Key) - } else { - grn, err := s.validateGRN(ctx, r.GRN) - if err != nil { - return nil, err - } - - constraints = append(constraints, "(tenant_id=? AND kind=? AND uid=?)") - args = append(args, grn.TenantID, grn.ResourceKind, grn.ResourceIdentifier) + if r.Key == "" { + return nil, fmt.Errorf("missing key") } + constraints = append(constraints, s.dialect.Quote("key")+"=?") + args = append(args, r.Key) + if r.Version != "" { return nil, fmt.Errorf("version not supported for batch read (yet?)") } @@ -315,7 +269,7 @@ func (s *sqlEntityServer) BatchRead(ctx context.Context, b *entity.BatchReadEnti // TODO? make sure the results are in order? rsp := &entity.BatchReadEntityResponse{} for rows.Next() { - r, err := s.rowToReadEntityResponse(ctx, rows, req) + r, err := s.rowToEntity(ctx, rows, req) if err != nil { return nil, err } @@ -324,311 +278,12 @@ func (s *sqlEntityServer) BatchRead(ctx context.Context, b *entity.BatchReadEnti return rsp, nil } -func (s *sqlEntityServer) Write(ctx context.Context, r *entity.WriteEntityRequest) (*entity.WriteEntityResponse, error) { - return s.AdminWrite(ctx, entity.ToAdminWriteEntityRequest(r)) -} - //nolint:gocyclo -func (s *sqlEntityServer) AdminWrite(ctx context.Context, r *entity.AdminWriteEntityRequest) (*entity.WriteEntityResponse, error) { - if err := s.Init(); err != nil { - return nil, err - } - - grn, err := s.validateGRN(ctx, r.Entity.GRN) - if err != nil { - s.log.Error("error validating GRN", "msg", err.Error()) - return nil, err - } - - timestamp := time.Now().UnixMilli() - createdAt := r.Entity.CreatedAt - createdBy := r.Entity.CreatedBy - updatedAt := r.Entity.UpdatedAt - updatedBy := r.Entity.UpdatedBy - if updatedBy == "" || createdBy == "" { - modifier, err := appcontext.User(ctx) - if err != nil { - return nil, err - } - if modifier == nil { - return nil, fmt.Errorf("can not find user in context") - } - if createdBy == "" { - createdBy = store.GetUserIDString(modifier) - } - if updatedBy == "" { - updatedBy = store.GetUserIDString(modifier) - } - } - if updatedAt < 1000 { - updatedAt = timestamp - } - - rsp := &entity.WriteEntityResponse{ - Entity: &entity.Entity{}, - Status: entity.WriteEntityResponse_CREATED, // Will be changed if not true - } - - err = s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error { - current, err := s.read(ctx, tx, &entity.ReadEntityRequest{ - GRN: grn, - WithMeta: true, - WithBody: true, - WithStatus: true, - WithSummary: true, - }) - if err != nil { - return err - } - - // Optimistic locking - if r.PreviousVersion != "" && r.PreviousVersion != current.Version { - return fmt.Errorf("optimistic lock failed") - } - - isUpdate := false - - // if we found an existing entity - if current.Guid != "" { - if r.ClearHistory { - // Optionally keep the original creation time information - if createdAt < 1000 || createdBy == "" { - createdAt = current.CreatedAt - createdBy = current.CreatedBy - } - - err = doDelete(ctx, tx, current) - if err != nil { - s.log.Error("error removing old version", "msg", err.Error()) - return err - } - - current = &entity.Entity{} - } else { - isUpdate = true - - rsp.Entity.Guid = current.Guid - - // Clear the labels+refs - if _, err := tx.Exec(ctx, "DELETE FROM entity_labels WHERE guid=?", rsp.Entity.Guid); err != nil { - return err - } - if _, err := tx.Exec(ctx, "DELETE FROM entity_ref WHERE guid=?", rsp.Entity.Guid); err != nil { - return err - } - } - } else { - // generate guid for new entity - current.Guid = uuid.New().String() - current.GRN = grn - current.Key = r.Entity.Key - } - - if r.Entity.GroupVersion != "" { - current.GroupVersion = r.Entity.GroupVersion - } - - if r.Entity.Folder != "" { - current.Folder = r.Entity.Folder - } - if r.Entity.Slug != "" { - current.Slug = r.Entity.Slug - } - - if r.Entity.Body != nil { - current.Body = r.Entity.Body - current.Size = int64(len(current.Body)) - } - - if r.Entity.Meta != nil { - current.Meta = r.Entity.Meta - } - - if r.Entity.Status != nil { - current.Status = r.Entity.Status - } - - etag := createContentsHash(current.Body, current.Meta, current.Status) - current.ETag = etag - current.UpdatedAt = updatedAt - current.UpdatedBy = updatedBy - - if r.Entity.Name != "" { - current.Name = r.Entity.Name - } - if r.Entity.Description != "" { - current.Description = r.Entity.Description - } - - labels, err := json.Marshal(r.Entity.Labels) - if err != nil { - s.log.Error("error marshalling labels", "msg", err.Error()) - return err - } - - fields, err := json.Marshal(r.Entity.Fields) - if err != nil { - s.log.Error("error marshalling fields", "msg", err.Error()) - return err - } - - errors, err := json.Marshal(r.Entity.Errors) - if err != nil { - s.log.Error("error marshalling errors", "msg", err.Error()) - return err - } - - if current.Origin == nil { - current.Origin = &entity.EntityOriginInfo{} - } - - if r.Entity.Origin != nil { - if r.Entity.Origin.Source != "" { - current.Origin.Source = r.Entity.Origin.Source - } - if r.Entity.Origin.Key != "" { - current.Origin.Key = r.Entity.Origin.Key - } - if r.Entity.Origin.Time > 0 { - current.Origin.Time = r.Entity.Origin.Time - } - } - - // Set the comment on this write - if r.Entity.Message != "" { - current.Message = r.Entity.Message - } - - // Update version - current.Version = s.snowflake.Generate().String() - - values := map[string]any{ - // below are only set at creation - "guid": current.Guid, - "key": current.Key, - "tenant_id": grn.TenantID, - "group": grn.ResourceGroup, - "kind": grn.ResourceKind, - "uid": grn.ResourceIdentifier, - "created_at": createdAt, - "created_by": createdBy, - // below are set during creation and update - "group_version": current.GroupVersion, - "folder": current.Folder, - "slug": current.Slug, - "updated_at": updatedAt, - "updated_by": updatedBy, - "body": current.Body, - "meta": current.Meta, - "status": current.Status, - "size": current.Size, - "etag": current.ETag, - "version": current.Version, - "name": current.Name, - "description": current.Description, - "labels": labels, - "fields": fields, - "errors": errors, - "origin": current.Origin.Source, - "origin_key": current.Origin.Key, - "origin_ts": current.Origin.Time, - "message": current.Message, - } - - // 1. Add the `entity_history` values - query, args, err := s.dialect.InsertQuery("entity_history", values) - if err != nil { - s.log.Error("error building entity history insert", "msg", err.Error()) - return err - } - - _, err = tx.Exec(ctx, query, args...) - if err != nil { - s.log.Error("error writing entity history", "msg", err.Error()) - return err - } - - // 5. Add/update the main `entity` table - if isUpdate { - // remove values that are only set at insert - delete(values, "guid") - delete(values, "key") - delete(values, "tenant_id") - delete(values, "group") - delete(values, "kind") - delete(values, "uid") - delete(values, "created_at") - delete(values, "created_by") - - query, args, err := s.dialect.UpdateQuery( - "entity", - values, - map[string]any{ - "guid": current.Guid, - }, - ) - if err != nil { - s.log.Error("error building entity update sql", "msg", err.Error()) - return err - } - - _, err = tx.Exec(ctx, query, args...) - if err != nil { - s.log.Error("error updating entity", "msg", err.Error()) - return err - } - - rsp.Status = entity.WriteEntityResponse_UPDATED - } else { - query, args, err := s.dialect.InsertQuery("entity", values) - if err != nil { - s.log.Error("error building entity insert sql", "msg", err.Error()) - return err - } - - _, err = tx.Exec(ctx, query, args...) - if err != nil { - s.log.Error("error inserting entity", "msg", err.Error()) - return err - } - - rsp.Status = entity.WriteEntityResponse_CREATED - } - - /* - switch current.GRN.ResourceKind { - case entity.StandardKindFolder: - err = updateFolderTree(ctx, tx, r.Entity.GRN.TenantID) - if err != nil { - s.log.Error("error updating folder tree", "msg", err.Error()) - return err - } - } - */ - - rsp.Entity = current - - return nil // s.writeSearchInfo(ctx, tx, current) - }) - if err != nil { - s.log.Error("error writing entity", "msg", err.Error()) - rsp.Status = entity.WriteEntityResponse_ERROR - } - - return rsp, err -} - func (s *sqlEntityServer) Create(ctx context.Context, r *entity.CreateEntityRequest) (*entity.CreateEntityResponse, error) { if err := s.Init(); err != nil { return nil, err } - grn, err := s.validateGRN(ctx, r.Entity.GRN) - if err != nil { - s.log.Error("error validating GRN", "msg", err.Error()) - return nil, err - } - createdAt := r.Entity.CreatedAt createdBy := r.Entity.CreatedBy if createdBy == "" { @@ -649,13 +304,11 @@ func (s *sqlEntityServer) Create(ctx context.Context, r *entity.CreateEntityRequ Status: entity.CreateEntityResponse_CREATED, // Will be changed if not true } - err = s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error { + err := s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error { current, err := s.read(ctx, tx, &entity.ReadEntityRequest{ - GRN: grn, - WithMeta: true, - WithBody: true, - WithStatus: true, - WithSummary: true, + Key: r.Entity.Key, + WithBody: true, + WithStatus: true, }) if err != nil { return err @@ -668,13 +321,20 @@ func (s *sqlEntityServer) Create(ctx context.Context, r *entity.CreateEntityRequ // generate guid for new entity current.Guid = uuid.New().String() - current.GRN = grn - current.Key = r.Entity.Key - if r.Entity.GroupVersion != "" { - current.GroupVersion = r.Entity.GroupVersion + // parse provided key + key, err := entity.ParseKey(r.Entity.Key) + if err != nil { + return err } + current.Key = r.Entity.Key + current.Namespace = key.Namespace + current.Group = key.Group + current.GroupVersion = r.Entity.GroupVersion + current.Resource = key.Resource + current.Uid = key.Name + if r.Entity.Folder != "" { current.Folder = r.Entity.Folder } @@ -750,16 +410,14 @@ func (s *sqlEntityServer) Create(ctx context.Context, r *entity.CreateEntityRequ current.Version = s.snowflake.Generate().String() values := map[string]any{ - // below are only set at creation - "guid": current.Guid, - "key": current.Key, - "tenant_id": grn.TenantID, - "group": grn.ResourceGroup, - "kind": grn.ResourceKind, - "uid": grn.ResourceIdentifier, - "created_at": createdAt, - "created_by": createdBy, - // below are set during creation and update + "guid": current.Guid, + "key": current.Key, + "namespace": current.Namespace, + "group": current.Group, + "resource": current.Resource, + "uid": current.Uid, + "created_at": createdAt, + "created_by": createdBy, "group_version": current.GroupVersion, "folder": current.Folder, "slug": current.Slug, @@ -782,42 +440,47 @@ func (s *sqlEntityServer) Create(ctx context.Context, r *entity.CreateEntityRequ "message": current.Message, } - // 1. Add the `entity_history` values + // 1. Add row to the `entity_history` values query, args, err := s.dialect.InsertQuery("entity_history", values) if err != nil { s.log.Error("error building entity history insert", "msg", err.Error()) return err } + s.log.Debug("create", "query", query, "args", args) + _, err = tx.Exec(ctx, query, args...) if err != nil { s.log.Error("error writing entity history", "msg", err.Error()) return err } - // 2. Add/update the main `entity` table + // 2. Add row to the main `entity` table query, args, err = s.dialect.InsertQuery("entity", values) if err != nil { s.log.Error("error building entity insert sql", "msg", err.Error()) return err } + s.log.Debug("create", "query", query, "args", args) + _, err = tx.Exec(ctx, query, args...) if err != nil { s.log.Error("error inserting entity", "msg", err.Error()) return err } - /* - switch current.GRN.ResourceKind { - case entity.StandardKindFolder: - err = updateFolderTree(ctx, tx, r.Entity.GRN.TenantID) + switch current.Group { + case entity.FolderGroupName: + switch current.Resource { + case entity.FolderResourceName: + err = updateFolderTree(ctx, tx, current.Namespace) if err != nil { s.log.Error("error updating folder tree", "msg", err.Error()) return err } } - */ + } rsp.Entity = current @@ -837,12 +500,6 @@ func (s *sqlEntityServer) Update(ctx context.Context, r *entity.UpdateEntityRequ return nil, err } - grn, err := s.validateGRN(ctx, r.Entity.GRN) - if err != nil { - s.log.Error("error validating GRN", "msg", err.Error()) - return nil, err - } - timestamp := time.Now().UnixMilli() updatedAt := r.Entity.UpdatedAt updatedBy := r.Entity.UpdatedBy @@ -865,13 +522,11 @@ func (s *sqlEntityServer) Update(ctx context.Context, r *entity.UpdateEntityRequ Status: entity.UpdateEntityResponse_UPDATED, // Will be changed if not true } - err = s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error { + err := s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error { current, err := s.read(ctx, tx, &entity.ReadEntityRequest{ - GRN: grn, - WithMeta: true, - WithBody: true, - WithStatus: true, - WithSummary: true, + Key: r.Entity.Key, + WithBody: true, + WithStatus: true, }) if err != nil { return err @@ -882,7 +537,7 @@ func (s *sqlEntityServer) Update(ctx context.Context, r *entity.UpdateEntityRequ return fmt.Errorf("optimistic lock failed") } - // if we found an existing entity + // if we didn't find an existing entity if current.Guid == "" { return fmt.Errorf("entity not found") } @@ -979,10 +634,10 @@ func (s *sqlEntityServer) Update(ctx context.Context, r *entity.UpdateEntityRequ // below are only set in history table "guid": current.Guid, "key": current.Key, - "tenant_id": grn.TenantID, - "group": grn.ResourceGroup, - "kind": grn.ResourceKind, - "uid": grn.ResourceIdentifier, + "namespace": current.Namespace, + "group": current.Group, + "resource": current.Resource, + "uid": current.Uid, "created_at": current.CreatedAt, "created_by": current.CreatedBy, // below are updated @@ -1026,9 +681,9 @@ func (s *sqlEntityServer) Update(ctx context.Context, r *entity.UpdateEntityRequ // remove values that are only set at insert delete(values, "guid") delete(values, "key") - delete(values, "tenant_id") + delete(values, "namespace") delete(values, "group") - delete(values, "kind") + delete(values, "resource") delete(values, "uid") delete(values, "created_at") delete(values, "created_by") @@ -1051,16 +706,17 @@ func (s *sqlEntityServer) Update(ctx context.Context, r *entity.UpdateEntityRequ return err } - /* - switch current.GRN.ResourceKind { - case entity.StandardKindFolder: - err = updateFolderTree(ctx, tx, r.Entity.GRN.TenantID) + switch current.Group { + case entity.FolderGroupName: + switch current.Resource { + case entity.FolderResourceName: + err = updateFolderTree(ctx, tx, current.Namespace) if err != nil { s.log.Error("error updating folder tree", "msg", err.Error()) return err } } - */ + } rsp.Entity = current @@ -1080,17 +736,17 @@ func (s *sqlEntityServer) writeSearchInfo( tx *session.SessionTx, current *entity.Entity, ) error { - // parent_grn := current.getParentGRN() + // parent_key := current.getParentKey() // Add the labels rows for k, v := range current.Labels { query, args, err := s.dialect.InsertQuery( "entity_labels", map[string]any{ - "grn": current.GRN.ToGRNString(), + "key": current.Key, "label": k, "value": v, - // "parent_grn": parent_grn, + // "parent_key": parent_key, }, ) if err != nil { @@ -1117,12 +773,9 @@ func (s *sqlEntityServer) Delete(ctx context.Context, r *entity.DeleteEntityRequ err := s.sess.WithTransaction(ctx, func(tx *session.SessionTx) error { var err error rsp.Entity, err = s.Read(ctx, &entity.ReadEntityRequest{ - GRN: r.GRN, - Key: r.Key, - WithBody: true, - WithMeta: true, - WithStatus: true, - WithSummary: true, + Key: r.Key, + WithBody: true, + WithStatus: true, }) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -1138,7 +791,7 @@ func (s *sqlEntityServer) Delete(ctx context.Context, r *entity.DeleteEntityRequ return fmt.Errorf("optimistic lock failed") } - err = doDelete(ctx, tx, rsp.Entity) + err = s.doDelete(ctx, tx, rsp.Entity) if err != nil { rsp.Status = entity.DeleteEntityResponse_ERROR return err @@ -1151,7 +804,7 @@ func (s *sqlEntityServer) Delete(ctx context.Context, r *entity.DeleteEntityRequ return rsp, err } -func doDelete(ctx context.Context, tx *session.SessionTx, ent *entity.Entity) error { +func (s *sqlEntityServer) doDelete(ctx context.Context, tx *session.SessionTx, ent *entity.Entity) error { _, err := tx.Exec(ctx, "DELETE FROM entity WHERE guid=?", ent.Guid) if err != nil { return err @@ -1171,10 +824,15 @@ func doDelete(ctx context.Context, tx *session.SessionTx, ent *entity.Entity) er return err } - if ent.GRN.ResourceKind == entity.StandardKindFolder { - err = updateFolderTree(ctx, tx, ent.GRN.TenantID) - if err != nil { - return err + switch ent.Group { + case entity.FolderGroupName: + switch ent.Resource { + case entity.FolderResourceName: + err = updateFolderTree(ctx, tx, ent.Namespace) + if err != nil { + s.log.Error("error updating folder tree", "msg", err.Error()) + return err + } } } @@ -1186,22 +844,15 @@ func (s *sqlEntityServer) History(ctx context.Context, r *entity.EntityHistoryRe return nil, err } - grn2, err := s.validateGRN(ctx, r.GRN) - if err != nil { - return nil, err - } - var limit int64 = 100 if r.Limit > 0 && r.Limit < 100 { limit = r.Limit } rr := &entity.ReadEntityRequest{ - GRN: grn2, - WithMeta: true, - WithBody: false, - WithStatus: true, - WithSummary: true, + Key: r.Key, + WithBody: true, + WithStatus: false, } query, err := s.getReadSelect(rr) @@ -1209,18 +860,29 @@ func (s *sqlEntityServer) History(ctx context.Context, r *entity.EntityHistoryRe return nil, err } - query += " FROM entity_history" + - " WHERE (tenant_id=? AND kind=? AND uid=?)" - args := []any{ - grn2.TenantID, grn2.ResourceKind, grn2.ResourceIdentifier, + if r.Key == "" { + return nil, fmt.Errorf("missing key") + } + + key, err := entity.ParseKey(r.Key) + if err != nil { + return nil, err } + where := []string{} + args := []any{} + + where = append(where, s.dialect.Quote("namespace")+"=?", s.dialect.Quote("group")+"=?", s.dialect.Quote("resource")+"=?", s.dialect.Quote("uid")+"=?") + args = append(args, key.Namespace, key.Group, key.Resource, key.Name) + if r.NextPageToken != "" { - query += " AND version <= ?" + where = append(where, "version <= ?") args = append(args, r.NextPageToken) } - query += " ORDER BY version DESC" + + query += " FROM entity_history" + + " WHERE " + strings.Join(where, " AND ") + + " ORDER BY version DESC" + // select 1 more than we need to see if there is a next page " LIMIT " + fmt.Sprint(limit+1) @@ -1231,10 +893,10 @@ func (s *sqlEntityServer) History(ctx context.Context, r *entity.EntityHistoryRe defer func() { _ = rows.Close() }() rsp := &entity.EntityHistoryResponse{ - GRN: grn2, + Key: r.Key, } for rows.Next() { - v, err := s.rowToReadEntityResponse(ctx, rows, rr) + v, err := s.rowToEntity(ctx, rows, rr) if err != nil { return nil, err } @@ -1267,24 +929,12 @@ func (s *sqlEntityServer) List(ctx context.Context, r *entity.EntityListRequest) return nil, fmt.Errorf("not yet supported") } - fields := []string{ - "guid", "guid", "key", - "tenant_id", "group", "group_version", "kind", "uid", - "version", "folder", "slug", "errors", // errors are always returned - "size", "updated_at", "updated_by", - "name", "description", // basic summary - } - - if r.WithBody { - fields = append(fields, "body", "meta", "status") + rr := &entity.ReadEntityRequest{ + WithBody: r.WithBody, + WithStatus: r.WithStatus, } - if r.WithLabels { - fields = append(fields, "labels") - } - if r.WithFields { - fields = append(fields, "fields") - } + fields := s.getReadFields(rr) entityQuery := selectQuery{ dialect: s.dialect, @@ -1294,18 +944,36 @@ func (s *sqlEntityServer) List(ctx context.Context, r *entity.EntityListRequest) limit: r.Limit, oneExtra: true, // request one more than the limit (and show next token if it exists) } - entityQuery.addWhere("tenant_id", user.OrgID) - if len(r.Kind) > 0 { - entityQuery.addWhereIn("kind", r.Kind) + // TODO fix this + // entityQuery.addWhere("namespace", user.OrgID) + + if len(r.Group) > 0 { + entityQuery.addWhereIn("group", r.Group) + } + + if len(r.Resource) > 0 { + entityQuery.addWhereIn("resource", r.Resource) } if len(r.Key) > 0 { where := []string{} args := []any{} for _, k := range r.Key { - args = append(args, k+"/%") - where = append(where, s.dialect.Quote("key")+" LIKE ?") + key, err := entity.ParseKey(k) + if err != nil { + return nil, err + } + + args = append(args, key.Namespace, key.Group, key.Resource) + whereclause := "(" + s.dialect.Quote("namespace") + "=? AND " + s.dialect.Quote("group") + "=? AND " + s.dialect.Quote("resource") + "=?" + if key.Name != "" { + args = append(args, key.Name) + whereclause += " AND " + s.dialect.Quote("uid") + "=?" + } + whereclause += ")" + + where = append(where, whereclause) } entityQuery.addWhere("("+strings.Join(where, " OR ")+")", args...) @@ -1339,42 +1007,16 @@ func (s *sqlEntityServer) List(ctx context.Context, r *entity.EntityListRequest) query, args := entityQuery.toQuery() - s.log.Info("listing", "query", query, "args", args) + s.log.Debug("listing", "query", query, "args", args) rows, err := s.sess.Query(ctx, query, args...) if err != nil { return nil, err } defer func() { _ = rows.Close() }() - token := "" rsp := &entity.EntityListResponse{} for rows.Next() { - result := &entity.Entity{ - GRN: &grn.GRN{}, - } - - var labels []byte - var errors []byte - var fields []byte - - args := []any{ - &token, &result.Guid, &result.Key, - &result.GRN.TenantID, &result.GRN.ResourceGroup, &result.GroupVersion, &result.GRN.ResourceKind, &result.GRN.ResourceIdentifier, - &result.Version, &result.Folder, &result.Slug, &errors, - &result.Size, &result.UpdatedAt, &result.UpdatedBy, - &result.Name, &result.Description, - } - if r.WithBody { - args = append(args, &result.Body, &result.Meta, &result.Status) - } - if r.WithLabels { - args = append(args, &labels) - } - if r.WithFields { - args = append(args, &fields) - } - - err = rows.Scan(args...) + result, err := s.rowToEntity(ctx, rows, rr) if err != nil { return rsp, err } @@ -1382,24 +1024,10 @@ func (s *sqlEntityServer) List(ctx context.Context, r *entity.EntityListRequest) // found more than requested if int64(len(rsp.Results)) >= entityQuery.limit { // TODO? this only works if we sort by guid - rsp.NextPageToken = token + rsp.NextPageToken = result.Guid break } - if labels != nil { - err = json.Unmarshal(labels, &result.Labels) - if err != nil { - return rsp, err - } - } - - if fields != nil { - err = json.Unmarshal(fields, &result.Fields) - if err != nil { - return rsp, err - } - } - rsp.Results = append(rsp.Results, result) } @@ -1433,14 +1061,14 @@ func (s *sqlEntityServer) FindReferences(ctx context.Context, r *entity.Referenc fields := []string{ "guid", "guid", - "tenant_id", "group", "group_version", "kind", "uid", + "namespace", "group", "group_version", "resource", "uid", "version", "folder", "slug", "errors", // errors are always returned "size", "updated_at", "updated_by", "name", "description", "meta", } // SELECT entity_ref.* FROM entity_ref - // JOIN entity ON entity_ref.grn = entity.grn + // JOIN entity ON entity_ref.key = entity.key // WHERE family='librarypanel' AND resolved_to='a7975b7a-fb53-4ab7-951d-15810953b54f'; sql := strings.Builder{} @@ -1451,10 +1079,10 @@ func (s *sqlEntityServer) FindReferences(ctx context.Context, r *entity.Referenc } _, _ = sql.WriteString(fmt.Sprintf("entity.%s", f)) } - _, _ = sql.WriteString(" FROM entity_ref JOIN entity ON entity_ref.grn = entity.grn") + _, _ = sql.WriteString(" FROM entity_ref JOIN entity ON entity_ref.key = entity.key") _, _ = sql.WriteString(" WHERE family=? AND resolved_to=?") // TODO tenant ID!!!! - rows, err := s.sess.Query(ctx, sql.String(), r.Kind, r.Uid) + rows, err := s.sess.Query(ctx, sql.String(), r.Resource, r.Uid) if err != nil { return nil, err } @@ -1462,13 +1090,11 @@ func (s *sqlEntityServer) FindReferences(ctx context.Context, r *entity.Referenc token := "" rsp := &entity.EntityListResponse{} for rows.Next() { - result := &entity.Entity{ - GRN: &grn.GRN{}, - } + result := &entity.Entity{} args := []any{ &token, &result.Guid, - &result.GRN.TenantID, &result.GRN.ResourceKind, &result.GRN.ResourceIdentifier, + &result.Namespace, &result.Group, &result.GroupVersion, &result.Resource, &result.Uid, &result.Version, &result.Folder, &result.Slug, &result.Errors, &result.Size, &result.UpdatedAt, &result.UpdatedBy, &result.Name, &result.Description, &result.Meta, diff --git a/pkg/services/store/entity/tests/server_integration_test.go b/pkg/services/store/entity/tests/server_integration_test.go index 4d073a7e7e3..e996af2cb3e 100644 --- a/pkg/services/store/entity/tests/server_integration_test.go +++ b/pkg/services/store/entity/tests/server_integration_test.go @@ -11,10 +11,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/metadata" - "github.com/grafana/grafana/pkg/infra/grn" "github.com/grafana/grafana/pkg/services/store" "github.com/grafana/grafana/pkg/services/store/entity" - "github.com/grafana/grafana/pkg/util" ) var ( @@ -25,7 +23,7 @@ var ( ) type rawEntityMatcher struct { - grn *grn.GRN + key string createdRange []time.Time updatedRange []time.Time createdBy string @@ -53,16 +51,8 @@ func requireEntityMatch(t *testing.T, obj *entity.Entity, m rawEntityMatcher) { require.NotNil(t, obj) mismatches := "" - if m.grn != nil { - if m.grn.TenantID > 0 && m.grn.TenantID != obj.GRN.TenantID { - mismatches += fmt.Sprintf("expected tenant: %d, actual: %d\n", m.grn.TenantID, obj.GRN.TenantID) - } - if m.grn.ResourceKind != "" && m.grn.ResourceKind != obj.GRN.ResourceKind { - mismatches += fmt.Sprintf("expected ResourceKind: %s, actual: %s\n", m.grn.ResourceKind, obj.GRN.ResourceKind) - } - if m.grn.ResourceIdentifier != "" && m.grn.ResourceIdentifier != obj.GRN.ResourceIdentifier { - mismatches += fmt.Sprintf("expected ResourceIdentifier: %s, actual: %s\n", m.grn.ResourceIdentifier, obj.GRN.ResourceIdentifier) - } + if m.key != "" && m.key != obj.Key { + mismatches += fmt.Sprintf("expected key: %s, actual: %s\n", m.key, obj.Key) } if len(m.createdRange) == 2 && !timestampInRange(obj.CreatedAt, m.createdRange) { @@ -134,59 +124,63 @@ func TestIntegrationEntityServer(t *testing.T) { fakeUser := store.GetUserIDString(testCtx.user) firstVersion := "1" - kind := entity.StandardKindJSONObj - testGrn := &grn.GRN{ - ResourceKind: kind, - ResourceIdentifier: "my-test-entity", - } + group := "test.grafana.app" + resource := "jsonobjs" + resource2 := "playlists" + namespace := "default" + uid := "my-test-entity" + testKey := "/" + group + "/" + resource + "/" + namespace + "/" + uid body := []byte("{\"name\":\"John\"}") t.Run("should not retrieve non-existent objects", func(t *testing.T) { resp, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{ - GRN: testGrn, + Key: testKey, }) require.NoError(t, err) require.NotNil(t, resp) - require.Nil(t, resp.GRN) + require.Empty(t, resp.Key) }) t.Run("should be able to read persisted objects", func(t *testing.T) { before := time.Now() - writeReq := &entity.WriteEntityRequest{ + createReq := &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: testGrn, - Body: body, - Message: "first entity!", + Key: testKey, + Group: group, + Resource: resource, + Namespace: namespace, + Uid: uid, + Body: body, + Message: "first entity!", }, } - writeResp, err := testCtx.client.Write(ctx, writeReq) + createResp, err := testCtx.client.Create(ctx, createReq) require.NoError(t, err) versionMatcher := objectVersionMatcher{ updatedRange: []time.Time{before, time.Now()}, updatedBy: fakeUser, version: &firstVersion, - comment: &writeReq.Entity.Message, + comment: &createReq.Entity.Message, } - requireVersionMatch(t, writeResp.Entity, versionMatcher) + requireVersionMatch(t, createResp.Entity, versionMatcher) readResp, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{ - GRN: testGrn, + Key: testKey, Version: "", WithBody: true, }) require.NoError(t, err) require.NotNil(t, readResp) - foundGRN := readResp.GRN - require.NotNil(t, foundGRN) - require.Equal(t, testCtx.user.OrgID, foundGRN.TenantID) // orgId becomes the tenant id when not set - require.Equal(t, testGrn.ResourceKind, foundGRN.ResourceKind) - require.Equal(t, testGrn.ResourceIdentifier, foundGRN.ResourceIdentifier) + require.Equal(t, testKey, readResp.Key) + require.Equal(t, namespace, readResp.Namespace) // orgId becomes the tenant id when not set + require.Equal(t, resource, readResp.Resource) + require.Equal(t, uid, readResp.Uid) objectMatcher := rawEntityMatcher{ - grn: testGrn, + key: testKey, createdRange: []time.Time{before, time.Now()}, updatedRange: []time.Time{before, time.Now()}, createdBy: fakeUser, @@ -197,74 +191,74 @@ func TestIntegrationEntityServer(t *testing.T) { requireEntityMatch(t, readResp, objectMatcher) deleteResp, err := testCtx.client.Delete(ctx, &entity.DeleteEntityRequest{ - GRN: testGrn, - PreviousVersion: writeResp.Entity.Version, + Key: testKey, + PreviousVersion: readResp.Version, }) require.NoError(t, err) require.Equal(t, deleteResp.Status, entity.DeleteEntityResponse_DELETED) readRespAfterDelete, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{ - GRN: testGrn, + Key: testKey, Version: "", WithBody: true, }) require.NoError(t, err) - require.Nil(t, readRespAfterDelete.GRN) + require.Empty(t, readRespAfterDelete.Key) }) t.Run("should be able to update an object", func(t *testing.T) { before := time.Now() - testGrn := &grn.GRN{ - ResourceKind: kind, - ResourceIdentifier: util.GenerateShortUID(), - } - writeReq1 := &entity.WriteEntityRequest{ + createReq := &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: testGrn, - Body: body, - Message: "first entity!", + Key: testKey, + Group: group, + Resource: resource, + Namespace: namespace, + Uid: uid, + Body: body, + Message: "first entity!", }, } - writeResp1, err := testCtx.client.Write(ctx, writeReq1) + createResp, err := testCtx.client.Create(ctx, createReq) require.NoError(t, err) - require.Equal(t, entity.WriteEntityResponse_CREATED, writeResp1.Status) + require.Equal(t, entity.CreateEntityResponse_CREATED, createResp.Status) body2 := []byte("{\"name\":\"John2\"}") - writeReq2 := &entity.WriteEntityRequest{ + updateReq := &entity.UpdateEntityRequest{ Entity: &entity.Entity{ - GRN: testGrn, + Key: testKey, Body: body2, Message: "update1", }, } - writeResp2, err := testCtx.client.Write(ctx, writeReq2) + updateResp, err := testCtx.client.Update(ctx, updateReq) require.NoError(t, err) - require.NotEqual(t, writeResp1.Entity.Version, writeResp2.Entity.Version) + require.NotEqual(t, createResp.Entity.Version, updateResp.Entity.Version) // Duplicate write (no change) - writeDupRsp, err := testCtx.client.Write(ctx, writeReq2) + writeDupRsp, err := testCtx.client.Update(ctx, updateReq) require.NoError(t, err) require.Nil(t, writeDupRsp.Error) - require.Equal(t, entity.WriteEntityResponse_UNCHANGED, writeDupRsp.Status) - require.Equal(t, writeResp2.Entity.Version, writeDupRsp.Entity.Version) - require.Equal(t, writeResp2.Entity.ETag, writeDupRsp.Entity.ETag) + require.Equal(t, entity.UpdateEntityResponse_UNCHANGED, writeDupRsp.Status) + require.Equal(t, updateResp.Entity.Version, writeDupRsp.Entity.Version) + require.Equal(t, updateResp.Entity.ETag, writeDupRsp.Entity.ETag) body3 := []byte("{\"name\":\"John3\"}") - writeReq3 := &entity.WriteEntityRequest{ + writeReq3 := &entity.UpdateEntityRequest{ Entity: &entity.Entity{ - GRN: testGrn, + Key: testKey, Body: body3, Message: "update3", }, } - writeResp3, err := testCtx.client.Write(ctx, writeReq3) + writeResp3, err := testCtx.client.Update(ctx, writeReq3) require.NoError(t, err) - require.NotEqual(t, writeResp3.Entity.Version, writeResp2.Entity.Version) + require.NotEqual(t, writeResp3.Entity.Version, updateResp.Entity.Version) latestMatcher := rawEntityMatcher{ - grn: testGrn, + key: testKey, createdRange: []time.Time{before, time.Now()}, updatedRange: []time.Time{before, time.Now()}, createdBy: fakeUser, @@ -273,7 +267,7 @@ func TestIntegrationEntityServer(t *testing.T) { version: &writeResp3.Entity.Version, } readRespLatest, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{ - GRN: testGrn, + Key: testKey, Version: "", // latest WithBody: true, }) @@ -281,15 +275,15 @@ func TestIntegrationEntityServer(t *testing.T) { requireEntityMatch(t, readRespLatest, latestMatcher) readRespFirstVer, err := testCtx.client.Read(ctx, &entity.ReadEntityRequest{ - GRN: testGrn, - Version: writeResp1.Entity.Version, + Key: testKey, + Version: createResp.Entity.Version, WithBody: true, }) require.NoError(t, err) require.NotNil(t, readRespFirstVer) requireEntityMatch(t, readRespFirstVer, rawEntityMatcher{ - grn: testGrn, + key: testKey, createdRange: []time.Time{before, time.Now()}, updatedRange: []time.Time{before, time.Now()}, createdBy: fakeUser, @@ -299,17 +293,17 @@ func TestIntegrationEntityServer(t *testing.T) { }) history, err := testCtx.client.History(ctx, &entity.EntityHistoryRequest{ - GRN: testGrn, + Key: testKey, }) require.NoError(t, err) require.Equal(t, []*entity.Entity{ writeResp3.Entity, - writeResp2.Entity, - writeResp1.Entity, + updateResp.Entity, + createResp.Entity, }, history.Versions) deleteResp, err := testCtx.client.Delete(ctx, &entity.DeleteEntityRequest{ - GRN: testGrn, + Key: testKey, PreviousVersion: writeResp3.Entity.Version, }) require.NoError(t, err) @@ -317,53 +311,40 @@ func TestIntegrationEntityServer(t *testing.T) { }) t.Run("should be able to list objects", func(t *testing.T) { - uid2 := "uid2" - uid3 := "uid3" - uid4 := "uid4" - kind2 := entity.StandardKindPlaylist - w1, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{ + w1, err := testCtx.client.Create(ctx, &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: testGrn, + Key: testKey + "1", Body: body, }, }) require.NoError(t, err) - w2, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{ + w2, err := testCtx.client.Create(ctx, &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: &grn.GRN{ - ResourceIdentifier: uid2, - ResourceKind: kind, - }, + Key: testKey + "2", Body: body, }, }) require.NoError(t, err) - w3, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{ + w3, err := testCtx.client.Create(ctx, &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: &grn.GRN{ - ResourceIdentifier: uid3, - ResourceKind: kind2, - }, + Key: testKey + "3", Body: body, }, }) require.NoError(t, err) - w4, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{ + w4, err := testCtx.client.Create(ctx, &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: &grn.GRN{ - ResourceIdentifier: uid4, - ResourceKind: kind2, - }, + Key: testKey + "4", Body: body, }, }) require.NoError(t, err) resp, err := testCtx.client.List(ctx, &entity.EntityListRequest{ - Kind: []string{kind, kind2}, + Resource: []string{resource, resource2}, WithBody: false, }) require.NoError(t, err) @@ -373,8 +354,8 @@ func TestIntegrationEntityServer(t *testing.T) { kinds := make([]string, 0, len(resp.Results)) version := make([]string, 0, len(resp.Results)) for _, res := range resp.Results { - uids = append(uids, res.GRN.ResourceIdentifier) - kinds = append(kinds, res.GRN.ResourceKind) + uids = append(uids, res.Uid) + kinds = append(kinds, res.Resource) version = append(version, res.Version) } require.Equal(t, []string{"my-test-entity", "uid2", "uid3", "uid4"}, uids) @@ -388,15 +369,15 @@ func TestIntegrationEntityServer(t *testing.T) { // Again with only one kind respKind1, err := testCtx.client.List(ctx, &entity.EntityListRequest{ - Kind: []string{kind}, + Resource: []string{resource}, }) require.NoError(t, err) uids = make([]string, 0, len(respKind1.Results)) kinds = make([]string, 0, len(respKind1.Results)) version = make([]string, 0, len(respKind1.Results)) for _, res := range respKind1.Results { - uids = append(uids, res.GRN.ResourceIdentifier) - kinds = append(kinds, res.GRN.ResourceKind) + uids = append(uids, res.Uid) + kinds = append(kinds, res.Resource) version = append(version, res.Version) } require.Equal(t, []string{"my-test-entity", "uid2"}, uids) @@ -409,32 +390,25 @@ func TestIntegrationEntityServer(t *testing.T) { t.Run("should be able to filter objects based on their labels", func(t *testing.T) { kind := entity.StandardKindDashboard - _, err := testCtx.client.Write(ctx, &entity.WriteEntityRequest{ + _, err := testCtx.client.Create(ctx, &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: &grn.GRN{ - ResourceKind: kind, - ResourceIdentifier: "blue-green", - }, + Key: "/grafana/dashboards/blue-green", Body: []byte(dashboardWithTagsBlueGreen), }, }) require.NoError(t, err) - _, err = testCtx.client.Write(ctx, &entity.WriteEntityRequest{ + _, err = testCtx.client.Create(ctx, &entity.CreateEntityRequest{ Entity: &entity.Entity{ - GRN: &grn.GRN{ - ResourceKind: kind, - ResourceIdentifier: "red-green", - }, + Key: "/grafana/dashboards/red-green", Body: []byte(dashboardWithTagsRedGreen), }, }) require.NoError(t, err) resp, err := testCtx.client.List(ctx, &entity.EntityListRequest{ - Kind: []string{kind}, - WithBody: false, - WithLabels: true, + Key: []string{kind}, + WithBody: false, Labels: map[string]string{ "red": "", }, @@ -442,12 +416,11 @@ func TestIntegrationEntityServer(t *testing.T) { require.NoError(t, err) require.NotNil(t, resp) require.Len(t, resp.Results, 1) - require.Equal(t, resp.Results[0].GRN.ResourceIdentifier, "red-green") + require.Equal(t, resp.Results[0].Uid, "red-green") resp, err = testCtx.client.List(ctx, &entity.EntityListRequest{ - Kind: []string{kind}, - WithBody: false, - WithLabels: true, + Key: []string{kind}, + WithBody: false, Labels: map[string]string{ "red": "", "green": "", @@ -456,12 +429,11 @@ func TestIntegrationEntityServer(t *testing.T) { require.NoError(t, err) require.NotNil(t, resp) require.Len(t, resp.Results, 1) - require.Equal(t, resp.Results[0].GRN.ResourceIdentifier, "red-green") + require.Equal(t, resp.Results[0].Uid, "red-green") resp, err = testCtx.client.List(ctx, &entity.EntityListRequest{ - Kind: []string{kind}, - WithBody: false, - WithLabels: true, + Key: []string{kind}, + WithBody: false, Labels: map[string]string{ "red": "invalid", }, @@ -471,9 +443,8 @@ func TestIntegrationEntityServer(t *testing.T) { require.Len(t, resp.Results, 0) resp, err = testCtx.client.List(ctx, &entity.EntityListRequest{ - Kind: []string{kind}, - WithBody: false, - WithLabels: true, + Key: []string{kind}, + WithBody: false, Labels: map[string]string{ "green": "", }, @@ -483,9 +454,8 @@ func TestIntegrationEntityServer(t *testing.T) { require.Len(t, resp.Results, 2) resp, err = testCtx.client.List(ctx, &entity.EntityListRequest{ - Kind: []string{kind}, - WithBody: false, - WithLabels: true, + Key: []string{kind}, + WithBody: false, Labels: map[string]string{ "yellow": "", }, diff --git a/pkg/services/store/entity/utils.go b/pkg/services/store/entity/utils.go deleted file mode 100644 index 18ce8613e77..00000000000 --- a/pkg/services/store/entity/utils.go +++ /dev/null @@ -1,9 +0,0 @@ -package entity - -// The admin request is a superset of write request features -func ToAdminWriteEntityRequest(req *WriteEntityRequest) *AdminWriteEntityRequest { - return &AdminWriteEntityRequest{ - Entity: req.Entity, - PreviousVersion: req.PreviousVersion, - } -} diff --git a/pkg/services/store/resolver/service.go b/pkg/services/store/resolver/service.go index 8adf1c6251e..2f9dfa06224 100644 --- a/pkg/services/store/resolver/service.go +++ b/pkg/services/store/resolver/service.go @@ -23,7 +23,7 @@ var getNow = func() time.Time { return time.Now() } type ResolutionInfo struct { OK bool `json:"ok"` - Key string `json:"key,omitempty"` // GRN? UID? + Key string `json:"key,omitempty"` // k8s key Warning string `json:"kind,omitempty"` // old syntax? (name>uid) references a renamed object? Timestamp time.Time `json:"timestamp,omitempty"` }