From d9b60f5ef48efa49f9eb6e9d9687a38d3252d12a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Mon, 4 Nov 2024 11:53:11 +0100 Subject: [PATCH 1/5] zones are taken from existing shoot for patch operations --- .../runtime/fsm/runtime_fsm_patch_shoot.go | 22 +++++++-- pkg/gardener/shoot/converter.go | 7 +-- pkg/gardener/shoot/extender/provider.go | 48 +++++++++++++++++-- pkg/gardener/shoot/extender/provider_test.go | 4 +- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index a9c58064..dc8e3969 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -2,6 +2,7 @@ package fsm import ( "context" + "slices" gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" @@ -16,7 +17,8 @@ import ( func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Patch shoot state") - updatedShoot, err := convertPatch(&s.instance, m.Config.ConverterConfig) + zonesFromShoot := getZones(s.shoot.Spec.Provider.Workers) + updatedShoot, err := convertPatch(&s.instance, m.Config.ConverterConfig, zonesFromShoot) if err != nil { m.log.Error(err, "Failed to convert Runtime instance to shoot object, exiting with no retry") m.Metrics.IncRuntimeFSMStopCounter() @@ -58,12 +60,26 @@ func sFnPatchExistingShoot(ctx context.Context, m *fsm, s *systemState) (stateFn return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) } -func convertPatch(instance *imv1.Runtime, cfg config.ConverterConfig) (gardener.Shoot, error) { +func getZones(workers []gardener.Worker) []string { + var zones []string + + for _, worker := range workers { + for _, zone := range worker.Zones { + if !slices.Contains(zones, zone) { + zones = append(zones, zone) + } + } + } + + return zones +} + +func convertPatch(instance *imv1.Runtime, cfg config.ConverterConfig, zonesFromShoot []string) (gardener.Shoot, error) { if err := instance.ValidateRequiredLabels(); err != nil { return gardener.Shoot{}, err } - converter := gardener_shoot.NewConverterPatch(cfg) + converter := gardener_shoot.NewConverterPatch(cfg, zonesFromShoot) newShoot, err := converter.ToShoot(*instance) if err != nil { setObjectFields(&newShoot) diff --git a/pkg/gardener/shoot/converter.go b/pkg/gardener/shoot/converter.go index 3a6c6047..9880e3fc 100644 --- a/pkg/gardener/shoot/converter.go +++ b/pkg/gardener/shoot/converter.go @@ -44,7 +44,7 @@ func newConverter(config config.ConverterConfig, extenders ...Extend) Converter func NewConverterCreate(cfg config.ConverterConfig) Converter { baseExtenders := baseExtenders(cfg) // https://github.com/kyma-project/infrastructure-manager/pull/460 - providerExtender := extender2.NewProviderExtender( + providerExtender := extender2.NewProviderExtenderForCreateOperation( cfg.Provider.AWS.EnableIMDSv2, cfg.MachineImage.DefaultName, cfg.MachineImage.DefaultVersion, @@ -54,13 +54,14 @@ func NewConverterCreate(cfg config.ConverterConfig) Converter { return newConverter(cfg, baseExtenders...) } -func NewConverterPatch(cfg config.ConverterConfig) Converter { +func NewConverterPatch(cfg config.ConverterConfig, zonesFromShoot []string) Converter { baseExtenders := baseExtenders(cfg) // https://github.com/kyma-project/infrastructure-manager/pull/460 - providerExtender := extender2.NewProviderExtender( + providerExtender := extender2.NewProviderExtenderPatchOperation( cfg.Provider.AWS.EnableIMDSv2, cfg.MachineImage.DefaultName, cfg.MachineImage.DefaultVersion, + zonesFromShoot, ) baseExtenders = append(baseExtenders, providerExtender) diff --git a/pkg/gardener/shoot/extender/provider.go b/pkg/gardener/shoot/extender/provider.go index 23c7ee6a..f627b86c 100644 --- a/pkg/gardener/shoot/extender/provider.go +++ b/pkg/gardener/shoot/extender/provider.go @@ -14,7 +14,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) -func NewProviderExtender(enableIMDSv2 bool, defaultMachineImageName, defaultMachineImageVersion string) func(rt imv1.Runtime, shoot *gardener.Shoot) error { +func NewProviderExtenderForCreateOperation(enableIMDSv2 bool, defaultMachineImageName, defaultMachineImageVersion string) func(rt imv1.Runtime, shoot *gardener.Shoot) error { return func(rt imv1.Runtime, shoot *gardener.Shoot) error { provider := &shoot.Spec.Provider provider.Type = rt.Spec.Shoot.Provider.Type @@ -22,7 +22,41 @@ func NewProviderExtender(enableIMDSv2 bool, defaultMachineImageName, defaultMach var err error var controlPlaneConf, infraConfig *runtime.RawExtension - infraConfig, controlPlaneConf, err = getConfig(rt.Spec.Shoot) + zones := getZones(rt.Spec.Shoot.Provider.Workers) + infraConfig, controlPlaneConf, err = getConfig(rt.Spec.Shoot, zones) + if err != nil { + return err + } + + if rt.Spec.Shoot.Provider.ControlPlaneConfig != nil { + controlPlaneConf = rt.Spec.Shoot.Provider.ControlPlaneConfig + } + + if rt.Spec.Shoot.Provider.InfrastructureConfig != nil { + infraConfig = rt.Spec.Shoot.Provider.InfrastructureConfig + } + + provider.ControlPlaneConfig = controlPlaneConf + provider.InfrastructureConfig = infraConfig + + setDefaultMachineImage(provider, defaultMachineImageName, defaultMachineImageVersion) + err = setWorkerConfig(provider, provider.Type, enableIMDSv2) + setWorkerSettings(provider) + + return err + } +} + +func NewProviderExtenderPatchOperation(enableIMDSv2 bool, defaultMachineImageName, defaultMachineImageVersion string, zones []string) func(rt imv1.Runtime, shoot *gardener.Shoot) error { + return func(rt imv1.Runtime, shoot *gardener.Shoot) error { + provider := &shoot.Spec.Provider + provider.Type = rt.Spec.Shoot.Provider.Type + provider.Workers = rt.Spec.Shoot.Provider.Workers + + var err error + var controlPlaneConf, infraConfig *runtime.RawExtension + + infraConfig, controlPlaneConf, err = getConfig(rt.Spec.Shoot, zones) if err != nil { return err } @@ -49,9 +83,15 @@ func NewProviderExtender(enableIMDSv2 bool, defaultMachineImageName, defaultMach type InfrastructureProviderFunc func(workersCidr string, zones []string) ([]byte, error) type ControlPlaneProviderFunc func(zones []string) ([]byte, error) -func getConfig(runtimeShoot imv1.RuntimeShoot) (infrastructureConfig *runtime.RawExtension, controlPlaneConfig *runtime.RawExtension, err error) { +func getConfig(runtimeShoot imv1.RuntimeShoot, zones []string) (infrastructureConfig *runtime.RawExtension, controlPlaneConfig *runtime.RawExtension, err error) { getConfigForProvider := func(runtimeShoot imv1.RuntimeShoot, infrastructureConfigFunc InfrastructureProviderFunc, controlPlaneConfigFunc ControlPlaneProviderFunc) (*runtime.RawExtension, *runtime.RawExtension, error) { - zones := getZones(runtimeShoot.Provider.Workers) + + //zones := getZones(runtimeShoot.Provider.Workers) + // + //// fix for internal#6177 where gardener's admission webhook rejected shoots with zones that have different order + //if len(zonesFromShoot) > 0 { + // zones = zonesFromShoot + //} infrastructureConfigBytes, err := infrastructureConfigFunc(runtimeShoot.Networking.Nodes, zones) if err != nil { diff --git a/pkg/gardener/shoot/extender/provider_test.go b/pkg/gardener/shoot/extender/provider_test.go index 7a53d6bc..b0153501 100644 --- a/pkg/gardener/shoot/extender/provider_test.go +++ b/pkg/gardener/shoot/extender/provider_test.go @@ -67,7 +67,7 @@ func TestProviderExtender(t *testing.T) { shoot := fixEmptyGardenerShoot("cluster", "kcp-system") // when - extender := NewProviderExtender(testCase.EnableIMDSv2, testCase.DefaultMachineImageName, testCase.DefaultMachineImageVersion) + extender := NewProviderExtenderForCreateOperation(testCase.EnableIMDSv2, testCase.DefaultMachineImageName, testCase.DefaultMachineImageVersion) err := extender(testCase.Runtime, &shoot) // then @@ -92,7 +92,7 @@ func TestProviderExtender(t *testing.T) { } // when - extender := NewProviderExtender(false, "", "") + extender := NewProviderExtenderForCreateOperation(false, "", "") err := extender(runtime, &shoot) // then From e4d7224829c23e9179b65c6c4afdf5c43d158791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Mon, 4 Nov 2024 13:15:27 +0100 Subject: [PATCH 2/5] workers aligned + tests --- pkg/gardener/shoot/converter_test.go | 35 +++++++++++++++++++++++++ pkg/gardener/shoot/extender/provider.go | 19 ++++++++------ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/pkg/gardener/shoot/converter_test.go b/pkg/gardener/shoot/converter_test.go index 9df31d76..8da294b5 100644 --- a/pkg/gardener/shoot/converter_test.go +++ b/pkg/gardener/shoot/converter_test.go @@ -36,6 +36,41 @@ func TestConverter(t *testing.T) { assert.Equal(t, runtime.Spec.Shoot.Networking.Pods, *shoot.Spec.Networking.Pods) assert.Equal(t, runtime.Spec.Shoot.Networking.Services, *shoot.Spec.Networking.Services) }) + + t.Run("Create shoot from Runtime for existing shoot", func(t *testing.T) { + // given + runtime := fixRuntime() + converterConfig := fixConverterConfig() + converter := NewConverterPatch(converterConfig, fixReversedZones()) + + // when + shoot, err := converter.ToShoot(runtime) + + // then + require.NoError(t, err) + 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.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) + + expectedZonesAreInSameOrder := []string{ + "eu-central-1c", + "eu-central-1b", + "eu-central-1a", + } + assert.Equal(t, expectedZonesAreInSameOrder, shoot.Spec.Provider.Workers[0].Zones) + }) +} + +func fixReversedZones() []string { + return []string{ + "eu-central-1c", + "eu-central-1b", + "eu-central-1a", + } } func fixConverterConfig() config.ConverterConfig { diff --git a/pkg/gardener/shoot/extender/provider.go b/pkg/gardener/shoot/extender/provider.go index f627b86c..edaa2219 100644 --- a/pkg/gardener/shoot/extender/provider.go +++ b/pkg/gardener/shoot/extender/provider.go @@ -49,11 +49,11 @@ func NewProviderExtenderForCreateOperation(enableIMDSv2 bool, defaultMachineImag func NewProviderExtenderPatchOperation(enableIMDSv2 bool, defaultMachineImageName, defaultMachineImageVersion string, zones []string) func(rt imv1.Runtime, shoot *gardener.Shoot) error { return func(rt imv1.Runtime, shoot *gardener.Shoot) error { + var err error provider := &shoot.Spec.Provider provider.Type = rt.Spec.Shoot.Provider.Type provider.Workers = rt.Spec.Shoot.Provider.Workers - var err error var controlPlaneConf, infraConfig *runtime.RawExtension infraConfig, controlPlaneConf, err = getConfig(rt.Spec.Shoot, zones) @@ -76,6 +76,8 @@ func NewProviderExtenderPatchOperation(enableIMDSv2 bool, defaultMachineImageNam err = setWorkerConfig(provider, provider.Type, enableIMDSv2) setWorkerSettings(provider) + alignWithExistingShoot(provider, zones) + return err } } @@ -86,13 +88,6 @@ type ControlPlaneProviderFunc func(zones []string) ([]byte, error) func getConfig(runtimeShoot imv1.RuntimeShoot, zones []string) (infrastructureConfig *runtime.RawExtension, controlPlaneConfig *runtime.RawExtension, err error) { getConfigForProvider := func(runtimeShoot imv1.RuntimeShoot, infrastructureConfigFunc InfrastructureProviderFunc, controlPlaneConfigFunc ControlPlaneProviderFunc) (*runtime.RawExtension, *runtime.RawExtension, error) { - //zones := getZones(runtimeShoot.Provider.Workers) - // - //// fix for internal#6177 where gardener's admission webhook rejected shoots with zones that have different order - //if len(zonesFromShoot) > 0 { - // zones = zonesFromShoot - //} - infrastructureConfigBytes, err := infrastructureConfigFunc(runtimeShoot.Networking.Nodes, zones) if err != nil { return nil, nil, err @@ -201,3 +196,11 @@ func setDefaultMachineImage(provider *gardener.Provider, defaultMachineImageName worker.Machine.Image.Version = machineImageVersion } } + +// We can't predict what will be the order of zones stored by Gardener. +// Without this patch, gardener's admission webhook might reject the request if the zones order does not match. +func alignWithExistingShoot(provider *gardener.Provider, zones []string) { + for i, _ := range provider.Workers { + provider.Workers[i].Zones = zones + } +} From 2ee93972eccb43dd0a5f094f4bb4c4bc25fcf1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Mon, 4 Nov 2024 13:34:45 +0100 Subject: [PATCH 3/5] linter fix --- internal/controller/runtime/suite_test.go | 1 - pkg/gardener/shoot/extender/provider.go | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index 41d969fe..169c8174 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -39,7 +39,6 @@ import ( v12 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - //nolint:revive "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" diff --git a/pkg/gardener/shoot/extender/provider.go b/pkg/gardener/shoot/extender/provider.go index edaa2219..839edc30 100644 --- a/pkg/gardener/shoot/extender/provider.go +++ b/pkg/gardener/shoot/extender/provider.go @@ -87,7 +87,6 @@ type ControlPlaneProviderFunc func(zones []string) ([]byte, error) func getConfig(runtimeShoot imv1.RuntimeShoot, zones []string) (infrastructureConfig *runtime.RawExtension, controlPlaneConfig *runtime.RawExtension, err error) { getConfigForProvider := func(runtimeShoot imv1.RuntimeShoot, infrastructureConfigFunc InfrastructureProviderFunc, controlPlaneConfigFunc ControlPlaneProviderFunc) (*runtime.RawExtension, *runtime.RawExtension, error) { - infrastructureConfigBytes, err := infrastructureConfigFunc(runtimeShoot.Networking.Nodes, zones) if err != nil { return nil, nil, err @@ -200,7 +199,7 @@ func setDefaultMachineImage(provider *gardener.Provider, defaultMachineImageName // We can't predict what will be the order of zones stored by Gardener. // Without this patch, gardener's admission webhook might reject the request if the zones order does not match. func alignWithExistingShoot(provider *gardener.Provider, zones []string) { - for i, _ := range provider.Workers { + for i := range provider.Workers { provider.Workers[i].Zones = zones } } From 0cb47f13093ed631c6771f525524fa7b46bff152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 6 Nov 2024 16:05:32 +0100 Subject: [PATCH 4/5] fixes empty kind during patch --- .../controller/runtime/fsm/runtime_fsm_create_shoot.go | 1 - .../controller/runtime/fsm/runtime_fsm_delete_shoot.go | 1 - .../controller/runtime/fsm/runtime_fsm_patch_shoot.go | 8 -------- pkg/gardener/shoot/converter.go | 4 ++++ 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go index 018cbe1b..c609bb8e 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_shoot.go @@ -70,7 +70,6 @@ func convertCreate(instance *imv1.Runtime, cfg config.ConverterConfig) (gardener converter := gardener_shoot.NewConverterCreate(cfg) newShoot, err := converter.ToShoot(*instance) if err != nil { - setObjectFields(&newShoot) return newShoot, err } diff --git a/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go index 6f19c099..1c0a614b 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go @@ -22,7 +22,6 @@ func sFnDeleteShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl if !isGardenerCloudDelConfirmationSet(s.shoot.Annotations) { m.log.Info("patching shoot with del-confirmation") // workaround for Gardener client - setObjectFields(s.shoot) s.shoot.Annotations = addGardenerCloudDelConfirmation(s.shoot.Annotations) err := m.ShootClient.Patch(ctx, s.shoot, client.Apply, &client.PatchOptions{ diff --git a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go index dc8e3969..fc9f9c76 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_patch_shoot.go @@ -82,20 +82,12 @@ func convertPatch(instance *imv1.Runtime, cfg config.ConverterConfig, zonesFromS converter := gardener_shoot.NewConverterPatch(cfg, zonesFromShoot) newShoot, err := converter.ToShoot(*instance) if err != nil { - setObjectFields(&newShoot) return newShoot, err } return newShoot, nil } -// workaround -func setObjectFields(shoot *gardener.Shoot) { - shoot.Kind = "Shoot" - shoot.APIVersion = "core.gardener.cloud/v1beta1" - shoot.ManagedFields = nil -} - func updateStatePendingWithErrorAndStop(instance *imv1.Runtime, //nolint:unparam c imv1.RuntimeConditionType, r imv1.RuntimeConditionReason, msg string) (stateFn, *ctrl.Result, error) { diff --git a/pkg/gardener/shoot/converter.go b/pkg/gardener/shoot/converter.go index 9880e3fc..63f21c91 100644 --- a/pkg/gardener/shoot/converter.go +++ b/pkg/gardener/shoot/converter.go @@ -84,6 +84,10 @@ func (c Converter) ToShoot(runtime imv1.Runtime) (gardener.Shoot, error) { // - if any logic is needed to be implemented, either enhance existing, or create a new extender shoot := gardener.Shoot{ + TypeMeta: v1.TypeMeta{ + Kind: "Shoot", + APIVersion: "core.gardener.cloud/v1beta1", + }, ObjectMeta: v1.ObjectMeta{ Name: runtime.Spec.Shoot.Name, Namespace: fmt.Sprintf("garden-%s", c.config.Gardener.ProjectName), From 495f94445967d9d440ae806abeceeb9dc4a343de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Drzewiecki?= Date: Wed, 6 Nov 2024 16:11:14 +0100 Subject: [PATCH 5/5] tests assure that kind and apiVersion are set --- pkg/gardener/shoot/converter_test.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/gardener/shoot/converter_test.go b/pkg/gardener/shoot/converter_test.go index 8da294b5..d66da4ba 100644 --- a/pkg/gardener/shoot/converter_test.go +++ b/pkg/gardener/shoot/converter_test.go @@ -28,13 +28,7 @@ func TestConverter(t *testing.T) { // then require.NoError(t, err) - 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.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) + assertShootFields(t, runtime, shoot) }) t.Run("Create shoot from Runtime for existing shoot", func(t *testing.T) { @@ -48,13 +42,7 @@ func TestConverter(t *testing.T) { // then require.NoError(t, err) - 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.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) + assertShootFields(t, runtime, shoot) expectedZonesAreInSameOrder := []string{ "eu-central-1c", @@ -65,6 +53,18 @@ func TestConverter(t *testing.T) { }) } +func assertShootFields(t *testing.T, runtime imv1.Runtime, shoot gardener.Shoot) { + 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.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) + assert.Equal(t, "Shoot", shoot.TypeMeta.Kind) + assert.Equal(t, "core.gardener.cloud/v1beta1", shoot.TypeMeta.APIVersion) +} + func fixReversedZones() []string { return []string{ "eu-central-1c",