Skip to content

Commit 9265768

Browse files
committed
Add tests for egress policy & custom offerings
1 parent 1ad840e commit 9265768

File tree

11 files changed

+289
-35
lines changed

11 files changed

+289
-35
lines changed

pkg/cloud/isolated_network_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ var _ = ginkgo.Describe("Network", func() {
8484
PublicIpAddresses: []*csapi.PublicIpAddress{{Id: dummies.PublicIPID, Ipaddress: "fakeIP"}}}, nil)
8585
as.EXPECT().NewAssociateIpAddressParams().Return(&csapi.AssociateIpAddressParams{})
8686
as.EXPECT().AssociateIpAddress(gomock.Any())
87+
ns.EXPECT().GetNetworkByID(dummies.ISONet1.ID, gomock.Any()).Return(&csapi.Network{Egressdefaultpolicy: false}, 1, nil)
8788
fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, gomock.Any()).
8889
DoAndReturn(func(_ string, protocol string) *csapi.CreateEgressFirewallRuleParams {
8990
p := &csapi.CreateEgressFirewallRuleParams{}
@@ -138,6 +139,7 @@ var _ = ginkgo.Describe("Network", func() {
138139
ginkgo.Context("for a closed firewall", func() {
139140
ginkgo.It("OpenFirewallRule asks CloudStack to open the firewall", func() {
140141
dummies.Zone1.Network = dummies.ISONet1
142+
ns.EXPECT().GetNetworkByID(dummies.ISONet1.ID, gomock.Any()).Return(&csapi.Network{Egressdefaultpolicy: false}, 1, nil)
141143
fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, gomock.Any()).
142144
DoAndReturn(func(_ string, protocol string) *csapi.CreateEgressFirewallRuleParams {
143145
p := &csapi.CreateEgressFirewallRuleParams{}
@@ -165,6 +167,7 @@ var _ = ginkgo.Describe("Network", func() {
165167
ginkgo.It("OpenFirewallRule asks CloudStack to open the firewall anyway, but doesn't fail", func() {
166168
dummies.Zone1.Network = dummies.ISONet1
167169

170+
ns.EXPECT().GetNetworkByID(dummies.ISONet1.ID, gomock.Any()).Return(&csapi.Network{Egressdefaultpolicy: false}, 1, nil)
168171
fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, gomock.Any()).
169172
DoAndReturn(func(_ string, protocol string) *csapi.CreateEgressFirewallRuleParams {
170173
p := &csapi.CreateEgressFirewallRuleParams{}

test/e2e/common.go

+14-6
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,24 @@ const (
6262
InvalidDomainName = "CLOUDSTACK_INVALID_DOMAIN_NAME"
6363
InvalidTemplateName = "CLOUDSTACK_INVALID_TEMPLATE_NAME"
6464
InvalidCPOfferingName = "CLOUDSTACK_INVALID_CONTROL_PLANE_MACHINE_OFFERING"
65+
66+
CustomNetworkOfferingWithEgressPolicyName = "CLOUDSTACK_NETWORK_CUSTOM_OFFERING_EGRESS_POLICY_TRUE_NAME"
67+
NetworkNameWithCustomOffering = "CLOUDSTACK_NETWORK_NAME_WITH_CUSTOM_OFFERING"
68+
69+
VPCName = "CLOUDSTACK_VPC_NAME"
70+
VPCNetworkName = "CLOUDSTACK_VPC_NETWORK_NAME"
71+
CustomVPCOfferingName = "CLOUDSTACK_CUSTOM_VPC_OFFERING_NAME"
72+
CustomVPCNetworkOfferingName = "CLOUDSTACK_CUSTOM_VPC_NETWORK_OFFERING_NAME"
73+
VPCWithCustomOfferingName = "CLOUDSTACK_VPC_NAME_WITH_CUSTOM_OFFERING"
74+
VPCNetworkWithCustomOfferingName = "CLOUDSTACK_VPC_NETWORK_NAME_WITH_CUSTOM_OFFERING"
6575
)
6676

6777
const (
6878
ControlPlaneIndicator = "-control-plane-"
6979
MachineDeploymentIndicator = "-md-"
7080
DataVolumePrefix = "DATA-"
81+
DefaultVPCOffering = "Default VPC offering"
82+
DefaultVPCNetworkOffering = "DefaultIsolatedNetworkOfferingForVpcNetworks"
7183
)
7284

7385
type CommonSpecInput struct {
@@ -391,15 +403,11 @@ func CheckNetworkExists(client *cloudstack.CloudStackClient, networkName string)
391403
}
392404
return false, err
393405
} else if count > 1 {
394-
return false, fmt.Errorf("Expected 0-1 Network with name %s, but got %d.", networkName, count)
406+
return false, fmt.Errorf("expected 0-1 network with name %s, but got %d", networkName, count)
395407
}
396408
return count == 1, nil
397409
}
398410

399-
func CheckVPCExists(client *cloudstack.CloudStackClient, vpcName string) (bool, error) {
400-
return CheckVPCExistsInProject(client, vpcName, "")
401-
}
402-
403411
func CheckVPCExistsInProject(client *cloudstack.CloudStackClient, vpcName string, project string) (bool, error) {
404412
p := client.VPC.NewListVPCsParams()
405413
p.SetName(vpcName)
@@ -419,7 +427,7 @@ func CheckVPCExistsInProject(client *cloudstack.CloudStackClient, vpcName string
419427
}
420428
return false, err
421429
} else if listResp.Count > 1 {
422-
return false, fmt.Errorf("Expected 0-1 VPC with name %s, but got %d.", vpcName, listResp.Count)
430+
return false, fmt.Errorf("expected 0-1 vpc with name %s, but got %d", vpcName, listResp.Count)
423431
}
424432
return listResp.Count == 1, nil
425433
}

test/e2e/config/cloudstack.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ providers:
8989
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-second-cluster.yaml"
9090
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-shared-network-kubevip.yaml"
9191
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-vpc-network.yaml"
92+
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-custom-vpc-offering.yaml"
93+
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-network-with-custom-offering.yaml"
9294
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-invalid-disk-offering.yaml"
9395
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-invalid-disk-offering-size-for-non-customized.yaml"
9496
- sourcePath: "../data/infrastructure-cloudstack/v1beta3/cluster-template-invalid-disk-offering-size-for-customized.yaml"
@@ -129,10 +131,20 @@ variables:
129131
CLOUDSTACK_INVALID_ACCOUNT_NAME: accountXXXX
130132
CLOUDSTACK_DOMAIN_NAME: ROOT
131133
CLOUDSTACK_INVALID_DOMAIN_NAME: domainXXXX
134+
132135
CLOUDSTACK_NETWORK_NAME: isolated-for-e2e-1
136+
CLOUDSTACK_NETWORK_NAME_WITH_CUSTOM_OFFERING: isolated-for-e2e-1-with-custom-offering
137+
CLOUDSTACK_NETWORK_CUSTOM_OFFERING_EGRESS_POLICY_TRUE_NAME: CustomNetworkOfferingWithEgressPolicyTrue
138+
133139
CLOUDSTACK_VPC_NETWORK_NAME: vpc-isolated-for-e2e-1
134140
CLOUDSTACK_VPC_NAME: vpc-for-e2e-1
135141
CLOUDSTACK_VPC_CIDR: 10.10.0.0/16
142+
143+
CLOUDSTACK_VPC_NAME_WITH_CUSTOM_OFFERING: vpc-for-e2e-1-with-custom-offering
144+
CLOUDSTACK_VPC_NETWORK_NAME_WITH_CUSTOM_OFFERING: vpc-isolated-for-e2e-1-with-custom-offering
145+
CLOUDSTACK_CUSTOM_VPC_OFFERING_NAME: "CustomVPCOffering"
146+
CLOUDSTACK_CUSTOM_VPC_NETWORK_OFFERING_NAME: "CustomVPCNetworkOffering"
147+
136148
CLOUDSTACK_GATEWAY: 10.10.0.1
137149
CLOUDSTACK_NETMASK: 255.255.255.0
138150
CLOUDSTACK_NEW_NETWORK_NAME: isolated-for-e2e-new
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
3+
kind: CloudStackCluster
4+
metadata:
5+
name: ${CLUSTER_NAME}
6+
spec:
7+
failureDomains:
8+
- name: ${CLOUDSTACK_FD1_NAME}
9+
acsEndpoint:
10+
name: ${CLOUDSTACK_FD1_SECRET_NAME}
11+
namespace: default
12+
zone:
13+
name: ${CLOUDSTACK_ZONE_NAME}
14+
network:
15+
name: ${CLOUDSTACK_VPC_NETWORK_NAME_WITH_CUSTOM_OFFERING}
16+
gateway: ${CLOUDSTACK_GATEWAY}
17+
netmask: ${CLOUDSTACK_NETMASK}
18+
offering: ${CLOUDSTACK_CUSTOM_VPC_NETWORK_OFFERING_NAME}
19+
vpc:
20+
name: ${CLOUDSTACK_VPC_NAME_WITH_CUSTOM_OFFERING}
21+
cidr: ${CLOUDSTACK_VPC_CIDR}
22+
offering: ${CLOUDSTACK_CUSTOM_VPC_OFFERING_NAME}
23+
controlPlaneEndpoint:
24+
host: ""
25+
port: 6443
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+
- ./cluster-with-custom-vpc-offering.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
3+
kind: CloudStackCluster
4+
metadata:
5+
name: ${CLUSTER_NAME}
6+
spec:
7+
failureDomains:
8+
- name: ${CLOUDSTACK_FD1_NAME}
9+
acsEndpoint:
10+
name: ${CLOUDSTACK_FD1_SECRET_NAME}
11+
namespace: default
12+
zone:
13+
name: ${CLOUDSTACK_ZONE_NAME}
14+
network:
15+
name: ${CLOUDSTACK_NETWORK_NAME_WITH_CUSTOM_OFFERING}
16+
gateway: ${CLOUDSTACK_GATEWAY}
17+
netmask: ${CLOUDSTACK_NETMASK}
18+
networkoffering:
19+
name: ${CLOUDSTACK_NETWORK_CUSTOM_OFFERING_EGRESS_POLICY_TRUE_NAME}
20+
controlPlaneEndpoint:
21+
host: ""
22+
port: 6443
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+
- ./cluster-with-network-with-custom-offering.yaml
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
// NetworkWithCustomOfferingSpec implements a test that verifies that an app deployed to the workload cluster works.
35+
func NetworkWithCustomOfferingSpec(ctx context.Context, inputGetter func() CommonSpecInput) {
36+
var (
37+
specName = "network-with-custom-offering"
38+
input CommonSpecInput
39+
namespace *corev1.Namespace
40+
cancelWatches context.CancelFunc
41+
clusterResources *clusterctl.ApplyClusterTemplateAndWaitResult
42+
networkOfferingName = input.E2EConfig.GetVariable(CustomNetworkOfferingWithEgressPolicyName)
43+
networkName = input.E2EConfig.GetVariable(NetworkNameWithCustomOffering)
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+
csClient := CreateCloudStackClient(ctx, input.BootstrapClusterProxy.GetKubeconfigPath())
61+
exists, err := CheckNetworkExists(csClient, networkName)
62+
Expect(err).To(BeNil())
63+
Expect(exists).To(BeFalse())
64+
})
65+
66+
It("Should create a new network with a custom offering", func() {
67+
clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{
68+
ClusterProxy: input.BootstrapClusterProxy,
69+
CNIManifestPath: input.E2EConfig.GetVariable(CNIPath),
70+
ConfigCluster: clusterctl.ConfigClusterInput{
71+
LogFolder: filepath.Join(input.ArtifactFolder, "clusters", input.BootstrapClusterProxy.GetName()),
72+
ClusterctlConfigPath: input.ClusterctlConfigPath,
73+
KubeconfigPath: input.BootstrapClusterProxy.GetKubeconfigPath(),
74+
InfrastructureProvider: clusterctl.DefaultInfrastructureProvider,
75+
Flavor: specName,
76+
Namespace: namespace.Name,
77+
ClusterName: fmt.Sprintf("%s-%s", specName, util.RandomString(6)),
78+
KubernetesVersion: input.E2EConfig.GetVariable(KubernetesVersion),
79+
ControlPlaneMachineCount: pointer.Int64(1),
80+
WorkerMachineCount: pointer.Int64(1),
81+
},
82+
WaitForClusterIntervals: input.E2EConfig.GetIntervals(specName, "wait-cluster"),
83+
WaitForControlPlaneIntervals: input.E2EConfig.GetIntervals(specName, "wait-control-plane"),
84+
WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"),
85+
}, clusterResources)
86+
87+
csClient := CreateCloudStackClient(ctx, input.BootstrapClusterProxy.GetKubeconfigPath())
88+
89+
Byf("Checking if network %s exists with offering %s with egress policy %t", networkName, networkOfferingName, true)
90+
network, count, err := csClient.Network.GetNetworkByName(networkName)
91+
Expect(err).To(BeNil())
92+
Expect(count).To(BeEquivalentTo(1))
93+
Expect(network.Name).To(BeEquivalentTo(networkName))
94+
Expect(network.Networkofferingname).To(BeEquivalentTo(networkOfferingName))
95+
Expect(network.Egressdefaultpolicy).To(BeEquivalentTo(true))
96+
97+
By("PASSED!")
98+
})
99+
100+
AfterEach(func() {
101+
// Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself.
102+
dumpSpecResourcesAndCleanup(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, namespace, cancelWatches, clusterResources.Cluster, input.E2EConfig.GetIntervals, input.SkipCleanup)
103+
})
104+
}
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 network with custom offering", func() {
29+
NetworkWithCustomOfferingSpec(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+
})

test/e2e/resource_cleanup.go

+8
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ func ResourceCleanupSpec(ctx context.Context, inputGetter func() CommonSpecInput
8888
Expect(err).To(BeNil())
8989
Expect(exists).To(BeTrue())
9090

91+
Byf("Checking if network %s exists with offering %s with egress policy %t", networkName, DefaultVPCNetworkOffering, false)
92+
network, count, err := csClient.Network.GetNetworkByName(networkName)
93+
Expect(err).To(BeNil())
94+
Expect(count).To(BeEquivalentTo(1))
95+
Expect(network.Name).To(BeEquivalentTo(networkName))
96+
Expect(network.Networkofferingname).To(BeEquivalentTo(DefaultVPCNetworkOffering))
97+
Expect(network.Egressdefaultpolicy).To(BeEquivalentTo(false))
98+
9199
By("PASSED!")
92100
})
93101

0 commit comments

Comments
 (0)