From de6eb8cbb6902ce37fa5b1a387ff49eed7a83dec Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 6 Aug 2024 17:08:50 +0200 Subject: [PATCH 01/10] Fixes to make migrator up to date --- hack/runtime-migrator/main.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/hack/runtime-migrator/main.go b/hack/runtime-migrator/main.go index 97791825..3aee2f6e 100644 --- a/hack/runtime-migrator/main.go +++ b/hack/runtime-migrator/main.go @@ -166,7 +166,6 @@ func saveRuntime(ctx context.Context, cfg migrator.Config, runtime v1.Runtime, g func createRuntime(ctx context.Context, shoot v1beta1.Shoot, cfg migrator.Config, provider kubeconfig.Provider) (v1.Runtime, error) { var subjects = getAdministratorsList(ctx, provider, shoot.Name) var oidcConfig = getOidcConfig(shoot) - var hAFailureToleranceType = getFailureToleranceType(shoot) var licenceType = shoot.Annotations["kcp.provisioner.kyma-project.io/licence-type"] labels, err := getAllRuntimeLabels(ctx, shoot, cfg.Client) if err != nil { @@ -210,16 +209,13 @@ func createRuntime(ctx context.Context, shoot v1beta1.Shoot, cfg migrator.Config Workers: shoot.Spec.Provider.Workers, }, Networking: v1.Networking{ + Type: shoot.Spec.Networking.Type, Pods: *shoot.Spec.Networking.Pods, Nodes: *shoot.Spec.Networking.Nodes, Services: *shoot.Spec.Networking.Services, }, ControlPlane: v1beta1.ControlPlane{ - HighAvailability: &v1beta1.HighAvailability{ - FailureTolerance: v1beta1.FailureTolerance{ - Type: hAFailureToleranceType, - }, - }, + HighAvailability: getHighAvailability(shoot), }, }, Security: v1.Security{ @@ -280,13 +276,18 @@ func getShootList(ctx context.Context, cfg migrator.Config, gardenerNamespace st return list } -func getFailureToleranceType(shoot v1beta1.Shoot) v1beta1.FailureToleranceType { +func getHighAvailability(shoot v1beta1.Shoot) *v1beta1.HighAvailability { if shoot.Spec.ControlPlane != nil { if shoot.Spec.ControlPlane.HighAvailability != nil { - return shoot.Spec.ControlPlane.HighAvailability.FailureTolerance.Type + return &v1beta1.HighAvailability{ + FailureTolerance: v1beta1.FailureTolerance{ + Type: shoot.Spec.ControlPlane.HighAvailability.FailureTolerance.Type, + }, + } } } - return "" + + return nil } func getAdministratorsList(ctx context.Context, provider kubeconfig.Provider, shootName string) []string { @@ -395,8 +396,14 @@ func getAllRuntimeLabels(ctx context.Context, shoot v1beta1.Shoot, getClient mig return map[string]string{}, errors.Wrap(clientErr, fmt.Sprintf("Failed to get GardenerClient for shoot %s - %s\n", shoot.Name, clientErr)) } gardenerCluster := v1.GardenerCluster{} - shootKey := types.NamespacedName{Name: shoot.Name, Namespace: "kcp-system"} - getGardenerCRerr := k8sClient.Get(ctx, shootKey, &gardenerCluster) + + kymaID, found := shoot.Annotations["kcp.provisioner.kyma-project.io/runtime-id"] + if !found { + return nil, errors.New("Runtime ID not found in shoot annotations") + } + + gardenerCRKey := types.NamespacedName{Name: kymaID, Namespace: "kcp-system"} + getGardenerCRerr := k8sClient.Get(ctx, gardenerCRKey, &gardenerCluster) if getGardenerCRerr != nil { var errMsg = fmt.Sprintf("Failed to retrieve GardenerCluster CR for shoot %s\n", shoot.Name) return map[string]string{}, errors.Wrap(getGardenerCRerr, errMsg) @@ -410,7 +417,8 @@ func getAllRuntimeLabels(ctx context.Context, shoot v1beta1.Shoot, getClient mig enrichedRuntimeLabels["kyma-project.io/region"] = gardenerCluster.Labels["kyma-project.io/region"] enrichedRuntimeLabels["kyma-project.io/shoot-name"] = gardenerCluster.Labels["kyma-project.io/shoot-name"] enrichedRuntimeLabels["operator.kyma-project.io/kyma-name"] = gardenerCluster.Labels["operator.kyma-project.io/kyma-name"] - + // The runtime CR should not be controlled by the KIM + enrichedRuntimeLabels["kyma-project.io/controlled-by-provisioner"] = "false" // add custom label for the migrator enrichedRuntimeLabels[migratorLabel] = "true" From 67ba2e080bae1a0754be2c5abae1cac5972938f9 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Wed, 7 Aug 2024 09:35:27 +0200 Subject: [PATCH 02/10] First version of the Extension comparator --- hack/runtime-migrator/main.go | 11 +-- hack/shoot-comparator/go.mod | 5 +- .../pkg/shoot/etensionmatcher_test.go | 74 +++++++++++++++ .../pkg/shoot/extensionmatcher.go | 95 +++++++++++++++++++ hack/shoot-comparator/pkg/shoot/matcher.go | 64 +++++++------ 5 files changed, 210 insertions(+), 39 deletions(-) create mode 100644 hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go create mode 100644 hack/shoot-comparator/pkg/shoot/extensionmatcher.go diff --git a/hack/runtime-migrator/main.go b/hack/runtime-migrator/main.go index 3aee2f6e..53677cd3 100644 --- a/hack/runtime-migrator/main.go +++ b/hack/runtime-migrator/main.go @@ -214,9 +214,7 @@ func createRuntime(ctx context.Context, shoot v1beta1.Shoot, cfg migrator.Config Nodes: *shoot.Spec.Networking.Nodes, Services: *shoot.Spec.Networking.Services, }, - ControlPlane: v1beta1.ControlPlane{ - HighAvailability: getHighAvailability(shoot), - }, + ControlPlane: getControlPlane(shoot), }, Security: v1.Security{ Administrators: subjects, @@ -276,18 +274,19 @@ func getShootList(ctx context.Context, cfg migrator.Config, gardenerNamespace st return list } -func getHighAvailability(shoot v1beta1.Shoot) *v1beta1.HighAvailability { +func getControlPlane(shoot v1beta1.Shoot) v1beta1.ControlPlane { if shoot.Spec.ControlPlane != nil { if shoot.Spec.ControlPlane.HighAvailability != nil { - return &v1beta1.HighAvailability{ + return v1beta1.ControlPlane{HighAvailability: &v1beta1.HighAvailability{ FailureTolerance: v1beta1.FailureTolerance{ Type: shoot.Spec.ControlPlane.HighAvailability.FailureTolerance.Type, }, + }, } } } - return nil + return v1beta1.ControlPlane{} } func getAdministratorsList(ctx context.Context, provider kubeconfig.Provider, shootName string) []string { diff --git a/hack/shoot-comparator/go.mod b/hack/shoot-comparator/go.mod index 2f6be242..b1374110 100644 --- a/hack/shoot-comparator/go.mod +++ b/hack/shoot-comparator/go.mod @@ -6,8 +6,11 @@ require ( github.com/gardener/gardener v1.98.0 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 + github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 + gopkg.in/yaml.v3 v3.0.1 + k8s.io/apimachinery v0.29.6 sigs.k8s.io/yaml v1.4.0 ) @@ -31,10 +34,8 @@ require ( golang.org/x/tools v0.22.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 k8s.io/api v0.29.6 // indirect k8s.io/apiextensions-apiserver v0.29.6 // indirect - k8s.io/apimachinery v0.29.6 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go b/hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go new file mode 100644 index 00000000..06866988 --- /dev/null +++ b/hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go @@ -0,0 +1,74 @@ +package shoot + +import ( + "github.com/gardener/gardener/pkg/apis/core/v1beta1" + . "github.com/onsi/ginkgo/v2" //nolint:revive + . "github.com/onsi/gomega" //nolint:revive +) + +var _ = Describe(":: extension matcher :: ", func() { + var empty []v1beta1.Extension + + DescribeTable( + "checking invalid args :: ", + testExtensionInvalidArgs, + Entry("when actual is nil", nil, empty), + Entry("when expected is nil", "", nil), + ) + + //disabledTrue := true + disabledFalse := false + + DescribeTable( + "checking results :: ", + testExtensionResults, + Entry( + "should match empty and zero values", + nil, + empty, + true, + ), + Entry( + "should match identical tables", + newExtensionTable(newExtension("test", &disabledFalse)), + newExtensionTable(newExtension("test", &disabledFalse)), + true, + ), + Entry( + "should detect extension missing", + newExtensionTable(newExtension("test1", &disabledFalse), newExtension("test2", &disabledFalse)), + newExtensionTable(newExtension("test", &disabledFalse)), + false, + ), + Entry( + "should detect redundant extension", + newExtensionTable(newExtension("test", &disabledFalse)), + newExtensionTable(newExtension("test1", &disabledFalse), newExtension("test2", &disabledFalse)), + false, + ), + ) +}) + +func newExtension(name string, disabled *bool) v1beta1.Extension { + return v1beta1.Extension{ + Type: name, + Disabled: disabled, + } +} + +func newExtensionTable(extensions ...v1beta1.Extension) []v1beta1.Extension { + return extensions +} + +func testExtensionInvalidArgs(actual, expected interface{}) { + matcher := NewExtensionMatcher(expected) + _, err := matcher.Match(actual) + Expect(err).To(HaveOccurred()) +} + +func testExtensionResults(actual, expected interface{}, expectedMatch bool) { + matcher := NewExtensionMatcher(expected) + actualMatch, err := matcher.Match(actual) + Expect(err).ShouldNot(HaveOccurred()) + Expect(actualMatch).Should(Equal(expectedMatch), matcher.FailureMessage(actual)) +} diff --git a/hack/shoot-comparator/pkg/shoot/extensionmatcher.go b/hack/shoot-comparator/pkg/shoot/extensionmatcher.go new file mode 100644 index 00000000..5377da41 --- /dev/null +++ b/hack/shoot-comparator/pkg/shoot/extensionmatcher.go @@ -0,0 +1,95 @@ +package shoot + +import ( + "fmt" + "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/onsi/gomega" + "github.com/onsi/gomega/types" + "github.com/pkg/errors" + "reflect" + "strings" +) + +type ExtensionMatcher struct { + toMatch interface{} + fails []string +} + +func NewExtensionMatcher(i interface{}) types.GomegaMatcher { + return &ExtensionMatcher{ + toMatch: i, + } +} + +func (m *ExtensionMatcher) Match(actual interface{}) (success bool, err error) { + + if err != nil { + return false, err + } + + if actual == nil && m.toMatch != nil { + return false, errors.New("actual is nil") + } + + if actual != nil && m.toMatch == nil { + return false, errors.New("expected is nil") + } + + if actual == nil && m.toMatch == nil { + return true, nil + } + + aExtensions, err := getExtension(actual) + findExtension := func(extensions []v1beta1.Extension, extensionToFind string) v1beta1.Extension { + for _, extension := range extensions { + if extension.Type == extensionToFind { + return extension + } + } + return v1beta1.Extension{} + } + + eExtensions, err := getExtension(m.toMatch) + if err != nil { + return false, err + } + + for i, eExtension := range eExtensions { + aExtension := findExtension(aExtensions, eExtension.Type) + matcher := gomega.BeComparableTo(eExtension.Type) + ok, err := matcher.Match(aExtension.Type) + if err != nil { + return false, err + } + + if !ok { + msg := fmt.Sprintf("spec/Extensions[%d]: %s", i, matcher.FailureMessage(aExtension)) + m.fails = append(m.fails, msg) + } + + } + + return false, nil +} + +func (m *ExtensionMatcher) NegatedFailureMessage(_ interface{}) string { + return "expected should not equal actual" +} + +func (m *ExtensionMatcher) FailureMessage(_ interface{}) string { + return strings.Join(m.fails, "\n") +} + +func getExtension(i interface{}) (shoot []v1beta1.Extension, err error) { + if i == nil { + return []v1beta1.Extension{}, fmt.Errorf("invalid value nil") + } + + switch v := i.(type) { + case []v1beta1.Extension: + return v, nil + + default: + return []v1beta1.Extension{}, fmt.Errorf(`%w: %s`, errInvalidType, reflect.TypeOf(v)) + } +} diff --git a/hack/shoot-comparator/pkg/shoot/matcher.go b/hack/shoot-comparator/pkg/shoot/matcher.go index 4202f08d..3b6606b6 100644 --- a/hack/shoot-comparator/pkg/shoot/matcher.go +++ b/hack/shoot-comparator/pkg/shoot/matcher.go @@ -67,138 +67,140 @@ func (m *Matcher) Match(actual interface{}) (success bool, err error) { // Note: we define separate matchers for each field to make input more readable // Annotations are not matched as they are not relevant for the comparison ; both KIM, and Provisioner have different set of annotations for _, matcher := range []matcher{ - { - GomegaMatcher: gomega.Equal(eShoot.TypeMeta), - expected: aShoot.TypeMeta, - }, - { - GomegaMatcher: gomega.Equal(eShoot.Name), + // We need to skip comparing type meta as Provisioner doesn't set it. + // It is simpler to skip it than to make fix in the Provisioner. + //{ + // GomegaMatcher: gomega.BeComparableTo(eShoot.TypeMeta), + // expected: aShoot.TypeMeta, + //}, + { + GomegaMatcher: gomega.BeComparableTo(eShoot.Name), expected: aShoot.Name, path: "metadata/name", }, { - GomegaMatcher: gomega.Equal(eShoot.Namespace), + GomegaMatcher: gomega.BeComparableTo(eShoot.Namespace), expected: aShoot.Namespace, path: "metadata/namespace", }, { - GomegaMatcher: gomega.Equal(eShoot.Labels), + GomegaMatcher: gomega.BeComparableTo(eShoot.Labels), expected: aShoot.Labels, path: "metadata/labels", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Addons), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Addons), expected: aShoot.Spec.Addons, path: "spec/Addons", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.CloudProfileName), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.CloudProfileName), expected: aShoot.Spec.CloudProfileName, path: "spec/CloudProfileName", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.DNS), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.DNS), expected: aShoot.Spec.DNS, path: "spec/DNS", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Extensions), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Extensions), expected: aShoot.Spec.Extensions, path: "spec/Extensions", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Hibernation), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Hibernation), expected: aShoot.Spec.Hibernation, path: "spec/Hibernation", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Kubernetes), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Kubernetes), expected: aShoot.Spec.Kubernetes, path: "spec/Kubernetes", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Networking), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Networking), expected: aShoot.Spec.Networking, path: "spec/Networking", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Maintenance), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Maintenance), expected: aShoot.Spec.Maintenance, path: "spec/Maintenance", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Monitoring), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Monitoring), expected: aShoot.Spec.Monitoring, path: "spec/Monitoring", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Provider), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Provider), expected: aShoot.Spec.Provider, path: "spec/Provider", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Purpose), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Purpose), expected: aShoot.Spec.Purpose, path: "spec/Purpose", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Region), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Region), expected: aShoot.Spec.Region, path: "spec/Region", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.SecretBindingName), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SecretBindingName), expected: aShoot.Spec.SecretBindingName, path: "spec/SecretBindingName", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.SeedName), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SeedName), expected: aShoot.Spec.SeedName, path: "spec/SeedName", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.SeedSelector), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SeedSelector), expected: aShoot.Spec.SeedSelector, path: "spec/SeedSelector", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Resources), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Resources), expected: aShoot.Spec.Resources, path: "spec/Resources", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.Tolerations), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Tolerations), expected: aShoot.Spec.Tolerations, path: "spec/Tolerations", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.ExposureClassName), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.ExposureClassName), expected: aShoot.Spec.ExposureClassName, path: "spec/ExposureClassName", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.SystemComponents), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SystemComponents), expected: aShoot.Spec.SystemComponents, path: "spec/SystemComponents", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.ControlPlane), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.ControlPlane), expected: aShoot.Spec.ControlPlane, path: "spec/ControlPlane", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.SchedulerName), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SchedulerName), expected: aShoot.Spec.SchedulerName, path: "spec/SchedulerName", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.CloudProfile), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.CloudProfile), expected: aShoot.Spec.CloudProfile, path: "spec/CloudProfile", }, { - GomegaMatcher: gomega.Equal(eShoot.Spec.CredentialsBindingName), + GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.CredentialsBindingName), expected: aShoot.Spec.CredentialsBindingName, path: "spec/CredentialsBindingName", }, From 1c84bff0d693fcac66bdb90d11cf806fb423eea3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Mon, 12 Aug 2024 10:52:58 +0200 Subject: [PATCH 03/10] Extensions matcher used plus some fixes for comparison --- api/v1/runtime_types.go | 22 ++-- api/v1/zz_generated.deepcopy.go | 6 +- hack/runtime-migrator/main.go | 6 +- .../pkg/shoot/etensionmatcher_test.go | 74 ------------ .../pkg/shoot/extensionmatcher.go | 56 ++++----- .../pkg/shoot/extensionmatcher_test.go | 106 ++++++++++++++++++ hack/shoot-comparator/pkg/shoot/matcher.go | 2 +- internal/gardener/shoot/converter.go | 2 +- 8 files changed, 155 insertions(+), 119 deletions(-) delete mode 100644 hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go create mode 100644 hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go diff --git a/api/v1/runtime_types.go b/api/v1/runtime_types.go index 1e6af618..1ab41cbe 100644 --- a/api/v1/runtime_types.go +++ b/api/v1/runtime_types.go @@ -139,17 +139,17 @@ type RuntimeStatus struct { } type RuntimeShoot struct { - Name string `json:"name"` - Purpose gardener.ShootPurpose `json:"purpose"` - PlatformRegion string `json:"platformRegion"` - Region string `json:"region"` - LicenceType *string `json:"licenceType,omitempty"` - SecretBindingName string `json:"secretBindingName"` - EnforceSeedLocation *bool `json:"enforceSeedLocation,omitempty"` - Kubernetes Kubernetes `json:"kubernetes,omitempty"` - Provider Provider `json:"provider"` - Networking Networking `json:"networking"` - ControlPlane gardener.ControlPlane `json:"controlPlane"` + Name string `json:"name"` + Purpose gardener.ShootPurpose `json:"purpose"` + PlatformRegion string `json:"platformRegion"` + Region string `json:"region"` + LicenceType *string `json:"licenceType,omitempty"` + SecretBindingName string `json:"secretBindingName"` + EnforceSeedLocation *bool `json:"enforceSeedLocation,omitempty"` + Kubernetes Kubernetes `json:"kubernetes,omitempty"` + Provider Provider `json:"provider"` + Networking Networking `json:"networking"` + ControlPlane *gardener.ControlPlane `json:"controlPlane"` } type Kubernetes struct { diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index a96109e4..9221ecb8 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -372,7 +372,11 @@ func (in *RuntimeShoot) DeepCopyInto(out *RuntimeShoot) { in.Kubernetes.DeepCopyInto(&out.Kubernetes) in.Provider.DeepCopyInto(&out.Provider) in.Networking.DeepCopyInto(&out.Networking) - in.ControlPlane.DeepCopyInto(&out.ControlPlane) + if in.ControlPlane != nil { + in, out := &in.ControlPlane, &out.ControlPlane + *out = new(v1beta1.ControlPlane) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeShoot. diff --git a/hack/runtime-migrator/main.go b/hack/runtime-migrator/main.go index 53677cd3..1f783e22 100644 --- a/hack/runtime-migrator/main.go +++ b/hack/runtime-migrator/main.go @@ -274,10 +274,10 @@ func getShootList(ctx context.Context, cfg migrator.Config, gardenerNamespace st return list } -func getControlPlane(shoot v1beta1.Shoot) v1beta1.ControlPlane { +func getControlPlane(shoot v1beta1.Shoot) *v1beta1.ControlPlane { if shoot.Spec.ControlPlane != nil { if shoot.Spec.ControlPlane.HighAvailability != nil { - return v1beta1.ControlPlane{HighAvailability: &v1beta1.HighAvailability{ + return &v1beta1.ControlPlane{HighAvailability: &v1beta1.HighAvailability{ FailureTolerance: v1beta1.FailureTolerance{ Type: shoot.Spec.ControlPlane.HighAvailability.FailureTolerance.Type, }, @@ -286,7 +286,7 @@ func getControlPlane(shoot v1beta1.Shoot) v1beta1.ControlPlane { } } - return v1beta1.ControlPlane{} + return nil } func getAdministratorsList(ctx context.Context, provider kubeconfig.Provider, shootName string) []string { diff --git a/hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go b/hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go deleted file mode 100644 index 06866988..00000000 --- a/hack/shoot-comparator/pkg/shoot/etensionmatcher_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package shoot - -import ( - "github.com/gardener/gardener/pkg/apis/core/v1beta1" - . "github.com/onsi/ginkgo/v2" //nolint:revive - . "github.com/onsi/gomega" //nolint:revive -) - -var _ = Describe(":: extension matcher :: ", func() { - var empty []v1beta1.Extension - - DescribeTable( - "checking invalid args :: ", - testExtensionInvalidArgs, - Entry("when actual is nil", nil, empty), - Entry("when expected is nil", "", nil), - ) - - //disabledTrue := true - disabledFalse := false - - DescribeTable( - "checking results :: ", - testExtensionResults, - Entry( - "should match empty and zero values", - nil, - empty, - true, - ), - Entry( - "should match identical tables", - newExtensionTable(newExtension("test", &disabledFalse)), - newExtensionTable(newExtension("test", &disabledFalse)), - true, - ), - Entry( - "should detect extension missing", - newExtensionTable(newExtension("test1", &disabledFalse), newExtension("test2", &disabledFalse)), - newExtensionTable(newExtension("test", &disabledFalse)), - false, - ), - Entry( - "should detect redundant extension", - newExtensionTable(newExtension("test", &disabledFalse)), - newExtensionTable(newExtension("test1", &disabledFalse), newExtension("test2", &disabledFalse)), - false, - ), - ) -}) - -func newExtension(name string, disabled *bool) v1beta1.Extension { - return v1beta1.Extension{ - Type: name, - Disabled: disabled, - } -} - -func newExtensionTable(extensions ...v1beta1.Extension) []v1beta1.Extension { - return extensions -} - -func testExtensionInvalidArgs(actual, expected interface{}) { - matcher := NewExtensionMatcher(expected) - _, err := matcher.Match(actual) - Expect(err).To(HaveOccurred()) -} - -func testExtensionResults(actual, expected interface{}, expectedMatch bool) { - matcher := NewExtensionMatcher(expected) - actualMatch, err := matcher.Match(actual) - Expect(err).ShouldNot(HaveOccurred()) - Expect(actualMatch).Should(Equal(expectedMatch), matcher.FailureMessage(actual)) -} diff --git a/hack/shoot-comparator/pkg/shoot/extensionmatcher.go b/hack/shoot-comparator/pkg/shoot/extensionmatcher.go index 5377da41..1421964d 100644 --- a/hack/shoot-comparator/pkg/shoot/extensionmatcher.go +++ b/hack/shoot-comparator/pkg/shoot/extensionmatcher.go @@ -5,7 +5,6 @@ import ( "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/onsi/gomega" "github.com/onsi/gomega/types" - "github.com/pkg/errors" "reflect" "strings" ) @@ -23,53 +22,58 @@ func NewExtensionMatcher(i interface{}) types.GomegaMatcher { func (m *ExtensionMatcher) Match(actual interface{}) (success bool, err error) { + aExtensions, err := getExtension(actual) if err != nil { return false, err } - if actual == nil && m.toMatch != nil { - return false, errors.New("actual is nil") + eExtensions, err := getExtension(m.toMatch) + if err != nil { + return false, err } - if actual != nil && m.toMatch == nil { - return false, errors.New("expected is nil") + if len(aExtensions) != len(eExtensions) { + m.fails = append(m.fails, "Extensions count mismatch") + return false, nil } - if actual == nil && m.toMatch == nil { + if len(aExtensions) == 0 && len(eExtensions) == 0 { return true, nil } - aExtensions, err := getExtension(actual) - findExtension := func(extensions []v1beta1.Extension, extensionToFind string) v1beta1.Extension { - for _, extension := range extensions { - if extension.Type == extensionToFind { - return extension + findExtension := func(name string, extensions []v1beta1.Extension) v1beta1.Extension { + for _, e := range extensions { + if e.Type == name { + return e } } + return v1beta1.Extension{} } - eExtensions, err := getExtension(m.toMatch) - if err != nil { - return false, err - } + differenceFound := false + + for _, e := range eExtensions { + a := findExtension(e.Type, aExtensions) + if a.Type == "" { + m.fails = append(m.fails, fmt.Sprintf("Extension %s not found in both expected and actual", e.Type)) + return false, nil + } - for i, eExtension := range eExtensions { - aExtension := findExtension(aExtensions, eExtension.Type) - matcher := gomega.BeComparableTo(eExtension.Type) - ok, err := matcher.Match(aExtension.Type) + matcher := gomega.BeComparableTo(e) + + ok, err := matcher.Match(a) if err != nil { return false, err } if !ok { - msg := fmt.Sprintf("spec/Extensions[%d]: %s", i, matcher.FailureMessage(aExtension)) - m.fails = append(m.fails, msg) + differenceFound = true + m.fails = append(m.fails, matcher.FailureMessage(a)) } - } - return false, nil + return !differenceFound, nil } func (m *ExtensionMatcher) NegatedFailureMessage(_ interface{}) string { @@ -80,11 +84,7 @@ func (m *ExtensionMatcher) FailureMessage(_ interface{}) string { return strings.Join(m.fails, "\n") } -func getExtension(i interface{}) (shoot []v1beta1.Extension, err error) { - if i == nil { - return []v1beta1.Extension{}, fmt.Errorf("invalid value nil") - } - +func getExtension(i interface{}) ([]v1beta1.Extension, error) { switch v := i.(type) { case []v1beta1.Extension: return v, nil diff --git a/hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go b/hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go new file mode 100644 index 00000000..f6c7c486 --- /dev/null +++ b/hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go @@ -0,0 +1,106 @@ +package shoot + +import ( + "fmt" + "github.com/gardener/gardener/pkg/apis/core/v1beta1" + . "github.com/onsi/ginkgo/v2" //nolint:revive + . "github.com/onsi/gomega" //nolint:revive + "k8s.io/apimachinery/pkg/runtime" +) + +var _ = Describe(":: extension matcher :: ", func() { + emptyExt := make([]v1beta1.Extension, 0) + + DescribeTable( + "checking invalid args :: ", + testExtensionInvalidArgs, + Entry("when actual is not of Extension type", v1beta1.Shoot{}, emptyExt), + Entry("when expected is not of Extension type", emptyExt, v1beta1.Shoot{}), + Entry("when actual is nil", nil, emptyExt), + Entry("when expected is nil", emptyExt, nil), + ) + + dnsExtEnabled := getDNSExtension(false, true) + dnsExtDisabled := getDNSExtension(true, false) + networkingExtDisabled := getNetworkingExtension(true) + certificateExtEnabled := getCertificateExtension(false, true) + + DescribeTable( + "checking results :: ", + testExtensionResults, + Entry( + "should match empty values", + emptyExt, + emptyExt, + true, + ), + Entry( + "should match identical tables", + []v1beta1.Extension{dnsExtEnabled, networkingExtDisabled, certificateExtEnabled}, + []v1beta1.Extension{networkingExtDisabled, certificateExtEnabled, dnsExtEnabled}, + true, + ), + Entry( + "should detect extension differs", + []v1beta1.Extension{dnsExtEnabled, networkingExtDisabled, certificateExtEnabled}, + []v1beta1.Extension{dnsExtDisabled, networkingExtDisabled, certificateExtEnabled}, + false, + ), + Entry( + "should detect missing extension", + []v1beta1.Extension{dnsExtEnabled, networkingExtDisabled, certificateExtEnabled}, + []v1beta1.Extension{networkingExtDisabled, certificateExtEnabled}, + false, + ), + Entry( + "should detect redundant extension", + []v1beta1.Extension{networkingExtDisabled, certificateExtEnabled}, + []v1beta1.Extension{dnsExtEnabled, networkingExtDisabled, certificateExtEnabled}, + false, + ), + ) +}) + +func testExtensionInvalidArgs(actual, expected interface{}) { + matcher := NewExtensionMatcher(expected) + _, err := matcher.Match(actual) + Expect(err).To(HaveOccurred()) +} + +func testExtensionResults(actual, expected interface{}, expectedMatch bool) { + matcher := NewExtensionMatcher(expected) + actualMatch, err := matcher.Match(actual) + Expect(err).ShouldNot(HaveOccurred()) + Expect(actualMatch).Should(Equal(expectedMatch), matcher.FailureMessage(actual)) +} + +func getDNSExtension(disabled bool, replicationEnabled bool) v1beta1.Extension { + json := fmt.Sprintf(`{apiVersion: "service.dns.extensions.gardener.cloud/v1alpha1", kind: "DNSConfig", dnsProviderReplication: {enabled: %v}}`, replicationEnabled) + + return v1beta1.Extension{ + Type: "shoot-dns-service", + Disabled: &disabled, + ProviderConfig: &runtime.RawExtension{ + Raw: []byte(json), + }, + } +} + +func getNetworkingExtension(disabled bool) v1beta1.Extension { + return v1beta1.Extension{ + Type: "shoot-networking-service", + Disabled: &disabled, + } +} + +func getCertificateExtension(disabled bool, shootIssuersEnabled bool) v1beta1.Extension { + json := fmt.Sprintf(`{apiVersion: "service.cert.extensions.gardener.cloud/v1alpha1", kind: "CertConfig", shootIssuers: {enabled: %v}}`, shootIssuersEnabled) + + return v1beta1.Extension{ + Type: "shoot-cert-service", + Disabled: &disabled, + ProviderConfig: &runtime.RawExtension{ + Raw: []byte(json), + }, + } +} diff --git a/hack/shoot-comparator/pkg/shoot/matcher.go b/hack/shoot-comparator/pkg/shoot/matcher.go index 3b6606b6..d4d3bd71 100644 --- a/hack/shoot-comparator/pkg/shoot/matcher.go +++ b/hack/shoot-comparator/pkg/shoot/matcher.go @@ -104,7 +104,7 @@ func (m *Matcher) Match(actual interface{}) (success bool, err error) { path: "spec/DNS", }, { - GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Extensions), + GomegaMatcher: NewExtensionMatcher(eShoot.Spec.Extensions), expected: aShoot.Spec.Extensions, path: "spec/Extensions", }, diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index 2767ad87..d8195f44 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -108,7 +108,7 @@ func (c Converter) ToShoot(runtime imv1.Runtime) (gardener.Shoot, error) { Pods: &runtime.Spec.Shoot.Networking.Pods, Services: &runtime.Spec.Shoot.Networking.Services, }, - ControlPlane: &runtime.Spec.Shoot.ControlPlane, + ControlPlane: runtime.Spec.Shoot.ControlPlane, }, } From 446918efc0ad1bf380a4582f4bd2ff9859bfa5a3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Mon, 12 Aug 2024 10:59:43 +0200 Subject: [PATCH 04/10] Comment updated plus warning fixed --- hack/runtime-migrator/main.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hack/runtime-migrator/main.go b/hack/runtime-migrator/main.go index 1f783e22..ca5adcef 100644 --- a/hack/runtime-migrator/main.go +++ b/hack/runtime-migrator/main.go @@ -290,13 +290,13 @@ func getControlPlane(shoot v1beta1.Shoot) *v1beta1.ControlPlane { } func getAdministratorsList(ctx context.Context, provider kubeconfig.Provider, shootName string) []string { - var kubeconfig, err = provider.Fetch(ctx, shootName) - if kubeconfig == "" { + var clusterKubeconfig, err = provider.Fetch(ctx, shootName) + if clusterKubeconfig == "" { log.Printf("Failed to get dynamic kubeconfig for shoot %s, %s\n", shootName, err.Error()) return []string{} } - restClientConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(kubeconfig)) + restClientConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(clusterKubeconfig)) if err != nil { log.Printf("Failed to create REST client from kubeconfig - %s\n", err) return []string{} @@ -311,7 +311,8 @@ func getAdministratorsList(ctx context.Context, provider kubeconfig.Provider, sh LabelSelector: "reconciler.kyma-project.io/managed-by=reconciler,app=kyma", }) - var subjects = []string{} + subjects := make([]string, 0) + for _, clusterRoleBinding := range clusterRoleBindings.Items { for _, subject := range clusterRoleBinding.Subjects { subjects = append(subjects, subject.Name) @@ -416,7 +417,7 @@ func getAllRuntimeLabels(ctx context.Context, shoot v1beta1.Shoot, getClient mig enrichedRuntimeLabels["kyma-project.io/region"] = gardenerCluster.Labels["kyma-project.io/region"] enrichedRuntimeLabels["kyma-project.io/shoot-name"] = gardenerCluster.Labels["kyma-project.io/shoot-name"] enrichedRuntimeLabels["operator.kyma-project.io/kyma-name"] = gardenerCluster.Labels["operator.kyma-project.io/kyma-name"] - // The runtime CR should not be controlled by the KIM + // The runtime CR should be controlled by the KIM enrichedRuntimeLabels["kyma-project.io/controlled-by-provisioner"] = "false" // add custom label for the migrator enrichedRuntimeLabels[migratorLabel] = "true" From de49257890c7b02d34fa62735097c071beea6b80 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Mon, 12 Aug 2024 12:42:50 +0200 Subject: [PATCH 05/10] Extension matcher simplified --- .../pkg/shoot/extensionmatcher.go | 66 ++++++------------- 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/hack/shoot-comparator/pkg/shoot/extensionmatcher.go b/hack/shoot-comparator/pkg/shoot/extensionmatcher.go index 1421964d..fa7a1179 100644 --- a/hack/shoot-comparator/pkg/shoot/extensionmatcher.go +++ b/hack/shoot-comparator/pkg/shoot/extensionmatcher.go @@ -6,6 +6,7 @@ import ( "github.com/onsi/gomega" "github.com/onsi/gomega/types" "reflect" + "sort" "strings" ) @@ -21,7 +22,6 @@ func NewExtensionMatcher(i interface{}) types.GomegaMatcher { } func (m *ExtensionMatcher) Match(actual interface{}) (success bool, err error) { - aExtensions, err := getExtension(actual) if err != nil { return false, err @@ -32,48 +32,34 @@ func (m *ExtensionMatcher) Match(actual interface{}) (success bool, err error) { return false, err } - if len(aExtensions) != len(eExtensions) { - m.fails = append(m.fails, "Extensions count mismatch") - return false, nil - } + sort.Sort(Extensions(aExtensions)) + sort.Sort(Extensions(eExtensions)) - if len(aExtensions) == 0 && len(eExtensions) == 0 { - return true, nil - } + return gomega.BeComparableTo(eExtensions).Match(aExtensions) +} - findExtension := func(name string, extensions []v1beta1.Extension) v1beta1.Extension { - for _, e := range extensions { - if e.Type == name { - return e - } - } +func getExtension(i interface{}) ([]v1beta1.Extension, error) { + switch v := i.(type) { + case []v1beta1.Extension: + return v, nil - return v1beta1.Extension{} + default: + return []v1beta1.Extension{}, fmt.Errorf(`%w: %s`, errInvalidType, reflect.TypeOf(v)) } +} - differenceFound := false - - for _, e := range eExtensions { - a := findExtension(e.Type, aExtensions) - if a.Type == "" { - m.fails = append(m.fails, fmt.Sprintf("Extension %s not found in both expected and actual", e.Type)) - return false, nil - } - - matcher := gomega.BeComparableTo(e) +type Extensions []v1beta1.Extension - ok, err := matcher.Match(a) - if err != nil { - return false, err - } +func (e Extensions) Len() int { + return len(e) +} - if !ok { - differenceFound = true - m.fails = append(m.fails, matcher.FailureMessage(a)) - } - } +func (e Extensions) Less(i, j int) bool { + return e[i].Type < e[j].Type +} - return !differenceFound, nil +func (e Extensions) Swap(i, j int) { + e[i], e[j] = e[j], e[i] } func (m *ExtensionMatcher) NegatedFailureMessage(_ interface{}) string { @@ -83,13 +69,3 @@ func (m *ExtensionMatcher) NegatedFailureMessage(_ interface{}) string { func (m *ExtensionMatcher) FailureMessage(_ interface{}) string { return strings.Join(m.fails, "\n") } - -func getExtension(i interface{}) ([]v1beta1.Extension, error) { - switch v := i.(type) { - case []v1beta1.Extension: - return v, nil - - default: - return []v1beta1.Extension{}, fmt.Errorf(`%w: %s`, errInvalidType, reflect.TypeOf(v)) - } -} From 2186d7f10dff3992a9b16af0ffd1b60e84c5d7f8 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Mon, 12 Aug 2024 12:50:36 +0200 Subject: [PATCH 06/10] Extension Matcher test minor fix --- hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go b/hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go index f6c7c486..ed8ffb36 100644 --- a/hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go +++ b/hack/shoot-comparator/pkg/shoot/extensionmatcher_test.go @@ -47,13 +47,13 @@ var _ = Describe(":: extension matcher :: ", func() { false, ), Entry( - "should detect missing extension", + "should detect redundant extension", []v1beta1.Extension{dnsExtEnabled, networkingExtDisabled, certificateExtEnabled}, []v1beta1.Extension{networkingExtDisabled, certificateExtEnabled}, false, ), Entry( - "should detect redundant extension", + "should detect missing extension", []v1beta1.Extension{networkingExtDisabled, certificateExtEnabled}, []v1beta1.Extension{dnsExtEnabled, networkingExtDisabled, certificateExtEnabled}, false, From 98505c0c5d355c4c12cf6748e858ad6294e8cfc9 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Mon, 12 Aug 2024 14:19:42 +0200 Subject: [PATCH 07/10] Fix for unit tests plus Control Plane is optional --- api/v1/runtime_types.go | 2 +- .../bases/infrastructuremanager.kyma-project.io_runtimes.yaml | 1 - internal/gardener/shoot/converter_test.go | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/api/v1/runtime_types.go b/api/v1/runtime_types.go index 1ab41cbe..39137abf 100644 --- a/api/v1/runtime_types.go +++ b/api/v1/runtime_types.go @@ -149,7 +149,7 @@ type RuntimeShoot struct { Kubernetes Kubernetes `json:"kubernetes,omitempty"` Provider Provider `json:"provider"` Networking Networking `json:"networking"` - ControlPlane *gardener.ControlPlane `json:"controlPlane"` + ControlPlane *gardener.ControlPlane `json:"controlPlane,omitempty"` } type Kubernetes struct { diff --git a/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml b/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml index 5ca78a3b..034516ab 100644 --- a/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml +++ b/config/crd/bases/infrastructuremanager.kyma-project.io_runtimes.yaml @@ -997,7 +997,6 @@ spec: secretBindingName: type: string required: - - controlPlane - name - networking - platformRegion diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index b6ad26ee..78dbb54f 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -111,7 +111,7 @@ func fixRuntime() imv1.Runtime { Nodes: "10.250.0.0/16", Services: "100.104.0.0/13", }, - ControlPlane: gardener.ControlPlane{ + ControlPlane: &gardener.ControlPlane{ HighAvailability: &gardener.HighAvailability{ FailureTolerance: gardener.FailureTolerance{ Type: gardener.FailureToleranceTypeZone, From 3f030c5115d7845b6ab44abf227c1c3b9d762571 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Mon, 12 Aug 2024 15:04:28 +0200 Subject: [PATCH 08/10] Updated image of the comparator job --- hack/runtime-migrator/input/runtimeids_sample.json | 3 +-- hack/shoot-comparator/scripts/manifests/job.yaml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hack/runtime-migrator/input/runtimeids_sample.json b/hack/runtime-migrator/input/runtimeids_sample.json index e9a0cc0d..5425693e 100644 --- a/hack/runtime-migrator/input/runtimeids_sample.json +++ b/hack/runtime-migrator/input/runtimeids_sample.json @@ -1,4 +1,3 @@ { - c65d5c9b-b321-4481-b567-d331d769ff1c, - 61e18f65-6c82-4fdd-97dc-cf51bfbbbeb2 + 7c6b4bd3-09d3-462f-b27c-992727b62eec, } diff --git a/hack/shoot-comparator/scripts/manifests/job.yaml b/hack/shoot-comparator/scripts/manifests/job.yaml index 8b14c190..32a23102 100644 --- a/hack/shoot-comparator/scripts/manifests/job.yaml +++ b/hack/shoot-comparator/scripts/manifests/job.yaml @@ -47,7 +47,7 @@ spec: # You can specify a date when the comparison should start from. The date should be in RFC3339 format. # - --fromDate # - 2024-07-31T20:04:29Z - image: europe-docker.pkg.dev/kyma-project/dev/shoot-comparator:PR-321 + image: europe-docker.pkg.dev/kyma-project/dev/shoot-comparator:PR-329 name: compare-shoots resources: {} securityContext: From 1b09b24dbeb45aa7939ddb55d8f9a65f0c5fc8e7 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Mon, 12 Aug 2024 15:14:53 +0200 Subject: [PATCH 09/10] Unit test fix --- internal/gardener/shoot/converter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/gardener/shoot/converter_test.go b/internal/gardener/shoot/converter_test.go index 78dbb54f..d0be7181 100644 --- a/internal/gardener/shoot/converter_test.go +++ b/internal/gardener/shoot/converter_test.go @@ -30,7 +30,7 @@ func TestConverter(t *testing.T) { assert.Equal(t, runtime.Spec.Shoot.Purpose, *shoot.Spec.Purpose) assert.Equal(t, runtime.Spec.Shoot.Region, shoot.Spec.Region) assert.Equal(t, runtime.Spec.Shoot.SecretBindingName, *shoot.Spec.SecretBindingName) - assert.Equal(t, runtime.Spec.Shoot.ControlPlane, *shoot.Spec.ControlPlane) + assert.Equal(t, runtime.Spec.Shoot.ControlPlane, shoot.Spec.ControlPlane) assert.Equal(t, runtime.Spec.Shoot.Networking.Nodes, *shoot.Spec.Networking.Nodes) assert.Equal(t, runtime.Spec.Shoot.Networking.Pods, *shoot.Spec.Networking.Pods) assert.Equal(t, runtime.Spec.Shoot.Networking.Services, *shoot.Spec.Networking.Services) From f181bd58e8bc7dff811942b2bb01b9acd7a7d398 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 13 Aug 2024 16:36:12 +0200 Subject: [PATCH 10/10] Fixes in shoot creation: worker field set for gcp, enableStaticKubeconfigSet. --- hack/shoot-comparator/pkg/shoot/matcher.go | 64 +++++++++---------- internal/gardener/shoot/converter.go | 1 + .../shoot/extender/static_kubeconfig.go | 13 ++++ .../shoot/extender/static_kubeconfig_test.go | 21 ++++++ .../gardener/shoot/hyperscaler/gcp/config.go | 3 +- 5 files changed, 69 insertions(+), 33 deletions(-) create mode 100644 internal/gardener/shoot/extender/static_kubeconfig.go create mode 100644 internal/gardener/shoot/extender/static_kubeconfig_test.go diff --git a/hack/shoot-comparator/pkg/shoot/matcher.go b/hack/shoot-comparator/pkg/shoot/matcher.go index d4d3bd71..74074ea1 100644 --- a/hack/shoot-comparator/pkg/shoot/matcher.go +++ b/hack/shoot-comparator/pkg/shoot/matcher.go @@ -49,8 +49,8 @@ func getShoot(i interface{}) (shoot v1beta1.Shoot, err error) { type matcher struct { types.GomegaMatcher - path string - expected interface{} + path string + actual interface{} } func (m *Matcher) Match(actual interface{}) (success bool, err error) { @@ -71,147 +71,147 @@ func (m *Matcher) Match(actual interface{}) (success bool, err error) { // It is simpler to skip it than to make fix in the Provisioner. //{ // GomegaMatcher: gomega.BeComparableTo(eShoot.TypeMeta), - // expected: aShoot.TypeMeta, + // actual: aShoot.TypeMeta, //}, { GomegaMatcher: gomega.BeComparableTo(eShoot.Name), - expected: aShoot.Name, + actual: aShoot.Name, path: "metadata/name", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Namespace), - expected: aShoot.Namespace, + actual: aShoot.Namespace, path: "metadata/namespace", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Labels), - expected: aShoot.Labels, + actual: aShoot.Labels, path: "metadata/labels", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Addons), - expected: aShoot.Spec.Addons, + actual: aShoot.Spec.Addons, path: "spec/Addons", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.CloudProfileName), - expected: aShoot.Spec.CloudProfileName, + actual: aShoot.Spec.CloudProfileName, path: "spec/CloudProfileName", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.DNS), - expected: aShoot.Spec.DNS, + actual: aShoot.Spec.DNS, path: "spec/DNS", }, { GomegaMatcher: NewExtensionMatcher(eShoot.Spec.Extensions), - expected: aShoot.Spec.Extensions, + actual: aShoot.Spec.Extensions, path: "spec/Extensions", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Hibernation), - expected: aShoot.Spec.Hibernation, + actual: aShoot.Spec.Hibernation, path: "spec/Hibernation", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Kubernetes), - expected: aShoot.Spec.Kubernetes, + actual: aShoot.Spec.Kubernetes, path: "spec/Kubernetes", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Networking), - expected: aShoot.Spec.Networking, + actual: aShoot.Spec.Networking, path: "spec/Networking", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Maintenance), - expected: aShoot.Spec.Maintenance, + actual: aShoot.Spec.Maintenance, path: "spec/Maintenance", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Monitoring), - expected: aShoot.Spec.Monitoring, + actual: aShoot.Spec.Monitoring, path: "spec/Monitoring", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Provider), - expected: aShoot.Spec.Provider, + actual: aShoot.Spec.Provider, path: "spec/Provider", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Purpose), - expected: aShoot.Spec.Purpose, + actual: aShoot.Spec.Purpose, path: "spec/Purpose", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Region), - expected: aShoot.Spec.Region, + actual: aShoot.Spec.Region, path: "spec/Region", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SecretBindingName), - expected: aShoot.Spec.SecretBindingName, + actual: aShoot.Spec.SecretBindingName, path: "spec/SecretBindingName", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SeedName), - expected: aShoot.Spec.SeedName, + actual: aShoot.Spec.SeedName, path: "spec/SeedName", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SeedSelector), - expected: aShoot.Spec.SeedSelector, + actual: aShoot.Spec.SeedSelector, path: "spec/SeedSelector", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Resources), - expected: aShoot.Spec.Resources, + actual: aShoot.Spec.Resources, path: "spec/Resources", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.Tolerations), - expected: aShoot.Spec.Tolerations, + actual: aShoot.Spec.Tolerations, path: "spec/Tolerations", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.ExposureClassName), - expected: aShoot.Spec.ExposureClassName, + actual: aShoot.Spec.ExposureClassName, path: "spec/ExposureClassName", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SystemComponents), - expected: aShoot.Spec.SystemComponents, + actual: aShoot.Spec.SystemComponents, path: "spec/SystemComponents", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.ControlPlane), - expected: aShoot.Spec.ControlPlane, + actual: aShoot.Spec.ControlPlane, path: "spec/ControlPlane", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.SchedulerName), - expected: aShoot.Spec.SchedulerName, + actual: aShoot.Spec.SchedulerName, path: "spec/SchedulerName", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.CloudProfile), - expected: aShoot.Spec.CloudProfile, + actual: aShoot.Spec.CloudProfile, path: "spec/CloudProfile", }, { GomegaMatcher: gomega.BeComparableTo(eShoot.Spec.CredentialsBindingName), - expected: aShoot.Spec.CredentialsBindingName, + actual: aShoot.Spec.CredentialsBindingName, path: "spec/CredentialsBindingName", }, } { - ok, err := matcher.Match(matcher.expected) + ok, err := matcher.Match(matcher.actual) if err != nil { return false, err } if !ok { - msg := matcher.FailureMessage(matcher.expected) + msg := matcher.FailureMessage(matcher.actual) if matcher.path != "" { msg = fmt.Sprintf("%s: %s", matcher.path, msg) } @@ -223,7 +223,7 @@ func (m *Matcher) Match(actual interface{}) (success bool, err error) { } func (m *Matcher) NegatedFailureMessage(_ interface{}) string { - return "expected should not equal actual" + return "actual should not equal actual" } func (m *Matcher) FailureMessage(_ interface{}) string { diff --git a/internal/gardener/shoot/converter.go b/internal/gardener/shoot/converter.go index d8195f44..4ef431b3 100644 --- a/internal/gardener/shoot/converter.go +++ b/internal/gardener/shoot/converter.go @@ -78,6 +78,7 @@ func NewConverter(config ConverterConfig) Converter { extender.ExtendWithExposureClassName, extender.ExtendWithTolerations, extender.NewMaintenanceExtender(config.Kubernetes.EnableKubernetesVersionAutoUpdate, config.Kubernetes.EnableMachineImageVersionAutoUpdate), + extender.ExtendWithStaticKubeconfig, } return Converter{ diff --git a/internal/gardener/shoot/extender/static_kubeconfig.go b/internal/gardener/shoot/extender/static_kubeconfig.go new file mode 100644 index 00000000..f69f34a1 --- /dev/null +++ b/internal/gardener/shoot/extender/static_kubeconfig.go @@ -0,0 +1,13 @@ +package extender + +import ( + gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "k8s.io/utils/ptr" +) + +func ExtendWithStaticKubeconfig(_ imv1.Runtime, shoot *gardener.Shoot) error { + shoot.Spec.Kubernetes.EnableStaticTokenKubeconfig = ptr.To(false) + + return nil +} diff --git a/internal/gardener/shoot/extender/static_kubeconfig_test.go b/internal/gardener/shoot/extender/static_kubeconfig_test.go new file mode 100644 index 00000000..97795354 --- /dev/null +++ b/internal/gardener/shoot/extender/static_kubeconfig_test.go @@ -0,0 +1,21 @@ +package extender + +import ( + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) + +func TestExtendWithStaticKubeconfig(t *testing.T) { + // given + runtime := imv1.Runtime{} + shoot := fixEmptyGardenerShoot("test", "dev") + + // when + err := ExtendWithStaticKubeconfig(runtime, &shoot) + + // then + require.NoError(t, err) + assert.Equal(t, false, *shoot.Spec.Kubernetes.EnableStaticTokenKubeconfig) +} diff --git a/internal/gardener/shoot/hyperscaler/gcp/config.go b/internal/gardener/shoot/hyperscaler/gcp/config.go index 12facfc8..c4baa3fc 100644 --- a/internal/gardener/shoot/hyperscaler/gcp/config.go +++ b/internal/gardener/shoot/hyperscaler/gcp/config.go @@ -34,7 +34,8 @@ func NewInfrastructureConfig(workerCIDR string) v1alpha1.InfrastructureConfig { }, Networks: v1alpha1.NetworkConfig{ // Provisioner sets also deprecated Worker field. - // Logic for comparing shoots in integration tests must be adjusted accordingly + // We set it temporarily to make comparison easier. + Worker: workerCIDR, Workers: workerCIDR, }, }