From d2a4e3bdefa4807efbcedd4dc0e840c011ba73a1 Mon Sep 17 00:00:00 2001 From: Danil-Grigorev Date: Fri, 17 Jan 2025 17:46:28 +0100 Subject: [PATCH] e2e fixes Signed-off-by: Danil-Grigorev --- test/e2e/cluster_upgrade_runtimesdk.go | 22 ++-- test/e2e/clusterclass_changes.go | 154 ++++++++++++------------- test/e2e/clusterclass_changes_test.go | 2 +- test/e2e/quick_start.go | 22 ++-- test/e2e/quick_start_test.go | 1 - 5 files changed, 101 insertions(+), 100 deletions(-) diff --git a/test/e2e/cluster_upgrade_runtimesdk.go b/test/e2e/cluster_upgrade_runtimesdk.go index 1fb7bac72fdc..ef74de26e300 100644 --- a/test/e2e/cluster_upgrade_runtimesdk.go +++ b/test/e2e/cluster_upgrade_runtimesdk.go @@ -96,7 +96,7 @@ type ClusterUpgradeWithRuntimeSDKSpecInput struct { // ExtensionServiceName is the name of the service to configure in the test-namespace scoped ExtensionConfig. ExtensionServiceName string - // DeployClusterClassInSeparateNamespace is set if a second namespace is required for the ClusterClass deployment + // DeployClusterClassInSeparateNamespace defines if the ClusterClass should be deployed in a separate namespace. DeployClusterClassInSeparateNamespace bool } @@ -151,8 +151,10 @@ func ClusterUpgradeWithRuntimeSDKSpec(ctx context.Context, inputGetter func() Cl // Set up a Namespace where to host objects for this spec and create a watcher for the Namespace events. namespace, cancelWatches = framework.SetupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, input.PostNamespaceCreated) - clusterClassNamespace = framework.CreateNamespace(ctx, framework.CreateNamespaceInput{Creator: input.BootstrapClusterProxy.GetClient(), Name: fmt.Sprintf("%s-%s", specName, util.RandomString(6))}, "40s", "10s") - Expect(clusterClassNamespace).ToNot(BeNil(), "Failed to create namespace") + if input.DeployClusterClassInSeparateNamespace { + clusterClassNamespace = framework.CreateNamespace(ctx, framework.CreateNamespaceInput{Creator: input.BootstrapClusterProxy.GetClient(), Name: fmt.Sprintf("%s-%s", specName, util.RandomString(6))}, "40s", "10s") + Expect(clusterClassNamespace).ToNot(BeNil(), "Failed to create namespace") + } clusterName = fmt.Sprintf("%s-%s", specName, util.RandomString(6)) clusterResources = new(clusterctl.ApplyClusterTemplateAndWaitResult) }) @@ -166,8 +168,12 @@ func ClusterUpgradeWithRuntimeSDKSpec(ctx context.Context, inputGetter func() Cl By("Deploy Test Extension ExtensionConfig") + namespaces := []string{namespace.Name} + if input.DeployClusterClassInSeparateNamespace { + namespaces = append(namespaces, clusterClassNamespace.Name) + } Expect(input.BootstrapClusterProxy.GetClient().Create(ctx, - extensionConfig(specName, input.ExtensionServiceNamespace, input.ExtensionServiceName, namespace.Name, clusterClassNamespace.Name))). + extensionConfig(specName, input.ExtensionServiceNamespace, input.ExtensionServiceName, namespaces...))). To(Succeed(), "Failed to create the extension config") By("Creating a workload cluster; creation waits for BeforeClusterCreateHook to gate the operation") @@ -334,14 +340,8 @@ func ClusterUpgradeWithRuntimeSDKSpec(ctx context.Context, inputGetter func() Cl Name: namespace.Name, }) - Byf("Deleting namespace used for hosting the %q test spec", specName) - framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{ - Deleter: input.BootstrapClusterProxy.GetClient(), - Name: clusterClassNamespace.Name, - }) - if input.DeployClusterClassInSeparateNamespace { - Byf("Deleting namespace used for optionally hosting the %q infrastructure spec", specName) + Byf("Deleting namespace used for hosting the %q test spec ClusterClas", specName) framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{ Deleter: input.BootstrapClusterProxy.GetClient(), Name: clusterClassNamespace.Name, diff --git a/test/e2e/clusterclass_changes.go b/test/e2e/clusterclass_changes.go index 012293f5db6e..d8c60b21d08e 100644 --- a/test/e2e/clusterclass_changes.go +++ b/test/e2e/clusterclass_changes.go @@ -138,7 +138,7 @@ func ClusterClassChangesSpec(ctx context.Context, inputGetter func() ClusterClas specName = "clusterclass-changes" input ClusterClassChangesSpecInput namespace, clusterClassNamespace *corev1.Namespace - cancelWatches, cancelCCWatches context.CancelFunc + cancelWatches context.CancelFunc clusterResources *clusterctl.ApplyClusterTemplateAndWaitResult ) @@ -155,7 +155,7 @@ func ClusterClassChangesSpec(ctx context.Context, inputGetter func() ClusterClas // Set up a Namespace where to host objects for this spec and create a watcher for the namespace events. namespace, cancelWatches = framework.SetupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, input.PostNamespaceCreated) - clusterClassNamespace, cancelCCWatches = framework.SetupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, nil) + clusterClassNamespace = framework.CreateNamespace(ctx, framework.CreateNamespaceInput{Creator: input.BootstrapClusterProxy.GetClient(), Name: fmt.Sprintf("%s-clusterclass", namespace.Name)}, "40s", "10s") clusterResources = new(clusterctl.ApplyClusterTemplateAndWaitResult) }) @@ -185,10 +185,11 @@ func ClusterClassChangesSpec(ctx context.Context, inputGetter func() ClusterClas WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"), }, clusterResources) + originalClusterClassState := clusterResources.ClusterClass.DeepCopy() + By("Rebasing the Cluster to a ClusterClass with a modified label for MachineDeployments and wait for changes to be applied to the MachineDeployment objects") rebasedClusterClass := rebaseClusterClassAndWait(ctx, rebaseClusterClassAndWaitInput{ ClusterProxy: input.BootstrapClusterProxy, - ClusterClassNamespace: clusterClassNamespace.Name, ClusterClass: clusterResources.ClusterClass, Cluster: clusterResources.Cluster, WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"), @@ -223,6 +224,46 @@ func ClusterClassChangesSpec(ctx context.Context, inputGetter func() ClusterClas WaitForMachinePools: input.E2EConfig.GetIntervals(specName, "wait-machine-pool-nodes"), }) + By("Rebasing the Cluster to a copy of original ClusterClass in a different namespace") + rebasedClusterClass = rebaseClusterClassAndWait(ctx, rebaseClusterClassAndWaitInput{ + ClusterProxy: input.BootstrapClusterProxy, + ClusterClassNamespace: clusterClassNamespace.Name, + ClusterClass: originalClusterClassState, + Cluster: clusterResources.Cluster, + WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"), + }) + + By("Performing modification on a the referenced ClusterClass tempalates in a different namespace") + + By("Modifying the control plane configuration in second ClusterClass and wait for changes to be applied to the control plane object") + modifyControlPlaneViaClusterClassAndWait(ctx, modifyClusterClassControlPlaneAndWaitInput{ + ClusterProxy: input.BootstrapClusterProxy, + ClusterClass: rebasedClusterClass, + Cluster: clusterResources.Cluster, + ModifyControlPlaneFields: input.ModifyControlPlaneFields, + WaitForControlPlane: input.E2EConfig.GetIntervals(specName, "wait-control-plane"), + }) + + By("Modifying the MachineDeployment configuration in ClusterClass and wait for changes to be applied to the MachineDeployment objects") + modifyMachineDeploymentViaClusterClassAndWait(ctx, modifyMachineDeploymentViaClusterClassAndWaitInput{ + ClusterProxy: input.BootstrapClusterProxy, + ClusterClass: rebasedClusterClass, + Cluster: clusterResources.Cluster, + ModifyBootstrapConfigTemplateFields: input.ModifyMachineDeploymentBootstrapConfigTemplateFields, + ModifyInfrastructureMachineTemplateFields: input.ModifyMachineDeploymentInfrastructureMachineTemplateFields, + WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"), + }) + + By("Modifying the MachinePool configuration in ClusterClass and wait for changes to be applied to the MachinePool objects") + modifyMachinePoolViaClusterClassAndWait(ctx, modifyMachinePoolViaClusterClassAndWaitInput{ + ClusterProxy: input.BootstrapClusterProxy, + ClusterClass: rebasedClusterClass, + Cluster: clusterResources.Cluster, + ModifyBootstrapConfigTemplateFields: input.ModifyMachinePoolBootstrapConfigTemplateFields, + ModifyInfrastructureMachinePoolTemplateFields: input.ModifyMachinePoolInfrastructureMachinePoolTemplateFields, + WaitForMachinePools: input.E2EConfig.GetIntervals(specName, "wait-machine-pool-nodes"), + }) + By("Deleting a MachineDeploymentTopology in the Cluster Topology and wait for associated MachineDeployment to be deleted") deleteMachineDeploymentTopologyAndWait(ctx, deleteMachineDeploymentTopologyAndWaitInput{ ClusterProxy: input.BootstrapClusterProxy, @@ -236,13 +277,11 @@ func ClusterClassChangesSpec(ctx context.Context, inputGetter func() ClusterClas // Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself. framework.DumpSpecResourcesAndCleanup(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, namespace, cancelWatches, clusterResources.Cluster, input.E2EConfig.GetIntervals, input.SkipCleanup) - Byf("Deleting namespace used for hosting the %q test clusterClass", specName) + Byf("Deleting namespace used for hosting the %q test spec ClusterClass", specName) framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{ Deleter: input.BootstrapClusterProxy.GetClient(), Name: clusterClassNamespace.Name, }) - - cancelCCWatches() }) } @@ -685,7 +724,6 @@ func rebaseClusterClassAndWait(ctx context.Context, input rebaseClusterClassAndW Expect(input.ClusterProxy).ToNot(BeNil(), "Invalid argument. input.ClusterProxy can't be nil when calling RebaseClusterClassAndWait") Expect(input.ClusterClass).ToNot(BeNil(), "Invalid argument. input.ClusterClass can't be nil when calling RebaseClusterClassAndWait") Expect(input.Cluster).ToNot(BeNil(), "Invalid argument. input.Cluster can't be nil when calling RebaseClusterClassAndWait") - Expect(input.ClusterClassNamespace).ToNot(BeEmpty(), "Invalid argument. input.ClusterClassNamespace can't be empty when calling RebaseClusterClassAndWait") mgmtClient := input.ClusterProxy.GetClient() @@ -698,8 +736,11 @@ func rebaseClusterClassAndWait(ctx context.Context, input rebaseClusterClassAndW newClusterClass := sourceClusterClass.DeepCopy() newClusterClassName := fmt.Sprintf("%s-%s", input.ClusterClass.Name, util.RandomString(6)) newClusterClass.SetName(newClusterClassName) - newClusterClass.SetNamespace(input.ClusterClassNamespace) + if input.ClusterClassNamespace != "" { + newClusterClass.SetNamespace(input.ClusterClassNamespace) + } newClusterClass.SetResourceVersion("") + for i, mdClass := range newClusterClass.Spec.Workers.MachineDeployments { if mdClass.Template.Metadata.Labels == nil { mdClass.Template.Metadata.Labels = map[string]string{} @@ -710,82 +751,20 @@ func rebaseClusterClassAndWait(ctx context.Context, input rebaseClusterClassAndW // Copy ClusterClass templates to the new namespace for i, mdClass := range newClusterClass.Spec.Workers.MachineDeployments { - if mdClass.Template.Infrastructure.Ref != nil { - workerInfraTemplate, err := external.Get(ctx, mgmtClient, mdClass.Template.Infrastructure.Ref) - Expect(err).ToNot(HaveOccurred()) - workerInfraTemplate.SetNamespace(input.ClusterClassNamespace) - workerInfraTemplate.SetResourceVersion("") - workerInfraTemplate.SetOwnerReferences(nil) - Expect(mgmtClient.Create(ctx, workerInfraTemplate)).To(Succeed()) - mdClass.Template.Infrastructure.Ref = external.GetObjectReference(workerInfraTemplate) - } - - if mdClass.Template.Bootstrap.Ref != nil { - workerBootstrapTemplate, err := external.Get(ctx, mgmtClient, mdClass.Template.Bootstrap.Ref) - Expect(err).ToNot(HaveOccurred()) - workerBootstrapTemplate.SetNamespace(input.ClusterClassNamespace) - workerBootstrapTemplate.SetResourceVersion("") - workerBootstrapTemplate.SetOwnerReferences(nil) - Expect(mgmtClient.Create(ctx, workerBootstrapTemplate)).To(Succeed()) - mdClass.Template.Bootstrap.Ref = external.GetObjectReference(workerBootstrapTemplate) - } - + cloneRef(ctx, mgmtClient, mdClass.Template.Infrastructure.Ref, input.ClusterClassNamespace) + cloneRef(ctx, mgmtClient, mdClass.Template.Bootstrap.Ref, input.ClusterClassNamespace) newClusterClass.Spec.Workers.MachineDeployments[i] = mdClass } for i, mpClass := range newClusterClass.Spec.Workers.MachinePools { - if mpClass.Template.Infrastructure.Ref != nil { - workerInfraTemplate, err := external.Get(ctx, mgmtClient, mpClass.Template.Infrastructure.Ref) - Expect(err).ToNot(HaveOccurred()) - workerInfraTemplate.SetNamespace(input.ClusterClassNamespace) - workerInfraTemplate.SetResourceVersion("") - workerInfraTemplate.SetOwnerReferences(nil) - Expect(mgmtClient.Create(ctx, workerInfraTemplate)).To(Succeed()) - mpClass.Template.Infrastructure.Ref = external.GetObjectReference(workerInfraTemplate) - } - - if mpClass.Template.Bootstrap.Ref != nil { - workerBootstrapTemplate, err := external.Get(ctx, mgmtClient, mpClass.Template.Bootstrap.Ref) - Expect(err).ToNot(HaveOccurred()) - workerBootstrapTemplate.SetNamespace(input.ClusterClassNamespace) - workerBootstrapTemplate.SetResourceVersion("") - workerBootstrapTemplate.SetOwnerReferences(nil) - Expect(mgmtClient.Create(ctx, workerBootstrapTemplate)).To(Succeed()) - mpClass.Template.Bootstrap.Ref = external.GetObjectReference(workerBootstrapTemplate) - } - + cloneRef(ctx, mgmtClient, mpClass.Template.Infrastructure.Ref, input.ClusterClassNamespace) + cloneRef(ctx, mgmtClient, mpClass.Template.Bootstrap.Ref, input.ClusterClassNamespace) newClusterClass.Spec.Workers.MachinePools[i] = mpClass } - if newClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref != nil { - machineInfraTemplate, err := external.Get(ctx, mgmtClient, newClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref) - Expect(err).ToNot(HaveOccurred()) - machineInfraTemplate.SetNamespace(input.ClusterClassNamespace) - machineInfraTemplate.SetResourceVersion("") - machineInfraTemplate.SetOwnerReferences(nil) - Expect(mgmtClient.Create(ctx, machineInfraTemplate)).To(Succeed()) - newClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref = external.GetObjectReference(machineInfraTemplate) - } - - if newClusterClass.Spec.ControlPlane.Ref != nil { - controlPlaneTemplate, err := external.Get(ctx, mgmtClient, newClusterClass.Spec.ControlPlane.Ref) - Expect(err).ToNot(HaveOccurred()) - controlPlaneTemplate.SetNamespace(input.ClusterClassNamespace) - controlPlaneTemplate.SetResourceVersion("") - controlPlaneTemplate.SetOwnerReferences(nil) - Expect(mgmtClient.Create(ctx, controlPlaneTemplate)).To(Succeed()) - newClusterClass.Spec.ControlPlane.Ref = external.GetObjectReference(controlPlaneTemplate) - } - - if newClusterClass.Spec.Infrastructure.Ref != nil { - infrastructureTemplate, err := external.Get(ctx, mgmtClient, newClusterClass.Spec.Infrastructure.Ref) - Expect(err).ToNot(HaveOccurred()) - infrastructureTemplate.SetNamespace(input.ClusterClassNamespace) - infrastructureTemplate.SetResourceVersion("") - infrastructureTemplate.SetOwnerReferences(nil) - Expect(mgmtClient.Create(ctx, infrastructureTemplate)).To(Succeed()) - newClusterClass.Spec.Infrastructure.Ref = external.GetObjectReference(infrastructureTemplate) - } + cloneRef(ctx, mgmtClient, newClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref, input.ClusterClassNamespace) + cloneRef(ctx, mgmtClient, newClusterClass.Spec.ControlPlane.Ref, input.ClusterClassNamespace) + cloneRef(ctx, mgmtClient, newClusterClass.Spec.Infrastructure.Ref, input.ClusterClassNamespace) Expect(mgmtClient.Create(ctx, newClusterClass)).To(Succeed()) @@ -846,6 +825,27 @@ func rebaseClusterClassAndWait(ctx context.Context, input rebaseClusterClassAndW return newClusterClass } +// cloneRef performs required modifications to avoid conflict, and create a copy of the referenced object, updating the ref in-place. +func cloneRef(ctx context.Context, cl client.Client, ref *corev1.ObjectReference, namespace string) { + if ref == nil { + return + } + + template, err := external.Get(ctx, cl, ref) + Expect(err).ToNot(HaveOccurred()) + if namespace != "" { + template.SetNamespace(namespace) + } else { + template.SetGenerateName(template.GetName()) + template.SetName("") + } + template.SetResourceVersion("") + template.SetOwnerReferences(nil) + Expect(cl.Create(ctx, template)).To(Succeed()) + + *ref = *external.GetObjectReference(template) +} + // deleteMachineDeploymentTopologyAndWaitInput is the input type for deleteMachineDeploymentTopologyAndWaitInput. type deleteMachineDeploymentTopologyAndWaitInput struct { ClusterProxy framework.ClusterProxy diff --git a/test/e2e/clusterclass_changes_test.go b/test/e2e/clusterclass_changes_test.go index 76b2cb846a6b..45831f06b65a 100644 --- a/test/e2e/clusterclass_changes_test.go +++ b/test/e2e/clusterclass_changes_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/utils/ptr" ) -var _ = Describe("When testing quick-start ClusterClass changes [ClusterClass] [PR-Blocking]", func() { +var _ = Describe("When testing ClusterClass changes [ClusterClass] [PR-Blocking]", func() { ClusterClassChangesSpec(ctx, func() ClusterClassChangesSpecInput { return ClusterClassChangesSpecInput{ E2EConfig: e2eConfig, diff --git a/test/e2e/quick_start.go b/test/e2e/quick_start.go index 3f30b7c64ec8..9b3f5f034ea9 100644 --- a/test/e2e/quick_start.go +++ b/test/e2e/quick_start.go @@ -44,7 +44,7 @@ type QuickStartSpecInput struct { // If not set, a random one will be generated. ClusterName *string - // DeployClusterClassInSeparateNamespace is set if a second namespace is required for the ClusterClass deployment + // DeployClusterClassInSeparateNamespace defines if the ClusterClass should be deployed in a separate namespace. DeployClusterClassInSeparateNamespace bool // InfrastructureProvider allows to specify the infrastructure provider to be used when looking for @@ -105,8 +105,10 @@ func QuickStartSpec(ctx context.Context, inputGetter func() QuickStartSpecInput) // Setup a Namespace where to host objects for this spec and create a watcher for the namespace events. namespace, cancelWatches = framework.SetupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, input.PostNamespaceCreated) - clusterClassNamespace = framework.CreateNamespace(ctx, framework.CreateNamespaceInput{Creator: input.BootstrapClusterProxy.GetClient(), Name: fmt.Sprintf("%s-%s", specName, util.RandomString(6))}, "40s", "10s") - Expect(clusterClassNamespace).ToNot(BeNil(), "Failed to create namespace") + if input.DeployClusterClassInSeparateNamespace { + clusterClassNamespace = framework.CreateNamespace(ctx, framework.CreateNamespaceInput{Creator: input.BootstrapClusterProxy.GetClient(), Name: fmt.Sprintf("%s-%s", specName, util.RandomString(6))}, "40s", "10s") + Expect(clusterClassNamespace).ToNot(BeNil(), "Failed to create namespace") + } clusterResources = new(clusterctl.ApplyClusterTemplateAndWaitResult) }) @@ -142,9 +144,7 @@ func QuickStartSpec(ctx context.Context, inputGetter func() QuickStartSpecInput) variables := map[string]string{} if input.DeployClusterClassInSeparateNamespace { variables["CLUSTER_CLASS_NAMESPACE"] = clusterClassNamespace.Name - By("Creating a cluster referencing a clusterClass from another namespace") - } else { - By("Creating a cluster referencing a clusterClass") + By("Creating a cluster referencing a ClusterClass from another namespace") } clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{ @@ -179,9 +179,11 @@ func QuickStartSpec(ctx context.Context, inputGetter func() QuickStartSpecInput) AfterEach(func() { // Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself. framework.DumpSpecResourcesAndCleanup(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, namespace, cancelWatches, clusterResources.Cluster, input.E2EConfig.GetIntervals, input.SkipCleanup) - framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{ - Deleter: input.BootstrapClusterProxy.GetClient(), - Name: clusterClassNamespace.Name, - }) + if input.DeployClusterClassInSeparateNamespace { + framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{ + Deleter: input.BootstrapClusterProxy.GetClient(), + Name: clusterClassNamespace.Name, + }) + } }) } diff --git a/test/e2e/quick_start_test.go b/test/e2e/quick_start_test.go index b6b566c247c2..03230acde215 100644 --- a/test/e2e/quick_start_test.go +++ b/test/e2e/quick_start_test.go @@ -120,7 +120,6 @@ var _ = Describe("When following the Cluster API quick-start with ClusterClass [ By("Checking that resourceVersions are stable") framework.ValidateResourceVersionStable(ctx, proxy, namespace, clusterctlcluster.FilterClusterObjectsWithNameFilter(clusterName)) }, - DeployClusterClassInSeparateNamespace: true, } }) })