@@ -27,8 +27,11 @@ import (
2727	. "github.com/onsi/ginkgo/v2" 
2828	. "github.com/onsi/gomega" 
2929	corev1 "k8s.io/api/core/v1" 
30+ 	"k8s.io/apimachinery/pkg/api/errors" 
31+ 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 
3032	"k8s.io/utils/ptr" 
3133
34+ 	"sigs.k8s.io/cluster-api/test/e2e/internal/log" 
3235	"sigs.k8s.io/cluster-api/test/framework" 
3336	"sigs.k8s.io/cluster-api/test/framework/clusterctl" 
3437	"sigs.k8s.io/cluster-api/util" 
@@ -111,156 +114,183 @@ func QuickStartSpec(ctx context.Context, inputGetter func() QuickStartSpecInput)
111114		clusterResources       * clusterctl.ApplyClusterTemplateAndWaitResult 
112115	)
113116
114- 	BeforeEach (func () {
115- 		Expect (ctx ).NotTo (BeNil (), "ctx is required for %s spec" , specName )
116- 		input  =  inputGetter ()
117- 		Expect (input .E2EConfig ).ToNot (BeNil (), "Invalid argument. input.E2EConfig can't be nil when calling %s spec" , specName )
118- 		Expect (input .ClusterctlConfigPath ).To (BeAnExistingFile (), "Invalid argument. input.ClusterctlConfigPath must be an existing file when calling %s spec" , specName )
119- 		Expect (input .BootstrapClusterProxy ).ToNot (BeNil (), "Invalid argument. input.BootstrapClusterProxy can't be nil when calling %s spec" , specName )
120- 		Expect (os .MkdirAll (input .ArtifactFolder , 0750 )).To (Succeed (), "Invalid argument. input.ArtifactFolder can't be created for %s spec" , specName )
117+ 	for  i  :=  0 ; i  <  15 ; i ++  {
121118
122- 		Expect (input .E2EConfig .Variables ).To (HaveKey (KubernetesVersion ))
119+ 		BeforeEach (func () {
120+ 			Expect (ctx ).NotTo (BeNil (), "ctx is required for %s spec" , specName )
121+ 			input  =  inputGetter ()
122+ 			Expect (input .E2EConfig ).ToNot (BeNil (), "Invalid argument. input.E2EConfig can't be nil when calling %s spec" , specName )
123+ 			Expect (input .ClusterctlConfigPath ).To (BeAnExistingFile (), "Invalid argument. input.ClusterctlConfigPath must be an existing file when calling %s spec" , specName )
124+ 			Expect (input .BootstrapClusterProxy ).ToNot (BeNil (), "Invalid argument. input.BootstrapClusterProxy can't be nil when calling %s spec" , specName )
125+ 			Expect (os .MkdirAll (input .ArtifactFolder , 0750 )).To (Succeed (), "Invalid argument. input.ArtifactFolder can't be created for %s spec" , specName )
123126
124- 		if  input .ExtensionServiceNamespace  !=  ""  &&  input .ExtensionServiceName  !=  ""  {
125- 			if  input .ExtensionConfigName  ==  ""  {
126- 				input .ExtensionConfigName  =  specName 
127+ 			Expect (input .E2EConfig .Variables ).To (HaveKey (KubernetesVersion ))
128+ 
129+ 			if  input .ExtensionServiceNamespace  !=  ""  &&  input .ExtensionServiceName  !=  ""  {
130+ 				if  input .ExtensionConfigName  ==  ""  {
131+ 					input .ExtensionConfigName  =  specName 
132+ 				}
127133			}
128- 		}
129134
130- 		// Setup a Namespace where to host objects for this spec and create a watcher for the namespace events. 
131- 		namespace , cancelWatches  =  framework .SetupSpecNamespace (ctx , specName , input .BootstrapClusterProxy , input .ArtifactFolder , input .PostNamespaceCreated )
135+ 			 // Setup a Namespace where to host objects for this spec and create a watcher for the namespace events. 
136+ 			 namespace , cancelWatches  =  framework .SetupSpecNamespace (ctx , specName , input .BootstrapClusterProxy , input .ArtifactFolder , input .PostNamespaceCreated )
132137
133- 		if  input .DeployClusterClassInSeparateNamespace  {
134- 			clusterClassNamespace  =  framework .CreateNamespace (ctx , framework.CreateNamespaceInput {Creator : input .BootstrapClusterProxy .GetClient (), Name : fmt .Sprintf ("%s-clusterclass" , namespace .Name )}, "40s" , "10s" )
135- 			Expect (clusterClassNamespace ).ToNot (BeNil (), "Failed to create namespace" )
136- 		}
138+ 			 if  input .DeployClusterClassInSeparateNamespace  {
139+ 				 clusterClassNamespace  =  framework .CreateNamespace (ctx , framework.CreateNamespaceInput {Creator : input .BootstrapClusterProxy .GetClient (), Name : fmt .Sprintf ("%s-clusterclass" , namespace .Name )}, "40s" , "10s" )
140+ 				 Expect (clusterClassNamespace ).ToNot (BeNil (), "Failed to create namespace" )
141+ 			 }
137142
138- 		clusterResources  =  new (clusterctl.ApplyClusterTemplateAndWaitResult )
139- 	})
143+ 			 clusterResources  =  new (clusterctl.ApplyClusterTemplateAndWaitResult )
144+ 		 })
140145
141- 	It ("Should create a workload cluster" , func () {
142- 		By ("Creating a workload cluster" )
146+ 		 It ("Should create a workload cluster" , func () {
147+ 			 By ("Creating a workload cluster" )
143148
144- 		infrastructureProvider  :=  clusterctl .DefaultInfrastructureProvider 
145- 		if  input .InfrastructureProvider  !=  nil  {
146- 			infrastructureProvider  =  * input .InfrastructureProvider 
147- 		}
149+ 			 infrastructureProvider  :=  clusterctl .DefaultInfrastructureProvider 
150+ 			 if  input .InfrastructureProvider  !=  nil  {
151+ 				 infrastructureProvider  =  * input .InfrastructureProvider 
152+ 			 }
148153
149- 		flavor  :=  clusterctl .DefaultFlavor 
150- 		if  input .Flavor  !=  nil  {
151- 			flavor  =  * input .Flavor 
152- 		}
154+ 			 flavor  :=  clusterctl .DefaultFlavor 
155+ 			 if  input .Flavor  !=  nil  {
156+ 				 flavor  =  * input .Flavor 
157+ 			 }
153158
154- 		controlPlaneMachineCount  :=  ptr.To [int64 ](1 )
155- 		if  input .ControlPlaneMachineCount  !=  nil  {
156- 			controlPlaneMachineCount  =  input .ControlPlaneMachineCount 
157- 		}
159+ 			 controlPlaneMachineCount  :=  ptr.To [int64 ](1 )
160+ 			 if  input .ControlPlaneMachineCount  !=  nil  {
161+ 				 controlPlaneMachineCount  =  input .ControlPlaneMachineCount 
162+ 			 }
158163
159- 		workerMachineCount  :=  ptr.To [int64 ](1 )
160- 		if  input .WorkerMachineCount  !=  nil  {
161- 			workerMachineCount  =  input .WorkerMachineCount 
162- 		}
164+ 			 workerMachineCount  :=  ptr.To [int64 ](1 )
165+ 			 if  input .WorkerMachineCount  !=  nil  {
166+ 				 workerMachineCount  =  input .WorkerMachineCount 
167+ 			 }
163168
164- 		clusterName  :=  fmt .Sprintf ("%s-%s" , specName , util .RandomString (6 ))
165- 		if  input .ClusterName  !=  nil  {
166- 			clusterName  =  * input .ClusterName 
167- 		}
169+ 			clusterName  :=  fmt .Sprintf ("%s-%s" , specName , util .RandomString (6 ))
170+ 			if  input .ClusterName  !=  nil  {
171+ 				clusterName  =  * input .ClusterName 
172+ 			}
173+ 
174+ 			if  input .ExtensionServiceNamespace  !=  ""  &&  input .ExtensionServiceName  !=  ""  {
175+ 				// NOTE: test extension is already deployed in the management cluster. If for any reason in future we want 
176+ 				// to make this test more self-contained this test should be modified in order to create an additional 
177+ 				// management cluster; also the E2E test configuration should be modified introducing something like 
178+ 				// optional:true allowing to define which providers should not be installed by default in 
179+ 				// a management cluster. 
180+ 				By ("Deploy Test Extension ExtensionConfig" )
181+ 
182+ 				// In this test we are defaulting all handlers to non-blocking because we don't expect the handlers to block the 
183+ 				// cluster lifecycle by default. Setting defaultAllHandlersToBlocking to false enforces that the test-extension 
184+ 				// automatically creates the ConfigMap with non-blocking preloaded responses. 
185+ 				defaultAllHandlersToBlocking  :=  false 
186+ 				// select on the current namespace 
187+ 				// This is necessary so in CI this test doesn't influence other tests by enabling lifecycle hooks 
188+ 				// in other test namespaces. 
189+ 				namespaces  :=  []string {namespace .Name }
190+ 				if  input .DeployClusterClassInSeparateNamespace  {
191+ 					// Add the ClusterClass namespace, if the ClusterClass is deployed in a separate namespace. 
192+ 					namespaces  =  append (namespaces , clusterClassNamespace .Name )
193+ 				}
194+ 				extensionConfig  :=  extensionConfig (input .ExtensionConfigName , input .ExtensionServiceNamespace , input .ExtensionServiceName , defaultAllHandlersToBlocking , namespaces ... )
195+ 				Expect (input .BootstrapClusterProxy .GetClient ().Create (ctx ,
196+ 					extensionConfig )).
197+ 					To (Succeed (), "Failed to create the ExtensionConfig" )
198+ 			}
199+ 
200+ 			variables  :=  map [string ]string {
201+ 				// This is used to template the name of the ExtensionConfig into the ClusterClass. 
202+ 				"EXTENSION_CONFIG_NAME" : input .ExtensionConfigName ,
203+ 			}
204+ 			maps .Copy (variables , input .ClusterctlVariables )
168205
169- 		if  input .ExtensionServiceNamespace  !=  ""  &&  input .ExtensionServiceName  !=  ""  {
170- 			// NOTE: test extension is already deployed in the management cluster. If for any reason in future we want 
171- 			// to make this test more self-contained this test should be modified in order to create an additional 
172- 			// management cluster; also the E2E test configuration should be modified introducing something like 
173- 			// optional:true allowing to define which providers should not be installed by default in 
174- 			// a management cluster. 
175- 			By ("Deploy Test Extension ExtensionConfig" )
176- 
177- 			// In this test we are defaulting all handlers to non-blocking because we don't expect the handlers to block the 
178- 			// cluster lifecycle by default. Setting defaultAllHandlersToBlocking to false enforces that the test-extension 
179- 			// automatically creates the ConfigMap with non-blocking preloaded responses. 
180- 			defaultAllHandlersToBlocking  :=  false 
181- 			// select on the current namespace 
182- 			// This is necessary so in CI this test doesn't influence other tests by enabling lifecycle hooks 
183- 			// in other test namespaces. 
184- 			namespaces  :=  []string {namespace .Name }
185206			if  input .DeployClusterClassInSeparateNamespace  {
186- 				// Add the ClusterClass namespace, if the ClusterClass is deployed in a separate namespace. 
187- 				namespaces   =   append ( namespaces ,  clusterClassNamespace . Name )
207+ 				variables [ "CLUSTER_CLASS_NAMESPACE" ]  =   clusterClassNamespace . Name 
208+ 				By ( "Creating a cluster referencing a ClusterClass from another namespace" )
188209			}
189- 			extensionConfig  :=  extensionConfig (input .ExtensionConfigName , input .ExtensionServiceNamespace , input .ExtensionServiceName , defaultAllHandlersToBlocking , namespaces ... )
190- 			Expect (input .BootstrapClusterProxy .GetClient ().Create (ctx ,
191- 				extensionConfig )).
192- 				To (Succeed (), "Failed to create the ExtensionConfig" )
193- 		}
194210
195- 		variables  :=  map [string ]string {
196- 			// This is used to template the name of the ExtensionConfig into the ClusterClass. 
197- 			"EXTENSION_CONFIG_NAME" : input .ExtensionConfigName ,
198- 		}
199- 		maps .Copy (variables , input .ClusterctlVariables )
211+ 			clusterctl .ApplyClusterTemplateAndWait (ctx , clusterctl.ApplyClusterTemplateAndWaitInput {
212+ 				ClusterProxy : input .BootstrapClusterProxy ,
213+ 				ConfigCluster : clusterctl.ConfigClusterInput {
214+ 					LogFolder :                filepath .Join (input .ArtifactFolder , "clusters" , input .BootstrapClusterProxy .GetName ()),
215+ 					ClusterctlConfigPath :     input .ClusterctlConfigPath ,
216+ 					ClusterctlVariables :      variables ,
217+ 					KubeconfigPath :           input .BootstrapClusterProxy .GetKubeconfigPath (),
218+ 					InfrastructureProvider :   infrastructureProvider ,
219+ 					Flavor :                   flavor ,
220+ 					Namespace :                namespace .Name ,
221+ 					ClusterName :              clusterName ,
222+ 					KubernetesVersion :        input .E2EConfig .MustGetVariable (KubernetesVersion ),
223+ 					ControlPlaneMachineCount : controlPlaneMachineCount ,
224+ 					WorkerMachineCount :       workerMachineCount ,
225+ 				},
226+ 				ControlPlaneWaiters :          input .ControlPlaneWaiters ,
227+ 				WaitForClusterIntervals :      input .E2EConfig .GetIntervals (specName , "wait-cluster" ),
228+ 				WaitForControlPlaneIntervals : input .E2EConfig .GetIntervals (specName , "wait-control-plane" ),
229+ 				WaitForMachineDeployments :    input .E2EConfig .GetIntervals (specName , "wait-worker-nodes" ),
230+ 				PostMachinesProvisioned : func () {
231+ 					if  input .PostMachinesProvisioned  !=  nil  {
232+ 						input .PostMachinesProvisioned (input .BootstrapClusterProxy , namespace .Name , clusterName )
233+ 					}
234+ 				},
235+ 			}, clusterResources )
236+ 
237+ 			Byf ("Verify Cluster Available condition is true" )
238+ 			framework .VerifyClusterAvailable (ctx , framework.VerifyClusterAvailableInput {
239+ 				Getter :    input .BootstrapClusterProxy .GetClient (),
240+ 				Name :      clusterResources .Cluster .Name ,
241+ 				Namespace : clusterResources .Cluster .Namespace ,
242+ 			})
243+ 
244+ 			Byf ("Verify Machines Ready condition is true" )
245+ 			framework .VerifyMachinesReady (ctx , framework.VerifyMachinesReadyInput {
246+ 				Lister :    input .BootstrapClusterProxy .GetClient (),
247+ 				Name :      clusterResources .Cluster .Name ,
248+ 				Namespace : clusterResources .Cluster .Namespace ,
249+ 			})
250+ 
251+ 			By ("PASSED!" )
200252
201- 		if  input .DeployClusterClassInSeparateNamespace  {
202- 			variables ["CLUSTER_CLASS_NAMESPACE" ] =  clusterClassNamespace .Name 
203- 			By ("Creating a cluster referencing a ClusterClass from another namespace" )
204- 		}
253+ 		})
205254
206- 		clusterctl .ApplyClusterTemplateAndWait (ctx , clusterctl.ApplyClusterTemplateAndWaitInput {
207- 			ClusterProxy : input .BootstrapClusterProxy ,
208- 			ConfigCluster : clusterctl.ConfigClusterInput {
209- 				LogFolder :                filepath .Join (input .ArtifactFolder , "clusters" , input .BootstrapClusterProxy .GetName ()),
210- 				ClusterctlConfigPath :     input .ClusterctlConfigPath ,
211- 				ClusterctlVariables :      variables ,
212- 				KubeconfigPath :           input .BootstrapClusterProxy .GetKubeconfigPath (),
213- 				InfrastructureProvider :   infrastructureProvider ,
214- 				Flavor :                   flavor ,
215- 				Namespace :                namespace .Name ,
216- 				ClusterName :              clusterName ,
217- 				KubernetesVersion :        input .E2EConfig .MustGetVariable (KubernetesVersion ),
218- 				ControlPlaneMachineCount : controlPlaneMachineCount ,
219- 				WorkerMachineCount :       workerMachineCount ,
220- 			},
221- 			ControlPlaneWaiters :          input .ControlPlaneWaiters ,
222- 			WaitForClusterIntervals :      input .E2EConfig .GetIntervals (specName , "wait-cluster" ),
223- 			WaitForControlPlaneIntervals : input .E2EConfig .GetIntervals (specName , "wait-control-plane" ),
224- 			WaitForMachineDeployments :    input .E2EConfig .GetIntervals (specName , "wait-worker-nodes" ),
225- 			PostMachinesProvisioned : func () {
226- 				if  input .PostMachinesProvisioned  !=  nil  {
227- 					input .PostMachinesProvisioned (input .BootstrapClusterProxy , namespace .Name , clusterName )
255+ 		AfterEach (func () {
256+ 			// Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself. 
257+ 			framework .DumpSpecResourcesAndCleanup (ctx , specName , input .BootstrapClusterProxy , input .ClusterctlConfigPath , input .ArtifactFolder , namespace , cancelWatches , clusterResources .Cluster , input .E2EConfig .GetIntervals , input .SkipCleanup )
258+ 			if  ! input .SkipCleanup  {
259+ 				if  input .ExtensionServiceNamespace  !=  ""  &&  input .ExtensionServiceName  !=  ""  {
260+ 					Eventually (func () error  {
261+ 						return  input .BootstrapClusterProxy .GetClient ().Delete (ctx , extensionConfig (input .ExtensionConfigName , input .ExtensionServiceNamespace , input .ExtensionServiceName , true ))
262+ 					}, 10 * time .Second , 1 * time .Second ).Should (Succeed (), "Deleting ExtensionConfig failed" )
263+ 				}
264+ 				if  input .DeployClusterClassInSeparateNamespace  {
265+ 					DeleteNamespace11 (ctx , framework.DeleteNamespaceInput {
266+ 						Deleter : input .BootstrapClusterProxy .GetClient (),
267+ 						Name :    clusterClassNamespace .Name ,
268+ 					})
228269				}
229- 			},
230- 		}, clusterResources )
231- 
232- 		Byf ("Verify Cluster Available condition is true" )
233- 		framework .VerifyClusterAvailable (ctx , framework.VerifyClusterAvailableInput {
234- 			Getter :    input .BootstrapClusterProxy .GetClient (),
235- 			Name :      clusterResources .Cluster .Name ,
236- 			Namespace : clusterResources .Cluster .Namespace ,
270+ 			}
237271		})
238272
239- 		Byf ("Verify Machines Ready condition is true" )
240- 		framework .VerifyMachinesReady (ctx , framework.VerifyMachinesReadyInput {
241- 			Lister :    input .BootstrapClusterProxy .GetClient (),
242- 			Name :      clusterResources .Cluster .Name ,
243- 			Namespace : clusterResources .Cluster .Namespace ,
244- 		})
273+ 	}
274+ }
245275
246- 		By ("PASSED!" )
247- 	})
276+ // DeleteNamespace is used to delete namespace object. 
277+ func  DeleteNamespace11 (ctx  context.Context , input  framework.DeleteNamespaceInput , intervals  ... interface {}) {
278+ 	Expect (ctx ).NotTo (BeNil (), "ctx is required for DeleteNamespace" )
279+ 	Expect (input .Deleter ).NotTo (BeNil (), "input.Deleter is required for DeleteNamespace" )
280+ 	Expect (input .Name ).NotTo (BeEmpty (), "input.Name is required for DeleteNamespace" )
281+ 	ns  :=  & corev1.Namespace {
282+ 		ObjectMeta : metav1.ObjectMeta {
283+ 			Name : input .Name ,
284+ 		},
285+ 	}
286+ 	log .Logf ("Deleting namespace %s" , input .Name )
287+ 	Eventually (func () error  {
288+ 		err  :=  input .Deleter .Delete (ctx , ns )
289+ 		if  err  !=  nil  &&  ! errors .IsNotFound (err ) {
290+ 
291+ 			return  err 
248292
249- 	AfterEach (func () {
250- 		// Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself. 
251- 		framework .DumpSpecResourcesAndCleanup (ctx , specName , input .BootstrapClusterProxy , input .ClusterctlConfigPath , input .ArtifactFolder , namespace , cancelWatches , clusterResources .Cluster , input .E2EConfig .GetIntervals , input .SkipCleanup )
252- 		if  ! input .SkipCleanup  {
253- 			if  input .ExtensionServiceNamespace  !=  ""  &&  input .ExtensionServiceName  !=  ""  {
254- 				Eventually (func () error  {
255- 					return  input .BootstrapClusterProxy .GetClient ().Delete (ctx , extensionConfig (input .ExtensionConfigName , input .ExtensionServiceNamespace , input .ExtensionServiceName , true ))
256- 				}, 10 * time .Second , 1 * time .Second ).Should (Succeed (), "Deleting ExtensionConfig failed" )
257- 			}
258- 			if  input .DeployClusterClassInSeparateNamespace  {
259- 				framework .DeleteNamespace (ctx , framework.DeleteNamespaceInput {
260- 					Deleter : input .BootstrapClusterProxy .GetClient (),
261- 					Name :    clusterClassNamespace .Name ,
262- 				})
263- 			}
264293		}
265- 	})
294+ 		return  nil 
295+ 	}, intervals ... ).Should (Succeed (), "Failed to delete namespace %s" , input .Name )
266296}
0 commit comments