m/test/e2e/connectivity: add connectivity tester

This adds a connectivity testing framework. It uses pod agents and
communicates with them over stdio. This is used to implement a simple
smoke test and will later be used to test network policy controllers.

Change-Id: If40673a91336dbe3a7a383bf2e9d17736fad3bdc
Reviewed-on: https://review.monogon.dev/c/monogon/+/3756
Reviewed-by: Jan Schär <jan@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/test/e2e/suites/kubernetes/run_test.go b/metropolis/test/e2e/suites/kubernetes/run_test.go
index 0acc473..939c663 100644
--- a/metropolis/test/e2e/suites/kubernetes/run_test.go
+++ b/metropolis/test/e2e/suites/kubernetes/run_test.go
@@ -30,6 +30,7 @@
 	common "source.monogon.dev/metropolis/node"
 	apb "source.monogon.dev/metropolis/proto/api"
 	cpb "source.monogon.dev/metropolis/proto/common"
+	"source.monogon.dev/metropolis/test/e2e/connectivity"
 	mlaunch "source.monogon.dev/metropolis/test/launch"
 	"source.monogon.dev/metropolis/test/localregistry"
 	"source.monogon.dev/metropolis/test/util"
@@ -284,7 +285,7 @@
 		}
 	}()
 
-	clientSet, _, err := cluster.GetKubeClientSet()
+	clientSet, restConfig, err := cluster.GetKubeClientSet()
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -371,6 +372,26 @@
 			return fmt.Errorf("pod is not ready: %s", errorMsg.String())
 		}
 	})
+	t.Run("Connectivity Smoke Tests", func(t *testing.T) {
+		ct := connectivity.SetupTest(t, &connectivity.TestSpec{
+			Name:       "connectivity-smoke",
+			ClientSet:  clientSet,
+			RESTConfig: restConfig,
+			NumPods:    2,
+			ExtraPodConfig: func(i int, pod *corev1.Pod) {
+				// Spread pods out over nodes to test inter-node network
+				pod.Labels = make(map[string]string)
+				pod.Labels["name"] = "connectivity-smoketest"
+				pod.Spec.TopologySpreadConstraints = []corev1.TopologySpreadConstraint{{
+					MaxSkew:           1,
+					TopologyKey:       "kubernetes.io/hostname",
+					WhenUnsatisfiable: corev1.DoNotSchedule,
+					LabelSelector:     metav1.SetAsLabelSelector(pod.Labels),
+				}}
+			},
+		})
+		ct.TestPodConnectivity(t, 0, 1, 1234, connectivity.ExpectedSuccess)
+	})
 	for _, runtimeClass := range []string{"runc", "gvisor"} {
 		statefulSetName := fmt.Sprintf("test-statefulset-%s", runtimeClass)
 		util.TestEventual(t, fmt.Sprintf("StatefulSet with %s tests", runtimeClass), ctx, smallTestTimeout, func(ctx context.Context) error {