hs-test: add nginx mirroring KinD test, cleanup 87/43387/4
authorAdrian Villin <[email protected]>
Fri, 25 Jul 2025 14:11:20 +0000 (16:11 +0200)
committerFlorin Coras <[email protected]>
Tue, 29 Jul 2025 16:46:31 +0000 (16:46 +0000)
Type: test

Change-Id: I15e145023226ea0d442f69e42da4cdc586366873
Signed-off-by: Adrian Villin <[email protected]>
extras/hs-test/infra/kind/deployment.go
extras/hs-test/infra/kind/pod.go
extras/hs-test/infra/kind/suite_kind.go
extras/hs-test/infra/kind/utils.go
extras/hs-test/kind_test.go
extras/hs-test/kubernetes/setupCluster.sh

index 6404056..20fc6c8 100644 (file)
@@ -49,6 +49,7 @@ func (s *KindSuite) deleteNamespace(namespace string) error {
 }
 
 func (s *KindSuite) DeployPod(pod *Pod) {
+       pod.suite = s
        s.CurrentlyRunning = append(s.CurrentlyRunning, pod.Name)
        pod.CreatedPod = &corev1.Pod{
                ObjectMeta: metav1.ObjectMeta{
@@ -100,5 +101,5 @@ func (s *KindSuite) DeployPod(pod *Pod) {
                }
        }
 
-       s.Log("IP: %s", pod.IpAddress)
+       s.Log("IP: %s\n", pod.IpAddress)
 }
index 1b37047..f323130 100644 (file)
@@ -1,8 +1,20 @@
 package hst_kind
 
-import corev1 "k8s.io/api/core/v1"
+import (
+       "bytes"
+       "context"
+       "os"
+       "os/exec"
+       "text/template"
+       "time"
+
+       . "fd.io/hs-test/infra/common"
+       corev1 "k8s.io/api/core/v1"
+       "k8s.io/client-go/tools/remotecommand"
+)
 
 type Pod struct {
+       suite         *KindSuite
        Name          string
        Image         string
        ContainerName string
@@ -21,6 +33,7 @@ func (s *KindSuite) initPods() {
        clientCont := "client"
        serverCont := "server"
 
+       // TODO: load from file
        s.images = append(s.images, vppImg, nginxLdpImg, abImg)
        s.Namespace = "namespace" + s.Ppid
 
@@ -47,4 +60,74 @@ func (s *KindSuite) initPods() {
        s.Pods.Nginx.Image = nginxLdpImg
        s.Pods.Nginx.ContainerName = serverCont
        s.Pods.Nginx.Worker = wrk2
+
+       s.Pods.NginxProxy = new(Pod)
+       s.Pods.NginxProxy.Name = "nginx-proxy" + s.Ppid
+       s.Pods.NginxProxy.Image = nginxLdpImg
+       s.Pods.NginxProxy.ContainerName = serverCont
+       s.Pods.NginxProxy.Worker = wrk2
+}
+
+func (pod *Pod) CopyToPod(namespace string, src string, dst string) {
+       cmd := exec.Command("kubectl", "--kubeconfig="+pod.suite.KubeconfigPath, "cp", src, namespace+"/"+pod.Name+":"+dst)
+       out, err := cmd.CombinedOutput()
+       pod.suite.AssertNil(err, string(out))
+}
+
+func (pod *Pod) Exec(command []string) (string, error) {
+       var stdout, stderr bytes.Buffer
+
+       // Prepare the request
+       req := pod.suite.ClientSet.CoreV1().RESTClient().Post().
+               Resource("pods").
+               Name(pod.Name).
+               Namespace(pod.suite.Namespace).
+               SubResource("exec").
+               Param("container", pod.ContainerName).
+               Param("stdout", "true").
+               Param("stderr", "true").
+               Param("tty", "true")
+
+       for _, cmd := range command {
+               req = req.Param("command", cmd)
+       }
+       pod.suite.Log("%s: %s\n", pod.Name, command)
+
+       executor, err := remotecommand.NewSPDYExecutor(pod.suite.Config, "POST", req.URL())
+       if err != nil {
+               pod.suite.Log("Error creating executor: %s", err.Error())
+       }
+
+       ctx, cancel := context.WithTimeout(context.Background(), 500*time.Second)
+       defer cancel()
+
+       err = executor.StreamWithContext(ctx, remotecommand.StreamOptions{
+               Stdout: &stdout,
+               Stderr: &stderr,
+               Tty:    true,
+       })
+
+       output := stdout.String() + stderr.String()
+
+       if err != nil {
+               return output, err
+       }
+
+       return output, nil
+}
+
+func (pod *Pod) CreateConfigFromTemplate(targetConfigName string, templateName string, values any) {
+       template := template.Must(template.ParseFiles(templateName))
+
+       f, err := os.CreateTemp(LogDir, "hst-config")
+       pod.suite.AssertNil(err, err)
+       defer os.Remove(f.Name())
+
+       err = template.Execute(f, values)
+       pod.suite.AssertNil(err, err)
+
+       err = f.Close()
+       pod.suite.AssertNil(err, err)
+
+       pod.CopyToPod(pod.suite.Namespace, f.Name(), targetConfigName)
 }
index 45b24fc..1754853 100644 (file)
@@ -2,12 +2,10 @@ package hst_kind
 
 import (
        "fmt"
-       "os"
        "reflect"
        "regexp"
        "runtime"
        "strings"
-       "text/template"
 
        . "fd.io/hs-test/infra/common"
        . "github.com/onsi/ginkgo/v2"
@@ -30,12 +28,32 @@ type KindSuite struct {
                ServerGeneric *Pod
                ClientGeneric *Pod
                Nginx         *Pod
+               NginxProxy    *Pod
                Ab            *Pod
        }
 }
 
 var kindTests = map[string][]func(s *KindSuite){}
 
+const VclConfIperf = "echo \"vcl {\n" +
+       "rx-fifo-size 4000000\n" +
+       "tx-fifo-size 4000000\n" +
+       "app-scope-local\n" +
+       "app-scope-global\n" +
+       "app-socket-api abstract:vpp/session\n" +
+       "}\" > /vcl.conf"
+
+const VclConfNginx = "echo \"vcl {\n" +
+       "heapsize 64M\n" +
+       "rx-fifo-size 4000000\n" +
+       "tx-fifo-size 4000000\n" +
+       "segment-size 4000000000\n" +
+       "add-segment-size 4000000000\n" +
+       "event-queue-size 100000\n" +
+       "use-mq-eventfd\n" +
+       "app-socket-api abstract:vpp/session\n" +
+       "}\" > /vcl.conf"
+
 func RegisterKindTests(tests ...func(s *KindSuite)) {
        kindTests[GetTestFilename()] = tests
 }
@@ -74,6 +92,7 @@ func (s *KindSuite) SetupSuite() {
 func (s *KindSuite) TeardownTest() {
        s.HstCommon.TeardownTest()
        if len(s.CurrentlyRunning) != 0 {
+               s.Log("Removing:")
                for _, pod := range s.CurrentlyRunning {
                        s.Log("   %s", pod)
                        s.deletePod(s.Namespace, pod)
@@ -83,7 +102,7 @@ func (s *KindSuite) TeardownTest() {
 
 func (s *KindSuite) TeardownSuite() {
        s.HstCommon.TeardownSuite()
-       s.Log("   %s", s.Namespace)
+       s.Log("Removing:\n   %s", s.Namespace)
        s.AssertNil(s.deleteNamespace(s.Namespace))
 }
 
@@ -91,7 +110,7 @@ func (s *KindSuite) TeardownSuite() {
 // and searches for the first version string, then creates symlinks.
 func (s *KindSuite) FixVersionNumber(pods ...*Pod) {
        regex := regexp.MustCompile(`lib.*\.so\.([0-9]+\.[0-9]+)`)
-       o, _ := s.Exec(s.Pods.ServerGeneric, []string{"/bin/bash", "-c",
+       o, _ := s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c",
                "ldd /usr/lib/libvcl_ldpreload.so"})
        match := regex.FindStringSubmatch(o)
 
@@ -106,7 +125,7 @@ func (s *KindSuite) FixVersionNumber(pods ...*Pod) {
                        "fi\n"+
                        "done", version)
                for _, pod := range pods {
-                       s.Exec(pod, []string{"/bin/bash", "-c", cmd})
+                       pod.Exec([]string{"/bin/bash", "-c", cmd})
                }
 
        } else {
@@ -114,23 +133,7 @@ func (s *KindSuite) FixVersionNumber(pods ...*Pod) {
        }
 }
 
-func (s *KindSuite) CreateConfigFromTemplate(targetConfigName string, templateName string, values any) {
-       template := template.Must(template.ParseFiles(templateName))
-
-       f, err := os.CreateTemp(LogDir, "hst-config")
-       s.AssertNil(err, err)
-       defer os.Remove(f.Name())
-
-       err = template.Execute(f, values)
-       s.AssertNil(err, err)
-
-       err = f.Close()
-       s.AssertNil(err, err)
-
-       s.CopyToPod(s.Pods.Nginx.Name, s.Namespace, f.Name(), targetConfigName)
-}
-
-func (s *KindSuite) CreateNginxConfig() {
+func (s *KindSuite) CreateNginxConfig(pod *Pod) {
        values := struct {
                Workers uint8
                Port    uint16
@@ -138,13 +141,41 @@ func (s *KindSuite) CreateNginxConfig() {
                Workers: 1,
                Port:    8081,
        }
-       s.CreateConfigFromTemplate(
+       pod.CreateConfigFromTemplate(
                "/nginx.conf",
                "./resources/nginx/nginx.conf",
                values,
        )
 }
 
+func (s *KindSuite) CreateNginxProxyConfig(pod *Pod) {
+       pod.Exec([]string{"/bin/bash", "-c", "mkdir -p /tmp/nginx"})
+       values := struct {
+               Workers   uint8
+               LogPrefix string
+               Proxy     string
+               Server    string
+               Port      uint16
+               Upstream1 string
+               Upstream2 string
+               Upstream3 string
+       }{
+               Workers:   1,
+               LogPrefix: s.Pods.NginxProxy.Name,
+               Proxy:     s.Pods.NginxProxy.IpAddress,
+               Server:    s.Pods.Nginx.IpAddress,
+               Port:      8080,
+               Upstream1: "8081",
+               Upstream2: "8081",
+               Upstream3: "8081",
+       }
+       pod.CreateConfigFromTemplate(
+               "/nginx.conf",
+               "./resources/nginx/nginx_proxy_mirroring.conf",
+               values,
+       )
+}
+
 var _ = Describe("KindSuite", Ordered, ContinueOnFailure, Label("Perf"), func() {
        var s KindSuite
        BeforeAll(func() {
index d6f3719..ea82085 100644 (file)
@@ -1,62 +1,5 @@
 package hst_kind
 
-import (
-       "bytes"
-       "context"
-       "os/exec"
-       "time"
-
-       "k8s.io/client-go/tools/remotecommand"
-)
-
-func (s *KindSuite) CopyToPod(podName string, namespace string, src string, dst string) {
-       cmd := exec.Command("kubectl", "--kubeconfig="+s.KubeconfigPath, "cp", src, namespace+"/"+podName+":"+dst)
-       out, err := cmd.CombinedOutput()
-       s.AssertNil(err, string(out))
-}
-
-func (s *KindSuite) Exec(pod *Pod, command []string) (string, error) {
-       var stdout, stderr bytes.Buffer
-
-       // Prepare the request
-       req := s.ClientSet.CoreV1().RESTClient().Post().
-               Resource("pods").
-               Name(pod.Name).
-               Namespace(s.Namespace).
-               SubResource("exec").
-               Param("container", pod.ContainerName).
-               Param("stdout", "true").
-               Param("stderr", "true").
-               Param("tty", "true")
-
-       for _, cmd := range command {
-               req = req.Param("command", cmd)
-       }
-       s.Log("%s: %s", pod.Name, command)
-
-       executor, err := remotecommand.NewSPDYExecutor(s.Config, "POST", req.URL())
-       if err != nil {
-               s.Log("Error creating executor: %s", err.Error())
-       }
-
-       ctx, cancel := context.WithTimeout(context.Background(), 500*time.Second)
-       defer cancel()
-
-       err = executor.StreamWithContext(ctx, remotecommand.StreamOptions{
-               Stdout: &stdout,
-               Stderr: &stderr,
-               Tty:    true,
-       })
-
-       output := stdout.String() + stderr.String()
-
-       if err != nil {
-               return output, err
-       }
-
-       return output, nil
-}
-
 func boolPtr(b bool) *bool {
        return &b
 }
index 0e0431d..bc09fb7 100644 (file)
@@ -8,7 +8,7 @@ import (
 )
 
 func init() {
-       RegisterKindTests(KindIperfVclTest, NginxRpsTest)
+       RegisterKindTests(KindIperfVclTest, NginxRpsTest, NginxProxyMirroringTest)
 }
 
 const vcl string = "VCL_CONFIG=/vcl.conf"
@@ -18,58 +18,70 @@ func KindIperfVclTest(s *KindSuite) {
        s.DeployPod(s.Pods.ClientGeneric)
        s.DeployPod(s.Pods.ServerGeneric)
 
-       vclConf := "echo \"vcl {\n" +
-               "rx-fifo-size 4000000\n" +
-               "tx-fifo-size 4000000\n" +
-               "app-scope-local\n" +
-               "app-scope-global\n" +
-               "app-socket-api abstract:vpp/session\n" +
-               "}\" > /vcl.conf"
-
-       _, err := s.Exec(s.Pods.ClientGeneric, []string{"/bin/bash", "-c", vclConf})
+       _, err := s.Pods.ClientGeneric.Exec([]string{"/bin/bash", "-c", VclConfIperf})
        s.AssertNil(err)
-       _, err = s.Exec(s.Pods.ServerGeneric, []string{"/bin/bash", "-c", vclConf})
+       _, err = s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c", VclConfIperf})
        s.AssertNil(err)
 
        s.FixVersionNumber(s.Pods.ClientGeneric, s.Pods.ServerGeneric)
 
-       o, err := s.Exec(s.Pods.ServerGeneric, []string{"/bin/bash", "-c",
+       o, err := s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c",
                vcl + " " + ldp + " iperf3 -s -D -4"})
        s.AssertNil(err, o)
-       output, err := s.Exec(s.Pods.ClientGeneric, []string{"/bin/bash", "-c",
+       o, err = s.Pods.ClientGeneric.Exec([]string{"/bin/bash", "-c",
                vcl + " " + ldp + " iperf3 -l 1460 -b 10g -c " + s.Pods.ServerGeneric.IpAddress})
-       s.Log(output)
+       s.Log(o)
        s.AssertNil(err)
 }
 
 func NginxRpsTest(s *KindSuite) {
        s.DeployPod(s.Pods.Nginx)
        s.DeployPod(s.Pods.Ab)
-       s.CreateNginxConfig()
-
-       vclConf := "echo \"vcl {\n" +
-               "heapsize 64M\n" +
-               "rx-fifo-size 4000000\n" +
-               "tx-fifo-size 4000000\n" +
-               "segment-size 4000000000\n" +
-               "add-segment-size 4000000000\n" +
-               "event-queue-size 100000\n" +
-               "use-mq-eventfd\n" +
-               "app-socket-api abstract:vpp/session\n" +
-               "}\" > /vcl.conf"
-
-       out, err := s.Exec(s.Pods.Nginx, []string{"/bin/bash", "-c", vclConf})
+       s.CreateNginxConfig(s.Pods.Nginx)
+
+       out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", VclConfNginx})
+       s.AssertNil(err, out)
+
+       go func() {
+               defer GinkgoRecover()
+               out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", ldp + " " + vcl + " nginx -c /nginx.conf"})
+               s.AssertNil(err, out)
+       }()
+
+       // wait for nginx to start up
+       time.Sleep(time.Second * 2)
+       out, err = s.Pods.Ab.Exec([]string{"ab", "-k", "-r", "-n", "1000000", "-c", "1000", "http://" + s.Pods.Nginx.IpAddress + ":8081/64B.json"})
+       s.Log(out)
+       s.AssertNil(err)
+}
+
+func NginxProxyMirroringTest(s *KindSuite) {
+       s.DeployPod(s.Pods.Nginx)
+       s.DeployPod(s.Pods.NginxProxy)
+       s.DeployPod(s.Pods.ClientGeneric)
+       s.CreateNginxConfig(s.Pods.Nginx)
+       s.CreateNginxProxyConfig(s.Pods.NginxProxy)
+
+       out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", VclConfNginx})
        s.AssertNil(err, out)
+       out, err = s.Pods.NginxProxy.Exec([]string{"/bin/bash", "-c", VclConfNginx})
+       s.AssertNil(err, out)
+
+       go func() {
+               defer GinkgoRecover()
+               out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", ldp + " " + vcl + " nginx -c /nginx.conf"})
+               s.AssertNil(err, out)
+       }()
 
        go func() {
                defer GinkgoRecover()
-               out, err := s.Exec(s.Pods.Nginx, []string{"/bin/bash", "-c", ldp + " " + vcl + " nginx -c /nginx.conf"})
+               out, err := s.Pods.NginxProxy.Exec([]string{"/bin/bash", "-c", "nginx -c /nginx.conf"})
                s.AssertNil(err, out)
        }()
 
        // wait for nginx to start up
        time.Sleep(time.Second * 2)
-       out, err = s.Exec(s.Pods.Ab, []string{"ab", "-k", "-r", "-n", "1000000", "-c", "1000", "http://" + s.Pods.Nginx.IpAddress + ":8081/64B.json"})
+       out, err = s.Pods.ClientGeneric.Exec([]string{"curl", "-v", "--noproxy", "'*'", "--insecure", "http://" + s.Pods.NginxProxy.IpAddress + ":8080/64B.json"})
        s.Log(out)
        s.AssertNil(err)
 }
index 3c176f6..4eba189 100755 (executable)
@@ -67,7 +67,7 @@ setup_master() {
   make -C $CALICOVPP_DIR kind-new-cluster N_KIND_WORKERS=2
   kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.3/manifests/tigera-operator.yaml
   make -C $CALICOVPP_DIR cherry-vpp FORCE=y BASE=origin/master VPP_DIR=$VPP_DIR
-  make build-vpp-release
+  make -C $VPP_DIR/extras/hs-test build-vpp-release
   make -C $CALICOVPP_DIR dev-kind
   make -C $CALICOVPP_DIR load-kind
   $CALICOVPP_DIR/yaml/overlays/dev/kustomize.sh up