Skip to content

Commit 272bcf4

Browse files
Add e2e test to cover crossNamespace provisionging
Signed-off-by: Danil-Grigorev <[email protected]>
1 parent f6342fb commit 272bcf4

File tree

6 files changed

+169
-1
lines changed

6 files changed

+169
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ generate-e2e-templates-main: $(KUSTOMIZE)
617617
$(KUSTOMIZE) build $(DOCKER_TEMPLATES)/main/cluster-template-topology --load-restrictor LoadRestrictionsNone > $(DOCKER_TEMPLATES)/main/cluster-template-topology.yaml
618618
$(KUSTOMIZE) build $(DOCKER_TEMPLATES)/main/cluster-template-ignition --load-restrictor LoadRestrictionsNone > $(DOCKER_TEMPLATES)/main/cluster-template-ignition.yaml
619619
$(KUSTOMIZE) build $(DOCKER_TEMPLATES)/main/clusterclass-quick-start-kcp-only --load-restrictor LoadRestrictionsNone > $(DOCKER_TEMPLATES)/main/clusterclass-quick-start-kcp-only.yaml
620-
620+
$(KUSTOMIZE) build $(DOCKER_TEMPLATES)/main/cluster-template-cross-ns-topology --load-restrictor LoadRestrictionsNone > $(DOCKER_TEMPLATES)/main/cluster-template-cross-ns-topology.yaml
621621
$(KUSTOMIZE) build $(INMEMORY_TEMPLATES)/main/cluster-template --load-restrictor LoadRestrictionsNone > $(INMEMORY_TEMPLATES)/main/cluster-template.yaml
622622

623623
.PHONY: generate-metrics-config

test/e2e/config/docker.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ providers:
347347
- sourcePath: "../data/infrastructure-docker/main/cluster-template-topology-autoscaler.yaml"
348348
- sourcePath: "../data/infrastructure-docker/main/cluster-template-topology.yaml"
349349
- sourcePath: "../data/infrastructure-docker/main/cluster-template-ignition.yaml"
350+
- sourcePath: "../data/infrastructure-docker/main/cluster-template-cross-ns-topology.yaml"
350351
- sourcePath: "../data/infrastructure-docker/main/clusterclass-quick-start.yaml"
351352
- sourcePath: "../data/infrastructure-docker/main/clusterclass-quick-start-kcp-only.yaml"
352353
- sourcePath: "../data/infrastructure-docker/main/clusterclass-quick-start-runtimesdk.yaml"

