From 8af89b121098cccad3c8f9ae71e5fd94641055fa Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Tue, 13 Jan 2026 16:34:59 +0300 Subject: [PATCH] ensure GVK is configured --- .../apis/secret/inline/inline_secure_value.go | 4 +-- pkg/storage/unified/apistore/prepare.go | 29 +++++++++++++++---- pkg/tests/apis/datasource/testdata_test.go | 4 +-- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/pkg/registry/apis/secret/inline/inline_secure_value.go b/pkg/registry/apis/secret/inline/inline_secure_value.go index f6805938554..137e34c5e4f 100644 --- a/pkg/registry/apis/secret/inline/inline_secure_value.go +++ b/pkg/registry/apis/secret/inline/inline_secure_value.go @@ -60,7 +60,7 @@ func (s *LocalInlineSecureValueService) CanReference(ctx context.Context, owner } if owner.APIGroup == "" || owner.APIVersion == "" || owner.Kind == "" || owner.Name == "" { - return fmt.Errorf("owner reference must have a valid API group, API version, kind and name") + return fmt.Errorf("owner reference must have a valid API group, API version, kind and name [CanReference]") } if len(names) == 0 { @@ -167,7 +167,7 @@ func (s *LocalInlineSecureValueService) verifyOwnerAndAuth(ctx context.Context, } if owner.Namespace == "" || owner.APIGroup == "" || owner.APIVersion == "" || owner.Kind == "" || owner.Name == "" { - return nil, fmt.Errorf("owner reference must have a valid API group, API version, kind, namespace and name") + return nil, fmt.Errorf("owner reference must have a valid API group, API version, kind, namespace and name [verifyOwnerAndAuth:%+v]", owner) } return authInfo, nil diff --git a/pkg/storage/unified/apistore/prepare.go b/pkg/storage/unified/apistore/prepare.go index 40857b456f3..ccd1579d1c9 100644 --- a/pkg/storage/unified/apistore/prepare.go +++ b/pkg/storage/unified/apistore/prepare.go @@ -85,6 +85,9 @@ func (s *Storage) prepareObjectForStorage(ctx context.Context, newObject runtime if !ok { return v, errors.New("missing auth info") } + if err := s.checkGVK(newObject); err != nil { + return v, err + } obj, err := utils.MetaAccessor(newObject) if err != nil { @@ -153,6 +156,9 @@ func (s *Storage) prepareObjectForUpdate(ctx context.Context, updateObject runti if !ok { return v, errors.New("missing auth info") } + if err := s.checkGVK(updateObject); err != nil { + return v, err + } obj, err := utils.MetaAccessor(updateObject) if err != nil { @@ -273,10 +279,9 @@ func (s *Storage) handleLargeResources(ctx context.Context, obj utils.GrafanaMet return nil } -func (s *Storage) encode(obj runtime.Object, w io.Writer) error { - // The standard encoder is fine when only one type maps to a group +func (s *Storage) checkGVK(obj runtime.Object) error { if s.opts.Scheme == nil { - return s.codec.Encode(obj, w) + return nil // we can not do anything } // Ensure group+version+kind are configured @@ -285,7 +290,7 @@ func (s *Storage) encode(obj runtime.Object, w io.Writer) error { if gvk.Group == "" || gvk.Kind == "" || gvk.Version == "" { gvks, _, err := s.opts.Scheme.ObjectKinds(obj) if err != nil { - return fmt.Errorf("unable to encode object %w", err) + return fmt.Errorf("unknown object kind %w", err) } for _, v := range gvks { if v.Group != s.gr.Group { @@ -297,9 +302,23 @@ func (s *Storage) encode(obj runtime.Object, w io.Writer) error { gvk.Version = v.Version } info.SetGroupVersionKind(gvk) - break + return nil } } + return nil +} +func (s *Storage) encode(obj runtime.Object, w io.Writer) error { + // The standard encoder is fine when only one type maps to a group + if s.opts.Scheme == nil { + return s.codec.Encode(obj, w) + } + if err := s.checkGVK(obj); err != nil { + return err + } + + // This will always write the saved GVK, unlike: + // https://github.com/kubernetes/kubernetes/blob/v1.34.3/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go#L267 + // that picks an arbitrary GVK that may not match the same group! return json.NewEncoder(w).Encode(obj) } diff --git a/pkg/tests/apis/datasource/testdata_test.go b/pkg/tests/apis/datasource/testdata_test.go index 4179b006130..87de1bb7a2b 100644 --- a/pkg/tests/apis/datasource/testdata_test.go +++ b/pkg/tests/apis/datasource/testdata_test.go @@ -36,8 +36,8 @@ func TestIntegrationTestDatasource(t *testing.T) { for _, mode := range []grafanarest.DualWriterMode{ grafanarest.Mode0, // Legacy only - // grafanarest.Mode2, // write both, read legacy - // grafanarest.Mode3, // write both, read unified + grafanarest.Mode2, // write both, read legacy + grafanarest.Mode3, // write both, read unified grafanarest.Mode5, // Unified only } { t.Run(fmt.Sprintf("testdata (mode:%d)", mode), func(t *testing.T) {