@@ -27,8 +27,11 @@ import (
27
27
. "github.com/onsi/ginkgo/v2"
28
28
. "github.com/onsi/gomega"
29
29
corev1 "k8s.io/api/core/v1"
30
+ "k8s.io/apimachinery/pkg/api/errors"
31
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30
32
"k8s.io/utils/ptr"
31
33
34
+ "sigs.k8s.io/cluster-api/test/e2e/internal/log"
32
35
"sigs.k8s.io/cluster-api/test/framework"
33
36
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
34
37
"sigs.k8s.io/cluster-api/util"
@@ -111,156 +114,183 @@ func QuickStartSpec(ctx context.Context, inputGetter func() QuickStartSpecInput)
111
114
clusterResources * clusterctl.ApplyClusterTemplateAndWaitResult
112
115
)
113
116
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 < 20 ; i ++ {
121
118
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 )
123
126
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
+ }
127
133
}
128
- }
129
134
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 )
132
137
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
+ }
137
142
138
- clusterResources = new (clusterctl.ApplyClusterTemplateAndWaitResult )
139
- })
143
+ clusterResources = new (clusterctl.ApplyClusterTemplateAndWaitResult )
144
+ })
140
145
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" )
143
148
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
+ }
148
153
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
+ }
153
158
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
+ }
158
163
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
+ }
163
168
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 )
168
205
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 }
185
206
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" )
188
209
}
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
- }
194
210
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!" )
200
252
201
- if input .DeployClusterClassInSeparateNamespace {
202
- variables ["CLUSTER_CLASS_NAMESPACE" ] = clusterClassNamespace .Name
203
- By ("Creating a cluster referencing a ClusterClass from another namespace" )
204
- }
253
+ })
205
254
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
+ })
228
269
}
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
+ }
237
271
})
238
272
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
+ }
245
275
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
248
292
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
- }
264
293
}
265
- })
294
+ return nil
295
+ }, intervals ... ).Should (Succeed (), "Failed to delete namespace %s" , input .Name )
266
296
}
0 commit comments