Skip to content

Commit 4a0b6ba

Browse files
authored
Merge pull request #301 from Nordix/e2e
E2e specifications and IP Family support
2 parents d62d62f + 3288c83 commit 4a0b6ba

23 files changed

+787
-192
lines changed

Makefile

+3-12
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ LOCAL_VERSION ?= $(VERSION)
2929

3030
# E2E tests
3131
E2E_FOCUS ?= ""
32-
TRAFFIC_GENERATOR_CMD ?= "docker exec -i {trench}"
33-
NAMESPACE ?= red
34-
E2E_SCRIPT ?= "./data/kind/test.sh"
32+
E2E_PARAMETERS ?= $(shell cat ./test/e2e/environment/kind-helm/dualstack/config.txt | tr '\n' ' ')
33+
E2E_SEED ?= $(shell shuf -i 1-2147483647 -n1)
3534

3635
# Contrainer Registry
3736
REGISTRY ?= localhost:5000/meridio
@@ -119,15 +118,7 @@ lint: golangci-lint ## Run linter against code.
119118

120119
.PHONY: e2e
121120
e2e: ginkgo ## Run the E2E tests.
122-
ginkgo -v --focus=$(E2E_FOCUS) --repeat=0 --timeout=1h ./test/e2e/... -- \
123-
-traffic-generator-cmd=$(TRAFFIC_GENERATOR_CMD) \
124-
-namespace=${NAMESPACE} \
125-
-script=${E2E_SCRIPT} \
126-
-conduit-a-1-name=load-balancer \
127-
-conduit-b-1-name=load-balancer \
128-
-stream-a-1-name=stream-a \
129-
-stream-b-1-name=stream-a \
130-
-lb-fe-deployment-name=load-balancer-trench-a
121+
ginkgo -v --focus=$(E2E_FOCUS) --seed=$(E2E_SEED) --repeat=0 --timeout=1h ./test/e2e/... -- $(E2E_PARAMETERS)
131122

132123
.PHONY: test
133124
test: ## Run the Unit tests.

docs/resources/Initial-Deployment-E2E.svg

+1-1
Loading

docs/test.md

+62-26
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,74 @@
22

33
## E2E Tests
44

5-
### Environment
5+
### Environment / Framework
66

77
#### Initial Deployment
88

9-
<img src="resources/Initial-Deployment-E2E.svg" width="50%">
10-
11-
#### Test in another environment
12-
13-
1. Set `TRAFFIC_GENERATOR_CMD` when running `make e2e`
14-
2. Implement `test.sh`
9+
The picture below shows the initial deployment that should be installed in a kubernetes cluster in order to execute the complete e2e test suite in dualstack. With only IPv4, elements containing `v6` are not used, and with only IPv6, elements containing `v4` are not used. Elements between `[]` are configurable via parameters, see the `Configuration` section.
10+
11+
![Initial-Deployment-E2E](resources/Initial-Deployment-E2E.svg)
12+
13+
#### Configuration
14+
15+
| Name | Type | Description |
16+
|---|---|---|
17+
| traffic-generator-cmd | string | Command to use to connect to the traffic generator. All occurences of '{trench}' will be replaced with the trench name. |
18+
| script | string | Path + script used by the e2e tests |
19+
| | | |
20+
| k8s-namespace | string | Name of the namespace |
21+
| target-a-deployment-name | string | Name of the target deployment |
22+
| trench-a | string | Name of the trench |
23+
| attractor-a-1 | string | Name of the attractor |
24+
| conduit-a-1 | string | Name of the conduit |
25+
| stream-a-I | string | Name of the stream |
26+
| stream-a-II | string | Name of the stream |
27+
| flow-a-z-tcp | string | Name of the flow |
28+
| flow-a-z-tcp-destination-port-0 | int | Destination port 0 |
29+
| flow-a-z-udp | string | Name of the flow |
30+
| flow-a-z-udp-destination-port-0 | int | Destination port 0 |
31+
| flow-a-x-tcp | string | Name of the flow |
32+
| flow-a-x-tcp-destination-port-0 | int | Destination port 0 |
33+
| vip-1-v4 | string | Address of the vip v4 number 1 |
34+
| vip-1-v6 | string | Address of the vip v6 number 1 |
35+
| target-b-deployment-name | string | Name of the target deployment |
36+
| trench-b | string | Name of the trench |
37+
| conduit-b-1 | string | Name of the conduit |
38+
| stream-b-I | string | Name of the stream |
39+
| vip-2-v4 | string | Address of the vip v4 number 2 |
40+
| vip-2-v6 | string | Address of the vip v6 number 2 |
41+
| | | |
42+
| stateless-lb-fe-deployment-name | string | Name of stateless-lb-fe deployment in `trench-a` |
43+
| ip-family | string | IP Family |
44+
45+
For more details about each parameter, check the picture above in the `Initial Deployment` section.
46+
47+
#### Script
48+
49+
A bash script file must be passed as parameter of the e2e tests. The script is required to allowed the e2e tests to be run in every environment (Helm/Operator deployement...). The following functions has to be implemented in the script:
50+
51+
| Name | Description |
52+
|---|---|
53+
| init () error | Executed once before running the tests |
54+
| end () error | Executed once after running the tests |
55+
| configuration_new_ip () error | Executed just before running the `new-vip` test |
56+
| configuration_new_ip_revert () error | Executed just after running the `new-vip` test |
1557

