From 8c15a76aec0489f63ab841e4aaf09391d2e68912 Mon Sep 17 00:00:00 2001 From: Sebastian Florek Date: Sun, 27 Oct 2024 12:32:53 +0100 Subject: [PATCH] fix(api): ssar resource kind name and resource updates (#9599) * fix: ssar resource kind name invalid * fix resource update --- hack/docker/dev.compose.yml | 1 + modules/api/go.mod | 1 + modules/api/go.sum | 2 + modules/auth/go.mod | 2 +- modules/auth/go.sum | 4 +- .../client/common/resourcelister_options.go | 6 ++- modules/common/client/go.mod | 2 +- modules/common/client/go.sum | 4 +- modules/common/client/verber.go | 42 +++++++++++++++---- modules/web/go.mod | 2 +- modules/web/go.sum | 4 +- .../common/components/namespace/component.ts | 13 +++--- 12 files changed, 60 insertions(+), 23 deletions(-) diff --git a/hack/docker/dev.compose.yml b/hack/docker/dev.compose.yml index 09ad9250c8cf..aff0827f54fd 100644 --- a/hack/docker/dev.compose.yml +++ b/hack/docker/dev.compose.yml @@ -54,6 +54,7 @@ services: command: --kubeconfig=${KUBECONFIG:?} --sidecar-host=${SIDECAR_HOST:?} + --v=4 volumes: - ${PWD}/modules/common:/workspace/common # Required - Common dir watched by AIR - ${PWD}/modules/api/pkg:/workspace/api/pkg # Required - Source dir watched by AIR diff --git a/modules/api/go.mod b/modules/api/go.mod index 161dad33f687..24c0e1e868a3 100644 --- a/modules/api/go.mod +++ b/modules/api/go.mod @@ -38,6 +38,7 @@ require ( github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect diff --git a/modules/api/go.sum b/modules/api/go.sum index e0449decda5b..874f37f5484e 100644 --- a/modules/api/go.sum +++ b/modules/api/go.sum @@ -46,6 +46,8 @@ github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtz github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= diff --git a/modules/auth/go.mod b/modules/auth/go.mod index 9544c4a42d18..93c26be4e293 100644 --- a/modules/auth/go.mod +++ b/modules/auth/go.mod @@ -23,6 +23,7 @@ require ( github.com/cloudwego/iasm v0.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gammazero/deque v0.2.1 // indirect @@ -67,7 +68,6 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/auth/go.sum b/modules/auth/go.sum index 4d6b53738101..8f3a6a1bf9ac 100644 --- a/modules/auth/go.sum +++ b/modules/auth/go.sum @@ -17,6 +17,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= @@ -194,8 +196,6 @@ google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWn gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/modules/common/client/cache/client/common/resourcelister_options.go b/modules/common/client/cache/client/common/resourcelister_options.go index c06f7c59d0fb..1beb4a423ff8 100644 --- a/modules/common/client/cache/client/common/resourcelister_options.go +++ b/modules/common/client/cache/client/common/resourcelister_options.go @@ -15,6 +15,10 @@ package common import ( + "strings" + + "github.com/gobuffalo/flect" + "k8s.io/dashboard/types" ) @@ -28,7 +32,7 @@ func WithNamespace[T any](namespace string) Option[T] { func WithResourceKind[T any](kind types.ResourceKind) Option[T] { return func(lister *CachedResourceLister[T]) { - lister.ssar.Spec.ResourceAttributes.Resource = kind.String() + lister.ssar.Spec.ResourceAttributes.Resource = flect.Pluralize(strings.ToLower(kind.String())) } } diff --git a/modules/common/client/go.mod b/modules/common/client/go.mod index 6ec18fc7293f..3c0cbbff634d 100644 --- a/modules/common/client/go.mod +++ b/modules/common/client/go.mod @@ -4,6 +4,7 @@ go 1.23.0 require ( github.com/Yiling-J/theine-go v0.5.0 + github.com/evanphx/json-patch/v5 v5.9.0 github.com/gobuffalo/flect v1.0.3 github.com/spf13/pflag v1.0.5 k8s.io/api v0.31.1 @@ -50,7 +51,6 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/common/client/go.sum b/modules/common/client/go.sum index ef4f84b8d773..40b10bbc7bd3 100644 --- a/modules/common/client/go.sum +++ b/modules/common/client/go.sum @@ -9,6 +9,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= @@ -146,8 +148,6 @@ google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWn gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/modules/common/client/verber.go b/modules/common/client/verber.go index a6eedf08788d..c71c27c058f8 100644 --- a/modules/common/client/verber.go +++ b/modules/common/client/verber.go @@ -18,17 +18,20 @@ import ( "context" "fmt" "net/http" + "reflect" "strings" + jsonpatch "github.com/evanphx/json-patch/v5" "github.com/gobuffalo/flect" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" k8stypes "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/jsonmergepatch" + "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/util/retry" "k8s.io/klog/v2" ) @@ -169,14 +172,39 @@ func (v *resourceVerber) Update(object *unstructured.Unstructured) error { return fmt.Errorf("failed to marshal modified data: %w", err) } - patchBytes, err := jsonmergepatch.CreateThreeWayJSONMergePatch(origData, modifiedData, origData) - if err != nil { - return fmt.Errorf("failed creating merge patch: %w", err) + if reflect.DeepEqual(result, object) { + klog.V(3).InfoS("original and updated objects are the same, skipping") + return nil } - klog.V(2).InfoS("patching resource", "group", gvr.Group, "version", gvr.Version, "resource", gvr.Resource, "name", name, "namespace", namespace, "patch", string(patchBytes)) - _, updateErr := v.client.Resource(gvr).Namespace(namespace).Patch(context.TODO(), name, k8stypes.MergePatchType, patchBytes, metav1.PatchOptions{}) - return updateErr + versionedObject, err := scheme.Scheme.New(schema.GroupVersionKind{ + Group: gvr.Group, + Version: gvr.Version, + Kind: object.GetKind(), + }) + + switch { + case runtime.IsNotRegisteredError(err): + patchBytes, err := jsonpatch.CreateMergePatch(origData, modifiedData) + if err != nil { + return fmt.Errorf("failed creating merge patch: %w", err) + } + + klog.V(2).InfoS("patching resource", "group", gvr.Group, "version", gvr.Version, "resource", gvr.Resource, "name", name, "namespace", namespace, "patch", string(patchBytes)) + _, updateErr := v.client.Resource(gvr).Namespace(namespace).Patch(context.TODO(), name, k8stypes.MergePatchType, patchBytes, metav1.PatchOptions{}) + return updateErr + case err != nil: + return err + default: + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(origData, modifiedData, versionedObject) + if err != nil { + return fmt.Errorf("failed creating two way merge patch: %w", err) + } + + klog.V(2).InfoS("patching resource", "group", gvr.Group, "version", gvr.Version, "resource", gvr.Resource, "name", name, "namespace", namespace, "patch", string(patchBytes)) + _, updateErr := v.client.Resource(gvr).Namespace(namespace).Patch(context.TODO(), name, k8stypes.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) + return updateErr + } }) } diff --git a/modules/web/go.mod b/modules/web/go.mod index fd233282cacd..00e2a4481b1d 100644 --- a/modules/web/go.mod +++ b/modules/web/go.mod @@ -27,6 +27,7 @@ require ( github.com/cloudwego/iasm v0.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gammazero/deque v0.2.1 // indirect @@ -70,7 +71,6 @@ require ( golang.org/x/term v0.23.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/web/go.sum b/modules/web/go.sum index b16872b5a5f1..aff494e61bc3 100644 --- a/modules/web/go.sum +++ b/modules/web/go.sum @@ -19,6 +19,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= @@ -196,8 +198,6 @@ google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWn gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/modules/web/src/common/components/namespace/component.ts b/modules/web/src/common/components/namespace/component.ts index 188d22ea7e67..0d778e01c199 100644 --- a/modules/web/src/common/components/namespace/component.ts +++ b/modules/web/src/common/components/namespace/component.ts @@ -53,6 +53,7 @@ export class NamespaceSelectorComponent implements OnInit { @ViewChild('namespaceInput', {static: true}) private readonly namespaceInputEl_: ElementRef; private destroyRef = inject(DestroyRef); + constructor( private readonly router_: Router, private readonly namespaceService_: NamespaceService, @@ -164,8 +165,8 @@ export class NamespaceSelectorComponent implements OnInit { .pipe(startWith({})) .pipe(switchMap(() => this.namespace_.get(this.endpoint_.list()))) .pipe(takeUntilDestroyed(this.destroyRef)) - .subscribe( - namespaceList => { + .subscribe({ + next: namespaceList => { this.usingFallbackNamespaces = false; this.namespaces = namespaceList.namespaces.map(n => n.objectMeta.name); @@ -182,11 +183,11 @@ export class NamespaceSelectorComponent implements OnInit { } } }, - () => {}, - () => { + error: () => {}, + complete: () => { this.onNamespaceLoaded_(); - } - ); + }, + }); } private handleNamespaceChangeDialog_(): void {