Skip to content

Commit a5c90b4

Browse files
committed
Add e2e test for project
1 parent eba72cf commit a5c90b4

File tree

8 files changed

+204
-2
lines changed

8 files changed

+204
-2
lines changed

docs/book/src/getting-started.md

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
secret-key: <cloudstackSecretKey>
3636
api-url: <cloudstackApiUrl>
3737
verify-ssl: "false"
38-
project-id: <project id> # Optional. If provided, the provider will use this project id for all operations
3938
4039
```
4140
- Apply this secret to the management cluster:

test/e2e/common.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,16 @@ func DestroyOneMachine(client *cloudstack.CloudStackClient, clusterName string,
280280
}
281281

282282
func CheckAffinityGroupsDeleted(client *cloudstack.CloudStackClient, affinityIds []string) error {
283+
return CheckAffinityGroupsDeletedInProject(client, affinityIds, "")
284+
}
285+
286+
func CheckAffinityGroupsDeletedInProject(client *cloudstack.CloudStackClient, affinityIds []string, project string) error {
283287
if len(affinityIds) == 0 {
284288
return errors.New("affinityIds are empty")
285289
}
286290

287291
for _, affinityId := range affinityIds {
288-
affinity, count, _ := client.AffinityGroup.GetAffinityGroupByID(affinityId)
292+
affinity, count, _ := client.AffinityGroup.GetAffinityGroupByID(affinityId, cloudstack.WithProject(project))
289293
if count > 0 {
290294
return errors.New("Affinity group " + affinity.Name + " still exists")
291295
}

test/e2e/config/cloudstack.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ variables:
124124
CLOUDSTACK_INVALID_ZONE_NAME: zoneXXXX
125125
CLOUDSTACK_INVALID_NETWORK_NAME: networkXXXX
126126
CLOUDSTACK_ACCOUNT_NAME: admin
127+
CLOUDSTACK_PROJECT_NAME: capc-e2e-test
127128
CLOUDSTACK_INVALID_ACCOUNT_NAME: accountXXXX
128129
CLOUDSTACK_DOMAIN_NAME: ROOT
129130
CLOUDSTACK_INVALID_DOMAIN_NAME: domainXXXX
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
2+
kind: CloudStackCluster
3+
metadata:
4+
name: ${CLUSTER_NAME}
5+
spec:
6+
failureDomains:
7+
- name: ${CLOUDSTACK_FD1_NAME}
8+
acsEndpoint:
9+
name: ${CLOUDSTACK_FD1_SECRET_NAME}
10+
namespace: default
11+
zone:
12+
name : ${CLOUDSTACK_ZONE_NAME}
13+
network:
14+
name: ${CLOUDSTACK_NETWORK_NAME}
15+
project: ${CLOUDSTACK_PROJECT_NAME}
16+
controlPlaneEndpoint:
17+
host: ""
18+
port: 6443
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
bases:
2+
- ../bases/cluster-with-kcp.yaml
3+
- ../bases/md.yaml
4+
5+
patchesStrategicMerge:
6+
- ./cloudstack-cluster.yaml
7+
- ./md.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
3+
kind: CloudStackMachineTemplate
4+
metadata:
5+
name: ${CLUSTER_NAME}-control-plane
6+
spec:
7+
template:
8+
spec:
9+
offering:
10+
name: ${CLOUDSTACK_CONTROL_PLANE_MACHINE_OFFERING}
11+
template:
12+
name: ${CLOUDSTACK_TEMPLATE_NAME}
13+
sshKey: ${CLOUDSTACK_SSH_KEY_NAME}
14+
affinity: pro
15+
---
16+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
17+
kind: CloudStackMachineTemplate
18+
metadata:
19+
name: ${CLUSTER_NAME}-md-0
20+
spec:
21+
template:
22+
spec:
23+
offering:
24+
name: ${CLOUDSTACK_WORKER_MACHINE_OFFERING}
25+
template:
26+
name: ${CLOUDSTACK_TEMPLATE_NAME}
27+
sshKey: ${CLOUDSTACK_SSH_KEY_NAME}
28+
affinity: pro

test/e2e/project.go

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

test/e2e/project_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
25+
. "github.com/onsi/ginkgo/v2"
26+
)
27+
28+
var _ = Describe("When testing project", func() {
29+
ProjectSpec(context.TODO(), func() CommonSpecInput {
30+
return CommonSpecInput{
31+
E2EConfig: e2eConfig,
32+
ClusterctlConfigPath: clusterctlConfigPath,
33+
BootstrapClusterProxy: bootstrapClusterProxy,
34+
ArtifactFolder: artifactFolder,
35+
SkipCleanup: skipCleanup,
36+
}
37+
})
38+
39+
})

0 commit comments

Comments
 (0)