Skip to content

Commit d770987

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

File tree

11 files changed

+296
-35
lines changed

11 files changed

+296
-35
lines changed

pkg/cloud/isolated_network_test.go

Lines changed: 3 additions & 0 deletions
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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,25 @@ 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"
83+
DefaultNetworkOffering = "DefaultIsolatedNetworkOfferingWithSourceNatService"
7184
)
7285

7386
type CommonSpecInput struct {
@@ -391,15 +404,11 @@ func CheckNetworkExists(client *cloudstack.CloudStackClient, networkName string)
391404
}
392405
return false, err
393406
} else if count > 1 {
394-
return false, fmt.Errorf("Expected 0-1 Network with name %s, but got %d.", networkName, count)
407+
return false, fmt.Errorf("expected 0-1 network with name %s, but got %d", networkName, count)
395408
}
396409
return count == 1, nil
397410
}
398411

399-
func CheckVPCExists(client *cloudstack.CloudStackClient, vpcName string) (bool, error) {
400-
return CheckVPCExistsInProject(client, vpcName, "")
401-
}
402-
403412
func CheckVPCExistsInProject(client *cloudstack.CloudStackClient, vpcName string, project string) (bool, error) {
404413
p := client.VPC.NewListVPCsParams()
405414
p.SetName(vpcName)
@@ -419,7 +428,7 @@ func CheckVPCExistsInProject(client *cloudstack.CloudStackClient, vpcName string
419428
}
420429
return false, err
421430
} else if listResp.Count > 1 {
422-
return false, fmt.Errorf("Expected 0-1 VPC with name %s, but got %d.", vpcName, listResp.Count)
431+
return false, fmt.Errorf("expected 0-1 vpc with name %s, but got %d", vpcName, listResp.Count)
423432
}
424433
return listResp.Count == 1, nil
425434
}

test/e2e/config/cloudstack.yaml

Lines changed: 12 additions & 0 deletions
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+
offering:
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
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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 string
43+
networkName 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+
networkOfferingName = input.E2EConfig.GetVariable(CustomNetworkOfferingWithEgressPolicyName)
61+
networkName = input.E2EConfig.GetVariable(NetworkNameWithCustomOffering)
62+
63+
csClient := CreateCloudStackClient(ctx, input.BootstrapClusterProxy.GetKubeconfigPath())
64+
exists, err := CheckNetworkExists(csClient, networkName)
65+
Expect(err).To(BeNil())
66+
Expect(exists).To(BeFalse())
67+
})
68+
69+
It("Should create a new network with a custom offering", func() {
70+
clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{
71+
ClusterProxy: input.BootstrapClusterProxy,
72+
CNIManifestPath: input.E2EConfig.GetVariable(CNIPath),
73+
ConfigCluster: clusterctl.ConfigClusterInput{
74+
LogFolder: filepath.Join(input.ArtifactFolder, "clusters", input.BootstrapClusterProxy.GetName()),
75+
ClusterctlConfigPath: input.ClusterctlConfigPath,
76+
KubeconfigPath: input.BootstrapClusterProxy.GetKubeconfigPath(),
77+
InfrastructureProvider: clusterctl.DefaultInfrastructureProvider,
78+
Flavor: specName,
79+
Namespace: namespace.Name,
80+
ClusterName: fmt.Sprintf("%s-%s", specName, util.RandomString(6)),
81+
KubernetesVersion: input.E2EConfig.GetVariable(KubernetesVersion),
82+
ControlPlaneMachineCount: pointer.Int64(1),
83+
WorkerMachineCount: pointer.Int64(1),
84+
},
85+
WaitForClusterIntervals: input.E2EConfig.GetIntervals(specName, "wait-cluster"),
86+
WaitForControlPlaneIntervals: input.E2EConfig.GetIntervals(specName, "wait-control-plane"),
87+
WaitForMachineDeployments: input.E2EConfig.GetIntervals(specName, "wait-worker-nodes"),
88+
}, clusterResources)
89+
90+
csClient := CreateCloudStackClient(ctx, input.BootstrapClusterProxy.GetKubeconfigPath())
91+
92+
Byf("Checking if network %s exists with offering %s with egress policy %t", networkName, networkOfferingName, true)
93+
network, count, err := csClient.Network.GetNetworkByName(networkName)
94+
Expect(err).To(BeNil())
95+
Expect(count).To(BeEquivalentTo(1))
96+
Expect(network.Name).To(BeEquivalentTo(networkName))
97+
Expect(network.Networkofferingname).To(BeEquivalentTo(networkOfferingName))
98+
Expect(network.Egressdefaultpolicy).To(BeEquivalentTo(true))
99+
100+
By("PASSED!")
101+
})
102+
103+
AfterEach(func() {
104+
// Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself.
105+
dumpSpecResourcesAndCleanup(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder, namespace, cancelWatches, clusterResources.Cluster, input.E2EConfig.GetIntervals, input.SkipCleanup)
106+
})
107+
}
Lines changed: 39 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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, DefaultNetworkOffering, 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(DefaultNetworkOffering))
97+
Expect(network.Egressdefaultpolicy).To(BeEquivalentTo(false))
98+
9199
By("PASSED!")
92100
})
93101

0 commit comments

Comments
 (0)