test/e2e/cross-ns-quick-start.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package e2e
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"os"
23+
"path/filepath"
24+
25+
. "github.com/onsi/ginkgo/v2"
26+
. "github.com/onsi/gomega"
27+
corev1 "k8s.io/api/core/v1"
28+
"k8s.io/utils/ptr"
29+
30+
"sigs.k8s.io/cluster-api/test/framework"
31+
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
32+
"sigs.k8s.io/cluster-api/util"
33+
)
34+
35+
// CrossNsSpecInput is the input for QuickStartSpec in separate namespaces.
36+
type CrossNsSpecInput struct {
37+
QuickStartSpecInput
38+
}
39+
40+
// QuickStartSpec implements a spec that mimics the operation described in the Cluster API quick start, that is
41+
// creating a workload cluster.
42+
// This test is meant to provide a first, fast signal to detect regression; it is recommended to use it as a PR blocker test.
43+
// NOTE: This test works with Clusters with and without ClusterClass.
44+
func CrossNsSpecQuickstart(ctx context.Context, inputGetter func() CrossNsSpecInput) {
45+
var (
46+
specName = "quick-start"
47+
input CrossNsSpecInput
48+
namespace *corev1.Namespace
49+
clusterNamespace *corev1.Namespace
50+
cancelWatches context.CancelFunc
51+
cancelWatchesCluster context.CancelFunc
52+
clusterResources *clusterctl.ApplyClusterTemplateAndWaitResult
53+
)
54+
55+
BeforeEach(func() {
56+
Expect(ctx).NotTo(BeNil(), "ctx is required for %s spec", specName)
57+
input = inputGetter()
58+
Expect(input.E2EConfig).ToNot(BeNil(), "Invalid argument. input.E2EConfig can't be nil when calling %s spec", specName)
59+
Expect(input.ClusterctlConfigPath).To(BeAnExistingFile(), "Invalid argument. input.ClusterctlConfigPath must be an existing file when calling %s spec", specName)
60+
Expect(input.BootstrapClusterProxy).ToNot(BeNil(), "Invalid argument. input.BootstrapClusterProxy can't be nil when calling %s spec", specName)
61+
Expect(os.MkdirAll(input.ArtifactFolder, 0750)).To(Succeed(), "Invalid argument. input.ArtifactFolder can't be created for %s spec", specName)
62+
63+
Expect(input.E2EConfig.Variables).To(HaveKey(KubernetesVersion))
64+
65+
// Setup a Namespace where to host objects for this spec and create a watcher for the namespace events.
66+
namespace, cancelWatches = framework.SetupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, input.PostNamespaceCreated)
67+
clusterNamespace, cancelWatchesCluster = framework.SetupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, input.PostNamespaceCreated)
68+
clusterResources = new(clusterctl.ApplyClusterTemplateAndWaitResult)
69+
})
70+
71+
It("Should create a workload cluster in a separate namespace", func() {
72+
infrastructureProvider := clusterctl.DefaultInfrastructureProvider
73+
if input.InfrastructureProvider != nil {
74+
infrastructureProvider = *input.InfrastructureProvider
75+
}
76+
77+
flavor := clusterctl.DefaultFlavor
78+
if input.Flavor != nil {
79+
flavor = *input.Flavor
80+
}
81+
82+
controlPlaneMachineCount := ptr.To[int64](1)
83+
if input.ControlPlaneMachineCount != nil {
84+
controlPlaneMachineCount = input.ControlPlaneMachineCount
85+
}
86+
87+
workerMachineCount := ptr.To[int64](1)
88+
if input.WorkerMachineCount != nil {
89+
workerMachineCount = input.WorkerMachineCount
90+
}
91+
92+
clusterName := fmt.Sprintf("%s-%s", specName, util.RandomString(6))
93+
if input.ClusterName != nil {
94+
clusterName = *input.ClusterName
95+
}
96+
97+
By("Creating a cluster referencing a clusterClass from another namespace")
98+
clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{
99+
ClusterProxy: input.BootstrapClusterProxy,
100+
ConfigCluster: clusterctl.ConfigClusterInput{
101+
LogFolder: filepath.Join(input.ArtifactFolder, "clusters", input.BootstrapClusterProxy.GetName()),
102+
ClusterctlConfigPath: input.ClusterctlConfigPath,
103+
ClusterctlVariables: map[string]string{
104+
"CLUSTER_CLASS_NAMESPACE": namespace.Name,
105+
},
106+
KubeconfigPath: input.BootstrapClusterProxy.GetKubeconfigPath(),
107+
InfrastructureProvider: infrastructureProvider,
108+
Flavor: flavor,
109+
Namespace: clusterNamespace.Name,
110+
ClusterName: clusterName,
111+
KubernetesVersion: input.E2EConfig.GetVariable(KubernetesVersion),
112+
ControlPlaneMachineCount: controlPlaneMachineCount,
113+
WorkerMachineCount: workerMachineCount,
114+
},
115+
ControlPlaneWaiters: input.ControlPlaneWaiters,
116+
WaitForClusterIntervals: input.E2EConfig.GetIntervals(specName, "wait-cluster"),
117+
WaitForControlPlaneIntervals: input.E2EConfig.GetIntervals(specName, "wait-control-plane"),
118+
WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"),
119+
PostMachinesProvisioned: func() {
120+
if input.PostMachinesProvisioned != nil {
121+
input.PostMachinesProvisioned(input.BootstrapClusterProxy, clusterNamespace.Name, clusterName)
122+
}
123+
},
124+
}, clusterResources)
125+
126+
By("PASSED!")
127+
})
128+
129+
AfterEach(func() {
130+
// Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself.
131+
framework.DumpSpecResourcesAndCleanup(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, clusterNamespace, cancelWatchesCluster, clusterResources.Cluster, input.E2EConfig.GetIntervals, input.SkipCleanup)
132+
framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{
133+
Deleter: input.BootstrapClusterProxy.GetClient(),
134+
Name: namespace.Name,
135+
})
136+
cancelWatches()
137+
})
138+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
apiVersion: cluster.x-k8s.io/v1beta1
3+
kind: Cluster
4+
metadata:
5+
name: '${CLUSTER_NAME}'
6+
spec:
7+
topology:
8+
classNamespace: '${CLUSTER_CLASS_NAMESPACE}'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
resources:
2+
- ../cluster-template-topology-no-workers
3+
4+
patches:
5+
- path: cluster.yaml

test/e2e/quick_start_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ var _ = Describe("When following the Cluster API quick-start with ClusterClass [
124124
})
125125
})
126126

127+
var _ = Describe("When following the Cluster API quick-start with a cross-ns referenced ClusterClass [PR-Blocking] [ClusterClass]", func() {
128+
CrossNsSpecQuickstart(ctx, func() CrossNsSpecInput {
129+
return CrossNsSpecInput{
130+
QuickStartSpecInput: QuickStartSpecInput{
131+
E2EConfig: e2eConfig,
132+
ClusterctlConfigPath: clusterctlConfigPath,
133+
BootstrapClusterProxy: bootstrapClusterProxy,
134+
ArtifactFolder: artifactFolder,
135+
SkipCleanup: skipCleanup,
136+
Flavor: ptr.To("cross-ns-topology"),
137+
InfrastructureProvider: ptr.To("docker"),
138+
},
139+
}
140+
})
141+
})
142+
127143
// NOTE: This test requires an IPv6 management cluster (can be configured via IP_FAMILY=IPv6).
128144
var _ = Describe("When following the Cluster API quick-start with IPv6 [IPv6]", func() {
129145
QuickStartSpec(ctx, func() QuickStartSpecInput {

0 commit comments

Comments
 (0)