Skip to content

Commit 0c23b02

Browse files
committed
Add resource cleanup test that checks the created network is deleted when deleting cluster
1 parent 90cb431 commit 0c23b02

File tree

6 files changed

+172
-0
lines changed

6 files changed

+172
-0
lines changed

test/e2e/common.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,21 @@ func CheckAffinityGroup(clusterName string, affinityType string) []string {
285285
return affinityIds
286286
}
287287

288+
func CheckNetworkExists(networkName string) (bool, error) {
289+
client := createCloudStackClient()
290+
291+
_, count, err := client.Network.GetNetworkByName(networkName)
292+
if err != nil {
293+
if strings.Contains(err.Error(), "No match found for") {
294+
return false, nil
295+
}
296+
return false, err
297+
} else if count > 1 {
298+
return false, errors.New(fmt.Sprintf("Expected 0-1 Network with name %s, but got %d.", networkName, count))
299+
}
300+
return count == 1, nil
301+
}
302+
288303
func createCloudStackClient() *cloudstack.CloudStackClient {
289304
encodedSecret := os.Getenv("CLOUDSTACK_B64ENCODED_SECRET")
290305
secret, err := base64.StdEncoding.DecodeString(encodedSecret)

test/e2e/config/cloudstack.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ providers:
8585
- sourcePath: "../data/infrastructure-cloudstack/v1beta1/cluster-template-machine-remediation.yaml"
8686
- sourcePath: "../data/infrastructure-cloudstack/v1beta1/cluster-template-affinity-group-pro.yaml"
8787
- sourcePath: "../data/infrastructure-cloudstack/v1beta1/cluster-template-affinity-group-anti.yaml"
88+
- sourcePath: "../data/infrastructure-cloudstack/v1beta1/cluster-template-resource-cleanup.yaml"
8889
- sourcePath: "../data/shared/v1beta1/metadata.yaml"
8990
versions:
9091
- name: v1.0.0
@@ -109,7 +110,9 @@ variables:
109110
CLOUDSTACK_DOMAIN_NAME: ROOT
110111
CLOUDSTACK_INVALID_DOMAIN_NAME: domainXXXX
111112
CLOUDSTACK_NETWORK_NAME: isolated-for-e2e-1
113+
CLOUDSTACK_NEW_NETWORK_NAME: isolated-for-e2e-new
112114
CLUSTER_ENDPOINT_IP: 172.16.2.199
115+
CLUSTER_ENDPOINT_NEW_IP: 172.16.2.201
113116
CLUSTER_ENDPOINT_PORT: 6443
114117
CLOUDSTACK_CONTROL_PLANE_MACHINE_OFFERING: "Large Instance"
115118
CLOUDSTACK_INVALID_CONTROL_PLANE_MACHINE_OFFERING: "OfferingXXXX"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
2+
kind: CloudStackCluster
3+
metadata:
4+
name: ${CLUSTER_NAME}
5+
spec:
6+
zone: ${CLOUDSTACK_ZONE_NAME}
7+
network: ${CLOUDSTACK_NEW_NETWORK_NAME}
8+
controlPlaneEndpoint:
9+
host: ${CLUSTER_ENDPOINT_NEW_IP}
10+
port: ${CLUSTER_ENDPOINT_PORT}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
bases:
2+
- ../bases/cluster-with-kcp.yaml
3+
- ../bases/md.yaml
4+
5+
patchesStrategicMerge:
6+
- ./cloudstack-cluster.yaml

test/e2e/resource_cleanup.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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"
26+
. "github.com/onsi/gomega"
27+
corev1 "k8s.io/api/core/v1"
28+
"k8s.io/utils/pointer"
29+
30+
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
31+
"sigs.k8s.io/cluster-api/util"
32+
)
33+
34+
// ResourceCleanupSpec implements a test that verifies that an app deployed to the workload cluster works.
35+
func ResourceCleanupSpec(ctx context.Context, inputGetter func() CommonSpecInput) {
36+
var (
37+
specName = "resource-cleanup"
38+
input CommonSpecInput
39+
namespace *corev1.Namespace
40+
cancelWatches context.CancelFunc
41+
clusterResources *clusterctl.ApplyClusterTemplateAndWaitResult
42+
networkName = "isolated-for-e2e-new"
43+
)
44+
45+
BeforeEach(func() {
46+
Expect(ctx).NotTo(BeNil(), "ctx is required for %s spec", specName)
47+
input = inputGetter()
48+
Expect(input.E2EConfig).ToNot(BeNil(), "Invalid argument. input.E2EConfig can't be nil when calling %s spec", specName)
49+
Expect(input.ClusterctlConfigPath).To(BeAnExistingFile(), "Invalid argument. input.ClusterctlConfigPath must be an existing file when calling %s spec", specName)
50+
Expect(input.BootstrapClusterProxy).ToNot(BeNil(), "Invalid argument. input.BootstrapClusterProxy can't be nil when calling %s spec", specName)
51+
Expect(os.MkdirAll(input.ArtifactFolder, 0750)).To(Succeed(), "Invalid argument. input.ArtifactFolder can't be created for %s spec", specName)
52+
53+
Expect(input.E2EConfig.Variables).To(HaveKey(KubernetesVersion))
54+
55+
// Setup a Namespace where to host objects for this spec and create a watcher for the namespace events.
56+
namespace, cancelWatches = setupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder)
57+
clusterResources = new(clusterctl.ApplyClusterTemplateAndWaitResult)
58+
59+
exists, err := CheckNetworkExists(networkName)
60+
Expect(err).To(BeNil())
61+
Expect(exists).To(BeFalse())
62+
})
63+
64+
It("Should create a new network when the specified network does not exist", func() {
65+
clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{
66+
ClusterProxy: input.BootstrapClusterProxy,
67+
CNIManifestPath: input.E2EConfig.GetVariable(CNIPath),
68+
ConfigCluster: clusterctl.ConfigClusterInput{
69+
LogFolder: filepath.Join(input.ArtifactFolder, "clusters", input.BootstrapClusterProxy.GetName()),
70+
ClusterctlConfigPath: input.ClusterctlConfigPath,
71+
KubeconfigPath: input.BootstrapClusterProxy.GetKubeconfigPath(),
72+
InfrastructureProvider: clusterctl.DefaultInfrastructureProvider,
73+
Flavor: "resource-cleanup",
74+
Namespace: namespace.Name,
75+
ClusterName: fmt.Sprintf("%s-%s", specName, util.RandomString(6)),
76+
KubernetesVersion: input.E2EConfig.GetVariable(KubernetesVersion),
77+
ControlPlaneMachineCount: pointer.Int64Ptr(1),
78+
WorkerMachineCount: pointer.Int64Ptr(1),
79+
},
80+
WaitForClusterIntervals: input.E2EConfig.GetIntervals(specName, "wait-cluster"),
81+
WaitForControlPlaneIntervals: input.E2EConfig.GetIntervals(specName, "wait-control-plane"),
82+
WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"),
83+
}, clusterResources)
84+
85+
exists, err := CheckNetworkExists(networkName)
86+
Expect(err).To(BeNil())
87+
Expect(exists).To(BeTrue())
88+
89+
By("PASSED!")
90+
})
91+
92+
AfterEach(func() {
93+
// Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself.
94+
dumpSpecResourcesAndCleanup(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, namespace, cancelWatches, clusterResources.Cluster, input.E2EConfig.GetIntervals, input.SkipCleanup)
95+
96+
exists, err := CheckNetworkExists(networkName)
97+
Expect(err).To(BeNil())
98+
Expect(exists).To(BeFalse())
99+
})
100+
}

test/e2e/resource_cleanup_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//go:build e2e
2+
// +build e2e
3+
4+
/*
5+
Copyright 2020 The Kubernetes Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
*/
19+
20+
package e2e
21+
22+
import (
23+
"context"
24+
. "github.com/onsi/ginkgo"
25+
)
26+
27+
var _ = Describe("When testing resource cleanup", func() {
28+
ResourceCleanupSpec(context.TODO(), func() CommonSpecInput {
29+
return CommonSpecInput{
30+
E2EConfig: e2eConfig,
31+
ClusterctlConfigPath: clusterctlConfigPath,
32+
BootstrapClusterProxy: bootstrapClusterProxy,
33+
ArtifactFolder: artifactFolder,
34+
SkipCleanup: skipCleanup,
35+
}
36+
})
37+
38+
})

0 commit comments

Comments
 (0)