1658
### List of tests
1759

18-
- IngressTraffic (ingress_traffic_test.go)
19-
- IPv4 TCP traffic (20.0.0.1:4000)
20-
- IPv4 UDP traffic (20.0.0.1:4003)
21-
- IPv6 TCP traffic ([2000::1]:4000)
22-
- IPv6 UDP traffic ([2000::1]:4003)
23-
- MultiTrenches (multi_trenches_test.go)
24-
- Disconnect a target from trench-a and connect it to trench-b, then test traffic in both trench (and revert the changes)
25-
- Send traffic in 2 trenches (with the same configuration) at the same time
26-
- Scaling (scaling_test.go)
27-
- Scale in targets to 3 (and back to 4)
28-
- Scale in targets to 5 (and back to 4)
29-
- Target (target_test.go)
30-
- Close a stream, check traffic has not been received by the target and re-open the stream
31-
- Configuration (configuration_test.go)
32-
- Add a new VIP (60.0.0.150) to stream-a and attractor-a and test traffic and remove it after
33-
34-
### Tools
35-
36-
- ginkgo - https://onsi.github.io/ginkgo/#getting-ginkgo
60+
| Name | Type | Description |
61+
|---|---|---|
62+
| TCP-IPv4 | IngressTraffic | Send traffic in `trench-a` with `vip-1-v4` as destination IP and `flow-a-z-tcp-destination-port-0` as destination port |
63+
| TCP-IPv6 | IngressTraffic | Send traffic in `trench-a` with `vip-1-v6` as destination IP and `flow-a-z-tcp-destination-port-0` as destination port |
64+
| UDP-IPv4 | IngressTraffic | Send traffic in `trench-a` with `vip-1-v4` as destination IP and `flow-a-z-udp-destination-port-0` as destination port |
65+
| UDP-IPv6 | IngressTraffic | Send traffic in `trench-a` with `vip-1-v6` as destination IP and `flow-a-z-udp-destination-port-0` as destination port |
66+
| MT-Switch | MultiTrenches | Disconnect a target from `target-a-deployment-name` from `trench-a` and connect it to `trench-b` |
67+
| MT-Parallel | MultiTrenches | Send traffic in `trench-a` and `trench-b` at the same time |
68+
| Scale-Down | Scaling | Scale down `target-a-deployment-name` |
69+
| Scale-Up | Scaling | Scale up `target-a-deployment-name` |
70+
| close-open | TAPA | Close `stream-a-I` in one of the target from `target-a-deployment-name` and re-open it |
71+
| new-vip | Configuration | Configure `vip-2-v4` and `vip-2-v6` in `flow-a-z-tcp` and `attractor-a-1` |
72+
<!-- TODO: | open | TAPA | Open `stream-a-II` in one of the target from `target-a-deployment-name` and close it | -->
3773

3874
### Steps (Kind)
3975

test/e2e/configuration_test.go

+15-6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"bytes"
2121
"os/exec"
2222

