From 7613ab7a5be60188003e2786252df905ee599b68 Mon Sep 17 00:00:00 2001 From: Dan Cech Date: Tue, 19 Dec 2023 17:34:57 +0100 Subject: [PATCH] Storage: store full k8s object in body column (#79480) store full k8s object in body column --- pkg/services/grafana-apiserver/service.go | 4 +-- .../storage/entity/storage.go | 14 +++++----- .../grafana-apiserver/storage/entity/utils.go | 28 +++++++++---------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/pkg/services/grafana-apiserver/service.go b/pkg/services/grafana-apiserver/service.go index c99ec36a6f6..d76616ab600 100644 --- a/pkg/services/grafana-apiserver/service.go +++ b/pkg/services/grafana-apiserver/service.go @@ -289,7 +289,7 @@ func (s *service) start(ctx context.Context) error { return err } - serverConfig.Config.RESTOptionsGetter = entitystorage.NewRESTOptionsGetter(s.cfg, store, nil) + serverConfig.Config.RESTOptionsGetter = entitystorage.NewRESTOptionsGetter(s.cfg, store, o.Etcd.StorageConfig.Codec) case StorageTypeUnifiedGrpc: // Create a connection to the gRPC server @@ -305,7 +305,7 @@ func (s *service) start(ctx context.Context) error { // Create a client instance store := entity.NewEntityStoreClientWrapper(conn) - serverConfig.Config.RESTOptionsGetter = entitystorage.NewRESTOptionsGetter(s.cfg, store, nil) + serverConfig.Config.RESTOptionsGetter = entitystorage.NewRESTOptionsGetter(s.cfg, store, o.Etcd.StorageConfig.Codec) case StorageTypeFile: serverConfig.RESTOptionsGetter = filestorage.NewRESTOptionsGetter(s.config.dataPath, o.Etcd.StorageConfig) diff --git a/pkg/services/grafana-apiserver/storage/entity/storage.go b/pkg/services/grafana-apiserver/storage/entity/storage.go index c6c56beae74..1ca24e958d2 100644 --- a/pkg/services/grafana-apiserver/storage/entity/storage.go +++ b/pkg/services/grafana-apiserver/storage/entity/storage.go @@ -100,7 +100,7 @@ func (s *Storage) Create(ctx context.Context, key string, obj runtime.Object, ou metaAccessor.SetGenerateName("") } - e, err := resourceToEntity(key, obj, requestInfo) + e, err := resourceToEntity(key, obj, requestInfo, s.codec) if err != nil { return err } @@ -117,7 +117,7 @@ func (s *Storage) Create(ctx context.Context, key string, obj runtime.Object, ou return fmt.Errorf("this was not a create operation... (%s)", rsp.Status.String()) } - err = entityToResource(rsp.Entity, out) + err = entityToResource(rsp.Entity, out, s.codec) if err != nil { return apierrors.NewInternalError(err) } @@ -151,7 +151,7 @@ func (s *Storage) Delete(ctx context.Context, key string, out runtime.Object, pr return err } - err = entityToResource(rsp.Entity, out) + err = entityToResource(rsp.Entity, out, s.codec) if err != nil { return apierrors.NewInternalError(err) } @@ -193,7 +193,7 @@ func (s *Storage) Get(ctx context.Context, key string, opts storage.GetOptions, return apierrors.NewNotFound(s.gr, key) } - err = entityToResource(rsp, objPtr) + err = entityToResource(rsp, objPtr, s.codec) if err != nil { return apierrors.NewInternalError(err) } @@ -232,7 +232,7 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti for _, r := range rsp.Results { res := s.newFunc() - err := entityToResource(r, res) + err := entityToResource(r, res, s.codec) if err != nil { return apierrors.NewInternalError(err) } @@ -327,7 +327,7 @@ func (s *Storage) guaranteedUpdate( return apierrors.NewInternalError(fmt.Errorf("could not successfully update object. key=%s, err=%s", key, err.Error())) } - e, err := resourceToEntity(key, updatedObj, requestInfo) + e, err := resourceToEntity(key, updatedObj, requestInfo, s.codec) if err != nil { return err } @@ -351,7 +351,7 @@ func (s *Storage) guaranteedUpdate( return nil // destination is already set } - err = entityToResource(rsp.Entity, destination) + err = entityToResource(rsp.Entity, destination, s.codec) if err != nil { return apierrors.NewInternalError(err) } diff --git a/pkg/services/grafana-apiserver/storage/entity/utils.go b/pkg/services/grafana-apiserver/storage/entity/utils.go index beef0c7e477..c39dbb3579f 100644 --- a/pkg/services/grafana-apiserver/storage/entity/utils.go +++ b/pkg/services/grafana-apiserver/storage/entity/utils.go @@ -1,6 +1,7 @@ package entity import ( + "bytes" "encoding/json" "reflect" "time" @@ -8,6 +9,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/endpoints/request" @@ -16,7 +18,7 @@ import ( ) // this is terrible... but just making it work!!!! -func entityToResource(rsp *entityStore.Entity, res runtime.Object) error { +func entityToResource(rsp *entityStore.Entity, res runtime.Object, codec runtime.Codec) error { var err error metaAccessor, err := meta.Accessor(res) @@ -72,13 +74,11 @@ func entityToResource(rsp *entityStore.Entity, res runtime.Object) error { // TODO fields? if len(rsp.Body) > 0 { - spec := reflect.ValueOf(res).Elem().FieldByName("Spec") - if spec != (reflect.Value{}) && spec.CanSet() { - err = json.Unmarshal(rsp.Body, spec.Addr().Interface()) - if err != nil { - return err - } + decoded, _, err := codec.Decode(rsp.Body, &schema.GroupVersionKind{Group: rsp.Group, Version: rsp.GroupVersion}, res) + if err != nil { + return err } + res = decoded } if len(rsp.Status) > 0 { @@ -94,7 +94,7 @@ func entityToResource(rsp *entityStore.Entity, res runtime.Object) error { return nil } -func resourceToEntity(key string, res runtime.Object, requestInfo *request.RequestInfo) (*entityStore.Entity, error) { +func resourceToEntity(key string, res runtime.Object, requestInfo *request.RequestInfo, codec runtime.Codec) (*entityStore.Entity, error) { metaAccessor, err := meta.Accessor(res) if err != nil { return nil, err @@ -147,14 +147,12 @@ func resourceToEntity(key string, res runtime.Object, requestInfo *request.Reque return nil, err } - // TODO: store entire object in body? - spec := reflect.ValueOf(res).Elem().FieldByName("Spec") - if spec != (reflect.Value{}) { - rsp.Body, err = json.Marshal(spec.Interface()) - if err != nil { - return nil, err - } + var buf bytes.Buffer + err = codec.Encode(res, &buf) + if err != nil { + return nil, err } + rsp.Body = buf.Bytes() status := reflect.ValueOf(res).Elem().FieldByName("Status") if status != (reflect.Value{}) {