diff --git a/CHANGELOG.md b/CHANGELOG.md index 701bbef..daf13b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,34 @@ -## Version (0.0.0) -### Releshed/Unreleased -### Date +# Changelog -Changes: -- List of changes +All notable changes to this project will be documented in this file. -Improvements: -- List of improvements +## Table of Contents -Bug Fixes: -- NA +- [2.0.2](#202) +- [2.0.1](#201) +- [2.0.0](#200) +- [0.1.0](#010) ---- \ No newline at end of file +--- + +## `2.0.2` + +- integrate e2e tests with network policies +- fix a bug in udp testing + +## `2.0.1` + +- fix release naming + +## `2.0.0` + +- complete rewrite of the tool in Go, with unit and integration tests +- leverages the ephemeral container support in Kubernetes > v1.25 +- test case(s) are written in YAML +- support for Pods, StatefulSets, DaemonSets and Deployments which are directly referred through their names in the test suites +- artifacts are available for download + +## `0.1.0` + +- initial release +- no artifacts available \ No newline at end of file diff --git a/e2e/clusters/gke-dataplanev2/main.tf b/e2e/clusters/gke-dataplanev2/main.tf index 3a211ac..f880d54 100644 --- a/e2e/clusters/gke-dataplanev2/main.tf +++ b/e2e/clusters/gke-dataplanev2/main.tf @@ -13,7 +13,7 @@ provider "google" { resource "google_container_cluster" "e2etest" { name = var.cluster_name - initial_node_count = 3 + initial_node_count = 4 datapath_provider = var.use_dataplanev2 ? "ADVANCED_DATAPATH" : null ip_allocation_policy {} node_config { diff --git a/e2e/clusters/gke-vpc/main.tf b/e2e/clusters/gke-vpc/main.tf index 3a211ac..dc72edb 100644 --- a/e2e/clusters/gke-vpc/main.tf +++ b/e2e/clusters/gke-vpc/main.tf @@ -13,11 +13,18 @@ provider "google" { resource "google_container_cluster" "e2etest" { name = var.cluster_name - initial_node_count = 3 - datapath_provider = var.use_dataplanev2 ? "ADVANCED_DATAPATH" : null + initial_node_count = 4 + addons_config { + network_policy_config { + disabled = false + } + } + network_policy { + enabled = true + } ip_allocation_policy {} node_config { - machine_type = "e2-medium" + machine_type = "e2-standard-2" } release_channel { diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index c8e769a..2331491 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -177,8 +177,33 @@ func createTestDestroy(t *testing.T, gc helpers.GenericCluster) { if err != nil { t.Fatal(err) } - // run the tests + // run the tests without network policies + runTests(ctx, t, svc, netAssertTestCases) + + if gc.SkipNetPolTests() { + return + } + + // create the network policies + k8s.KubectlApply(t, options, "./manifests/networkpolicies.yaml") + + // read the tests again for a fresh start + netAssertTestCases, err = data.ReadTestsFromFile(testCasesFile) + if err != nil { + t.Fatal(err) + } + + // set the exit to 1 since this time the network policies will block the traffic + for _, tc := range netAssertTestCases { + tc.ExitCode = 1 + } + + // run the tests with network policies + runTests(ctx, t, svc, netAssertTestCases) +} + +func runTests(ctx context.Context, t *testing.T, svc *kubeops.Service, netAssertTestCases data.Tests) { lg := logger.NewHCLogger("INFO", "netassertv2-e2e", os.Stdout) testRunner := engine.New(svc, lg) diff --git a/e2e/helpers/common.go b/e2e/helpers/common.go index 838a40f..4b54178 100644 --- a/e2e/helpers/common.go +++ b/e2e/helpers/common.go @@ -14,4 +14,5 @@ type GenericCluster interface { Create(t *testing.T) Destroy(t *testing.T) KubeConfigGet() string + SkipNetPolTests() bool } diff --git a/e2e/helpers/eks.go b/e2e/helpers/eks.go index 0f98620..a00b2af 100644 --- a/e2e/helpers/eks.go +++ b/e2e/helpers/eks.go @@ -4,6 +4,7 @@ import ( "context" "os" "testing" + "time" "github.com/controlplaneio/netassert/v2/internal/kubeops" "github.com/controlplaneio/netassert/v2/internal/logger" @@ -110,6 +111,9 @@ func (g *EKSCluster) installCalico(t *testing.T) { if _, err := terraform.InitAndApplyE(t, newTFOptions); err != nil { t.Fatalf("failed to run terraform init and apply: %s", err) } + + svc.Log.Info("Sleeping 20 minutes so connectivity from the cluster to the Internet is restored") + time.Sleep(20 * time.Minute) } func (g *EKSCluster) Destroy(t *testing.T) { @@ -121,3 +125,7 @@ func (g *EKSCluster) Destroy(t *testing.T) { func (g *EKSCluster) KubeConfigGet() string { return g.kubeConfigPath } + +func (g *EKSCluster) SkipNetPolTests() bool { + return g.networkMode != Calico +} diff --git a/e2e/helpers/gke.go b/e2e/helpers/gke.go index e074bf0..5e47bd4 100644 --- a/e2e/helpers/gke.go +++ b/e2e/helpers/gke.go @@ -60,3 +60,7 @@ func (g *GKECluster) Destroy(t *testing.T) { func (g *GKECluster) KubeConfigGet() string { return g.kubeConfigPath } + +func (g *GKECluster) SkipNetPolTests() bool { + return false // network policies are supported by all gke cluster configurations +} diff --git a/e2e/manifests/networkpolicies.yaml b/e2e/manifests/networkpolicies.yaml new file mode 100644 index 0000000..a2d79a8 --- /dev/null +++ b/e2e/manifests/networkpolicies.yaml @@ -0,0 +1,70 @@ +--- +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + namespace: fluentd + name: fluentd-elasticsearch +spec: + podSelector: + matchLabels: + name: fluentd-elasticsearch + ingress: +--- +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + namespace: echoserver + name: echoserver +spec: + podSelector: + matchLabels: + app: echoserver + ingress: +--- +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + namespace: busybox + name: busybox +spec: + podSelector: + matchLabels: + app: busybox + policyTypes: + - Ingress + - Egress + ingress: + egress: +--- +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + namespace: pod1 + name: pod1 +spec: + podSelector: + matchLabels: + name: pod1 + ingress: +--- +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + namespace: pod2 + name: pod2 +spec: + podSelector: + matchLabels: + name: pod2 + ingress: +--- +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + namespace: web + name: nginx +spec: + podSelector: + matchLabels: + app: nginx + ingress: \ No newline at end of file diff --git a/e2e/manifests/pod1-pod2.yaml b/e2e/manifests/pod1-pod2.yaml index 1a05e34..6da47fd 100644 --- a/e2e/manifests/pod1-pod2.yaml +++ b/e2e/manifests/pod1-pod2.yaml @@ -15,6 +15,8 @@ kind: Pod metadata: name: pod2 namespace: pod2 + labels: + name: pod2 spec: containers: - name: webserver @@ -27,6 +29,8 @@ kind: Pod metadata: name: pod1 namespace: pod1 + labels: + name: pod1 spec: containers: - name: busybox diff --git a/internal/engine/run_udp.go b/internal/engine/run_udp.go index 268da4c..ec52d8a 100644 --- a/internal/engine/run_udp.go +++ b/internal/engine/run_udp.go @@ -12,8 +12,10 @@ import ( ) const ( - defaultNetInt = `eth0` // default network interface - defaultSnapLen = 1024 // default size of the packet snap length + defaultNetInt = `eth0` // default network interface + defaultSnapLen = 1024 // default size of the packet snap length + ephemeralContainersExtraSeconds = 23 // fixed extra time given for the ephemeral containers to come online + attemptsMultiplier = 3 // increase the attempts to ensure that we send three times the packets ) // RunUDPTest - runs a UDP test @@ -114,7 +116,7 @@ func (e *Engine) RunUDPTest( string(te.Protocol), te.Attempts, networkInterface, - te.TimeoutSeconds+5, // add 5 seconds for the Container to come online + te.TimeoutSeconds, ) if err != nil { return fmt.Errorf("failed to build sniffer ephemeral container for test %s: %w", te.Name, err) @@ -128,7 +130,7 @@ func (e *Engine) RunUDPTest( strconv.Itoa(te.TargetPort), string(te.Protocol), msg, - te.Attempts*3, // increase the attempts to ensure that we send three times the packets + te.Attempts*attemptsMultiplier, ) if err != nil { return fmt.Errorf("unable to build ephemeral scanner container for test %s: %w", te.Name, err) @@ -152,7 +154,7 @@ func (e *Engine) RunUDPTest( exitCodeSnifferCtr, err := e.Service.GetExitStatusOfEphemeralContainer( ctx, snifferContainerName, - time.Duration(te.TimeoutSeconds)*time.Second, + time.Duration(te.TimeoutSeconds+ephemeralContainersExtraSeconds)*time.Second, dstPod.Name, dstPod.Namespace, ) @@ -174,7 +176,7 @@ func (e *Engine) RunUDPTest( // get the exit status of the scanner container exitCodeScanner, err := e.Service.GetExitStatusOfEphemeralContainer( ctx, scannerContainerName, - time.Duration(te.TimeoutSeconds+10)*time.Second, + time.Duration(te.TimeoutSeconds+ephemeralContainersExtraSeconds)*time.Second, srcPod.Name, srcPod.Namespace, )