23+
"github.com/nordix/meridio/test/e2e/utils"
2324
. "github.com/onsi/ginkgo/v2"
2425
. "github.com/onsi/gomega"
2526
)
@@ -30,7 +31,7 @@ var _ = Describe("Configuration", func() {
3031

3132
When("creating a new vip and adding it to existing stream and attractor", func() {
3233
BeforeEach(func() {
33-
cmd := exec.Command(script, "configuration_new_ip")
34+
cmd := exec.Command(config.script, "configuration_new_ip")
3435
var stderr bytes.Buffer
3536
cmd.Stderr = &stderr
3637
err := cmd.Run()
@@ -39,7 +40,7 @@ var _ = Describe("Configuration", func() {
3940
})
4041

4142
AfterEach(func() {
42-
cmd := exec.Command(script, "configuration_new_ip_revert")
43+
cmd := exec.Command(config.script, "configuration_new_ip_revert")
4344
var stderr bytes.Buffer
4445
cmd.Stderr = &stderr
4546
err := cmd.Run()
@@ -48,10 +49,18 @@ var _ = Describe("Configuration", func() {
4849
})
4950

5051
It("should receive the traffic correctly", func() {
51-
By("Checking if all targets have receive traffic via the new VIP with no traffic interruption (no lost connection)")
52-
lastingConnections, lostConnections := trafficGeneratorHost.SendTraffic(trafficGenerator, trenchAName, namespace, newTCPVIP, "tcp")
53-
Expect(lostConnections).To(Equal(0))
54-
Expect(len(lastingConnections)).To(Equal(numberOfTargetA))
52+
if !utils.IsIPv6(config.ipFamily) { // Don't send traffic with IPv4 if the tests are only IPv6
53+
By("Checking if all targets have receive ipv4 traffic via the new VIP with no traffic interruption (no lost connection)")
54+
lastingConnections, lostConnections := trafficGeneratorHost.SendTraffic(trafficGenerator, config.trenchA, config.k8sNamespace, utils.VIPPort(config.vip2V4, config.flowAZTcpDestinationPort0), "tcp")
55+
Expect(lostConnections).To(Equal(0))
56+
Expect(len(lastingConnections)).To(Equal(numberOfTargetA))
57+
}
58+
if !utils.IsIPv4(config.ipFamily) { // Don't send traffic with IPv6 if the tests are only IPv4
59+
By("Checking if all targets have receive ipv6 traffic via the new VIP with no traffic interruption (no lost connection)")
60+
lastingConnections, lostConnections := trafficGeneratorHost.SendTraffic(trafficGenerator, config.trenchA, config.k8sNamespace, utils.VIPPort(config.vip2V6, config.flowAZTcpDestinationPort0), "tcp")
61+
Expect(lostConnections).To(Equal(0))
62+
Expect(len(lastingConnections)).To(Equal(numberOfTargetA))
63+
}
5564
})
5665
})
5766

test/e2e/e2e_suite_test.go

+68-47
Original file line numberDiff line numberDiff line change
@@ -32,60 +32,81 @@ import (
3232
)
3333

3434
var (
35-
trafficGeneratorCMD string
36-
namespace string
37-
script string
38-
39-
trenchAName string
40-
trenchBName string
41-
conduitA1Name string
42-
conduitB1Name string
43-
streamA1Name string
44-
streamB1Name string
45-
46-
tcpIPv4 string
47-
tcpIPv6 string
48-
udpIPv4 string
49-
udpIPv6 string
50-
51-
newTCPVIP string
52-
53-
lbfeDeploymentName string
54-
55-
targetADeploymentName string
56-
numberOfTargetA int
57-
targetBDeploymentName string
58-
numberOfTargetB int
59-
6035
clientset *kubernetes.Clientset
6136

6237
trafficGeneratorHost *utils.TrafficGeneratorHost
6338
trafficGenerator utils.TrafficGenerator
39+
40+
numberOfTargetA int
41+
numberOfTargetB int
42+
43+
config *e2eTestConfiguration
6444
)
6545

46+
type e2eTestConfiguration struct {
47+
trafficGeneratorCMD string
48+
script string
49+
50+
k8sNamespace string
51+
targetADeploymentName string
52+
trenchA string
53+
attractorA1 string
54+
conduitA1 string
55+
streamAI string
56+
streamAII string
57+
flowAZTcp string
58+
flowAZTcpDestinationPort0 int
59+
flowAZUdp string
60+
flowAZUdpDestinationPort0 int
61+
flowAXTcp string
62+
flowAXTcpDestinationPort0 int
63+
vip1V4 string
64+
vip1V6 string
65+
targetBDeploymentName string
66+
trenchB string
67+
conduitB1 string
68+
streamBI string
69+
vip2V4 string
70+
vip2V6 string
71+
72+
statelessLbFeDeploymentName string
73+
ipFamily string
74+
}
75+
6676
const (
6777
timeout = time.Minute * 3
6878
interval = time.Second * 2
6979
)
7080

7181
func init() {
72-
flag.StringVar(&trafficGeneratorCMD, "traffic-generator-cmd", "docker exec -i {trench}", "Command to use to connect to the traffic generator. All occurences of '{trench}' will be replaced with the trench name.")
73-
flag.StringVar(&namespace, "namespace", "red", "the namespace where expects operator to exist")
74-
flag.StringVar(&script, "script", "./data/kind/test.sh", "path + script used by the e2e tests")
75-
flag.StringVar(&trenchAName, "trench-a-name", "trench-a", "Name of trench-a (see e2e documentation diagram)")
76-
flag.StringVar(&trenchBName, "trench-b-name", "trench-b", "Name of trench-b (see e2e documentation diagram)")
77-
flag.StringVar(&conduitA1Name, "conduit-a-1-name", "conduit-a-1", "Name of conduit-a-1 (see e2e documentation diagram)")
78-
flag.StringVar(&conduitB1Name, "conduit-b-1-name", "conduit-b-1", "Name of conduit-b-1 (see e2e documentation diagram)")
79-
flag.StringVar(&streamA1Name, "stream-a-1-name", "stream-a-1", "Name of stream-a-1 (see e2e documentation diagram)")
80-
flag.StringVar(&streamB1Name, "stream-b-1-name", "stream-b-1", "Name of stream-b-1 (see e2e documentation diagram)")
81-
flag.StringVar(&lbfeDeploymentName, "lb-fe-deployment-name", "lb-fe-attractor-a-1", "Name of load-balancer deployment in trench-a")
82-
flag.StringVar(&targetADeploymentName, "target-a-deployment-name", "target-a", "Name of target-a deployment in trench-a")
83-
flag.StringVar(&targetBDeploymentName, "target-b-deployment-name", "target-b", "Name of target-b deployment in trench-b")
84-
flag.StringVar(&tcpIPv4, "tcp-ipv4", "20.0.0.1:4000", "IP + Port used for testing IPv4 TCP")
85-
flag.StringVar(&tcpIPv6, "tcp-ipv6", "[2000::1]:4000", "IP + Port used for testing IPv6 TCP")
86-
flag.StringVar(&udpIPv4, "udp-ipv4", "20.0.0.1:4003", "IP + Port used for testing IPv4 UDP")
87-
flag.StringVar(&udpIPv6, "udp-ipv6", "[2000::1]:4003", "IP + Port used for testing IPv6 UDP")
88-
flag.StringVar(&newTCPVIP, "new-tcp-vip", "60.0.0.150:4000", "IP + Port used for testing a new VIP with TCP")
82+
config = &e2eTestConfiguration{}
83+
flag.StringVar(&config.trafficGeneratorCMD, "traffic-generator-cmd", "", "Command to use to connect to the traffic generator. All occurences of '{trench}' will be replaced with the trench name.")
84+
flag.StringVar(&config.script, "script", "", "Path + script used by the e2e tests")
85+
86+
flag.StringVar(&config.k8sNamespace, "k8s-namespace", "", "Name of the namespace")
87+
flag.StringVar(&config.targetADeploymentName, "target-a-deployment-name", "", "Name of the namespace")
88+
flag.StringVar(&config.trenchA, "trench-a", "", "Name of the trench")
89+
flag.StringVar(&config.attractorA1, "attractor-a-1", "", "Name of the attractor")
90+
flag.StringVar(&config.conduitA1, "conduit-a-1", "", "Name of the conduit")
91+
flag.StringVar(&config.streamAI, "stream-a-I", "", "Name of the stream")
92+
flag.StringVar(&config.streamAII, "stream-a-II", "", "Name of the stream")
93+
flag.StringVar(&config.flowAZTcp, "flow-a-z-tcp", "", "Name of the flow")
94+
flag.IntVar(&config.flowAZTcpDestinationPort0, "flow-a-z-tcp-destination-port-0", 4000, "Destination port 0")
95+
flag.StringVar(&config.flowAZUdp, "flow-a-z-udp", "", "Name of the flow")
96+
flag.IntVar(&config.flowAZUdpDestinationPort0, "flow-a-z-udp-destination-port-0", 4000, "Destination port 0")
97+
flag.StringVar(&config.flowAXTcp, "flow-a-x-tcp", "", "Name of the flow")
98+
flag.IntVar(&config.flowAXTcpDestinationPort0, "flow-a-x-tcp-destination-port-0", 4000, "Destination port 0")
99+
flag.StringVar(&config.vip1V4, "vip-1-v4", "", "Address of the vip v4 number 1")
100+
flag.StringVar(&config.vip1V6, "vip-1-v6", "", "Address of the vip v6 number 1")
101+
flag.StringVar(&config.targetBDeploymentName, "target-b-deployment-name", "", "Name of the target deployment")
102+
flag.StringVar(&config.trenchB, "trench-b", "", "Name of the trench")
103+
flag.StringVar(&config.conduitB1, "conduit-b-1", "", "Name of the conduit")
104+
flag.StringVar(&config.streamBI, "stream-b-I", "", "Name of the stream")
105+
flag.StringVar(&config.vip2V4, "vip-2-v4", "", "Address of the vip v4 number 2")
106+
flag.StringVar(&config.vip2V6, "vip-2-v6", "", "Address of the vip v6 number 2")
107+
108+
flag.StringVar(&config.statelessLbFeDeploymentName, "stateless-lb-fe-deployment-name", "", "Name of stateless-lb-fe deployment in trench-a")
109+
flag.StringVar(&config.ipFamily, "ip-family", "", "IP Family")
89110
}
90111

91112
func TestE2e(t *testing.T) {
@@ -102,30 +123,30 @@ var _ = BeforeSuite(func() {
102123
Expect(err).ToNot(HaveOccurred())
103124

104125
trafficGeneratorHost = &utils.TrafficGeneratorHost{
105-
TrafficGeneratorCommand: trafficGeneratorCMD,
126+
TrafficGeneratorCommand: config.trafficGeneratorCMD,
106127
}
107128
trafficGenerator = &utils.MConnect{
108129
NConn: 400,
109130
}
110131

111-
cmd := exec.Command(script, "init")
132+
cmd := exec.Command(config.script, "init")
112133
var stderr bytes.Buffer
113134
cmd.Stderr = &stderr
114135
err = cmd.Run()
115136
Expect(stderr.String()).To(BeEmpty())
116137
Expect(err).ToNot(HaveOccurred())
117138

118-
deploymentTargetA, err := clientset.AppsV1().Deployments(namespace).Get(context.Background(), targetADeploymentName, metav1.GetOptions{})
139+
deploymentTargetA, err := clientset.AppsV1().Deployments(config.k8sNamespace).Get(context.Background(), config.targetADeploymentName, metav1.GetOptions{})
119140
Expect(err).ToNot(HaveOccurred())
120141
numberOfTargetA = int(*deploymentTargetA.Spec.Replicas)
121142

122-
deploymentTargetB, err := clientset.AppsV1().Deployments(namespace).Get(context.Background(), targetADeploymentName, metav1.GetOptions{})
143+
deploymentTargetB, err := clientset.AppsV1().Deployments(config.k8sNamespace).Get(context.Background(), config.targetADeploymentName, metav1.GetOptions{})
123144
Expect(err).ToNot(HaveOccurred())
124145
numberOfTargetB = int(*deploymentTargetB.Spec.Replicas)
125146
})
126147

127148
var _ = AfterSuite(func() {
128-
cmd := exec.Command(script, "end")
149+
cmd := exec.Command(config.script, "end")
129150
var stderr bytes.Buffer
130151
cmd.Stderr = &stderr
131152
err := cmd.Run()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-traffic-generator-cmd="docker exec -i {trench}"
2+
-script="./environment/kind-helm/dualstack/test.sh"
3+
-k8s-namespace="red"
4+
-target-a-deployment-name="target-a"
5+
-trench-a="trench-a"
6+
-attractor-a-1="attractor-a"
7+
-conduit-a-1="load-balancer"
8+
-stream-a-I="stream-a"
9+
-stream-a-II="stream-b"
10+
-flow-a-z-tcp=""
11+
-flow-a-z-tcp-destination-port-0=4000
12+
-flow-a-z-udp=""
13+
-flow-a-z-udp-destination-port-0=4003
14+
-flow-a-x-tcp=""
15+
-flow-a-x-tcp-destination-port-0=4001
16+
-vip-1-v4="20.0.0.1"
17+
-vip-1-v6="[2000::1]"
18+
-target-b-deployment-name="target-b"
19+
-trench-b="trench-b"
20+
-conduit-b-1="load-balancer"
21+
-stream-b-I="stream-a"
22+
-vip-2-v4="60.0.0.150"
23+
-vip-2-v6="[6000::150]"
24+
-stateless-lb-fe-deployment-name="load-balancer-trench-a"
25+
-ip-family="dualstack"

0 commit comments

Comments
 (0)