}
func (s *KindSuite) deletePod(namespace string, podName string) error {
+ delete(s.CurrentlyRunning, podName)
return s.ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), podName, metav1.DeleteOptions{GracePeriodSeconds: int64Ptr(0)})
}
}
func (s *KindSuite) DeployPod(pod *Pod) {
- pod.suite = s
- s.CurrentlyRunning = append(s.CurrentlyRunning, pod.Name)
pod.CreatedPod = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: s.Namespace,
// Create the Pod
_, err := s.ClientSet.CoreV1().Pods(s.Namespace).Create(context.TODO(), pod.CreatedPod, metav1.CreateOptions{})
s.AssertNil(err)
+ s.CurrentlyRunning[pod.Name] = pod
s.Log("Pod '%s' created", pod.Name)
// Get IP
s.Log("Obtaining IP from '%s'", pod.Name)
+ pod.IpAddress = ""
counter := 1
for pod.IpAddress == "" {
pod.CreatedPod, err = s.ClientSet.CoreV1().Pods(s.Namespace).Get(context.TODO(), pod.Name, metav1.GetOptions{})
"context"
"os"
"os/exec"
+ "slices"
"text/template"
- "time"
. "fd.io/hs-test/infra/common"
+ "gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/remotecommand"
)
Image string
ContainerName string
Worker string
+ Namespace string
IpAddress string
CreatedPod *corev1.Pod
}
-// Sets pod names, image names, namespace name
+type Image struct {
+ Name string `yaml:"name"`
+}
+type Container struct {
+ Name string `yaml:"name"`
+}
+type Worker struct {
+ Name string `yaml:"name"`
+}
+type Namespace struct {
+ Name string `yaml:"name"`
+}
+type PodYaml struct {
+ Name string `yaml:"name"`
+ Image []Image `yaml:"image"`
+ Container []Container `yaml:"container"`
+ Worker []Worker `yaml:"worker"`
+ Namespace []Namespace `yaml:"namespace"`
+}
+type Config struct {
+ Pods []PodYaml `yaml:"pods"`
+}
+
+func (s *KindSuite) LoadPodConfigs() {
+ data, err := os.ReadFile("kubernetes/pod-definitions.yaml")
+ s.AssertNil(err)
+
+ var config Config
+ err = yaml.Unmarshal(data, &config)
+ s.AssertNil(err)
+
+ for _, podData := range config.Pods {
+ newPod(s, podData)
+ }
+}
+
+func newPod(suite *KindSuite, input PodYaml) (*Pod, error) {
+ var pod = new(Pod)
+ pod.suite = suite
+ pod.Name = input.Name + suite.Ppid
+ pod.Image = input.Image[0].Name
+ pod.ContainerName = input.Container[0].Name
+ pod.Worker = input.Worker[0].Name
+ pod.Namespace = input.Namespace[0].Name + suite.Ppid
+
+ if suite.AllPods == nil {
+ suite.AllPods = make(map[string]*Pod)
+ suite.Namespace = pod.Namespace
+ }
+
+ suite.AllPods[pod.Name] = pod
+ if !slices.Contains(suite.images, pod.Image) {
+ suite.images = append(suite.images, pod.Image)
+ }
+
+ return pod, nil
+}
+
func (s *KindSuite) initPods() {
- wrk1 := "kind-worker"
- wrk2 := "kind-worker2"
- vppImg := "hs-test/vpp:latest"
- nginxLdpImg := "hs-test/nginx-ldp:latest"
- abImg := "hs-test/ab:latest"
- clientCont := "client"
- serverCont := "server"
-
- // TODO: load from file
- s.images = append(s.images, vppImg, nginxLdpImg, abImg)
- s.Namespace = "namespace" + s.Ppid
-
- s.Pods.ClientGeneric = new(Pod)
- s.Pods.ClientGeneric.Name = "client" + s.Ppid
- s.Pods.ClientGeneric.Image = vppImg
- s.Pods.ClientGeneric.ContainerName = clientCont
- s.Pods.ClientGeneric.Worker = wrk1
-
- s.Pods.ServerGeneric = new(Pod)
- s.Pods.ServerGeneric.Name = "server" + s.Ppid
- s.Pods.ServerGeneric.Image = vppImg
- s.Pods.ServerGeneric.ContainerName = serverCont
- s.Pods.ServerGeneric.Worker = wrk2
-
- s.Pods.Ab = new(Pod)
- s.Pods.Ab.Name = "ab" + s.Ppid
- s.Pods.Ab.Image = abImg
- s.Pods.Ab.ContainerName = clientCont
- s.Pods.Ab.Worker = wrk1
-
- s.Pods.Nginx = new(Pod)
- s.Pods.Nginx.Name = "nginx-ldp" + s.Ppid
- 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
+ s.Pods.Ab = s.getPodsByName("ab")
+ s.Pods.ClientGeneric = s.getPodsByName("client-generic")
+ s.Pods.ServerGeneric = s.getPodsByName("server-generic")
+ s.Pods.Nginx = s.getPodsByName("nginx-ldp")
+ s.Pods.NginxProxy = s.getPodsByName("nginx-proxy")
+}
+
+func (s *KindSuite) getPodsByName(podName string) *Pod {
+ return s.AllPods[podName+s.Ppid]
}
func (pod *Pod) CopyToPod(namespace string, src string, dst string) {
pod.suite.AssertNil(err, string(out))
}
-func (pod *Pod) Exec(command []string) (string, error) {
+func (pod *Pod) Exec(ctx context.Context, command []string) (string, error) {
var stdout, stderr bytes.Buffer
// Prepare the request
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,
err = template.Execute(f, values)
pod.suite.AssertNil(err, err)
-
err = f.Close()
pod.suite.AssertNil(err, err)
package hst_kind
import (
+ "context"
"fmt"
"reflect"
"regexp"
Config *rest.Config
Namespace string
KubeconfigPath string
- CurrentlyRunning []string
+ CurrentlyRunning map[string]*Pod
images []string
+ AllPods map[string]*Pod
Pods struct {
ServerGeneric *Pod
ClientGeneric *Pod
NginxProxy *Pod
Ab *Pod
}
+ MainContext context.Context
}
var kindTests = map[string][]func(s *KindSuite){}
}
func (s *KindSuite) SetupTest() {
+ s.MainContext = context.Background()
s.HstCommon.SetupTest()
}
Fail(message, callerSkip...)
})
+ s.CurrentlyRunning = make(map[string]*Pod)
+ s.LoadPodConfigs()
s.initPods()
s.loadDockerImages()
-
var err error
if *SudoUser == "root" {
s.KubeconfigPath = "/.kube/config"
if len(s.CurrentlyRunning) != 0 {
s.Log("Removing:")
for _, pod := range s.CurrentlyRunning {
- s.Log(" %s", pod)
- s.deletePod(s.Namespace, pod)
+ s.Log(" %s", pod.Name)
+ s.deletePod(s.Namespace, pod.Name)
}
}
}
func (s *KindSuite) TeardownSuite() {
s.HstCommon.TeardownSuite()
+ if len(s.CurrentlyRunning) == 0 {
+ return
+ }
s.Log("Removing:\n %s", s.Namespace)
s.AssertNil(s.deleteNamespace(s.Namespace))
}
// 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.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c",
+ o, _ := s.Pods.ServerGeneric.Exec(context.TODO(), []string{"/bin/bash", "-c",
"ldd /usr/lib/libvcl_ldpreload.so"})
match := regex.FindStringSubmatch(o)
"fi\n"+
"done", version)
for _, pod := range pods {
- pod.Exec([]string{"/bin/bash", "-c", cmd})
+ pod.Exec(context.TODO(), []string{"/bin/bash", "-c", cmd})
}
} else {
}
func (s *KindSuite) CreateNginxProxyConfig(pod *Pod) {
- pod.Exec([]string{"/bin/bash", "-c", "mkdir -p /tmp/nginx"})
+ pod.Exec(context.TODO(), []string{"/bin/bash", "-c", "mkdir -p /tmp/nginx"})
values := struct {
Workers uint8
LogPrefix string
package main
import (
+ "context"
+ "errors"
"time"
. "fd.io/hs-test/infra/kind"
const ldp string = "LD_PRELOAD=/usr/lib/libvcl_ldpreload.so"
func KindIperfVclTest(s *KindSuite) {
+ ctx, cancel := context.WithTimeout(s.MainContext, time.Second*30)
+ defer cancel()
s.DeployPod(s.Pods.ClientGeneric)
s.DeployPod(s.Pods.ServerGeneric)
- _, err := s.Pods.ClientGeneric.Exec([]string{"/bin/bash", "-c", VclConfIperf})
+ _, err := s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", VclConfIperf})
s.AssertNil(err)
- _, err = s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c", VclConfIperf})
+ _, err = s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c", VclConfIperf})
s.AssertNil(err)
s.FixVersionNumber(s.Pods.ClientGeneric, s.Pods.ServerGeneric)
- o, err := s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c",
+ o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c",
vcl + " " + ldp + " iperf3 -s -D -4"})
s.AssertNil(err, o)
- o, err = s.Pods.ClientGeneric.Exec([]string{"/bin/bash", "-c",
+ o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c",
vcl + " " + ldp + " iperf3 -l 1460 -b 10g -c " + s.Pods.ServerGeneric.IpAddress})
s.Log(o)
s.AssertNil(err)
}
func NginxRpsTest(s *KindSuite) {
+ ctx, cancel := context.WithCancel(s.MainContext)
+ defer cancel()
+
s.DeployPod(s.Pods.Nginx)
s.DeployPod(s.Pods.Ab)
s.CreateNginxConfig(s.Pods.Nginx)
- out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", VclConfNginx})
+ out, err := s.Pods.Nginx.Exec(ctx, []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)
+ out, err := s.Pods.Nginx.Exec(ctx, []string{"/bin/bash", "-c", "nginx -c /nginx.conf"})
+ if !errors.Is(err, context.Canceled) {
+ 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"})
+ out, err = s.Pods.Ab.Exec(ctx, []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) {
+ ctx, cancel := context.WithCancel(s.MainContext)
+ defer cancel()
+
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})
+ out, err := s.Pods.Nginx.Exec(ctx, []string{"/bin/bash", "-c", VclConfNginx})
s.AssertNil(err, out)
- out, err = s.Pods.NginxProxy.Exec([]string{"/bin/bash", "-c", VclConfNginx})
+ out, err = s.Pods.NginxProxy.Exec(ctx, []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)
+ out, err := s.Pods.Nginx.Exec(ctx, []string{"/bin/bash", "-c", ldp + " " + vcl + " nginx -c /nginx.conf"})
+ if !errors.Is(err, context.Canceled) {
+ s.AssertNil(err, out)
+ }
}()
go func() {
defer GinkgoRecover()
- out, err := s.Pods.NginxProxy.Exec([]string{"/bin/bash", "-c", "nginx -c /nginx.conf"})
- s.AssertNil(err, out)
+ out, err := s.Pods.NginxProxy.Exec(ctx, []string{"/bin/bash", "-c", "nginx -c /nginx.conf"})
+ if !errors.Is(err, context.Canceled) {
+ s.AssertNil(err, out)
+ }
}()
// wait for nginx to start up
time.Sleep(time.Second * 2)
- out, err = s.Pods.ClientGeneric.Exec([]string{"curl", "-v", "--noproxy", "'*'", "--insecure", "http://" + s.Pods.NginxProxy.IpAddress + ":8080/64B.json"})
+ out, err = s.Pods.ClientGeneric.Exec(ctx, []string{"curl", "-v", "--noproxy", "'*'", "--insecure", "http://" + s.Pods.NginxProxy.IpAddress + ":8080/64B.json"})
s.Log(out)
s.AssertNil(err)
}
--- /dev/null
+definitions:
+ image-names:
+ - image: &hs-test
+ name: "hs-test/vpp:latest"
+ - image: &nginx-ldp
+ name: "hs-test/nginx-ldp:latest"
+ - image: &ab
+ name: "hs-test/ab:latest"
+
+ container-names:
+ - container: &client
+ name: "client"
+ - container: &server
+ name: "server"
+
+ namespace-names:
+ - namespace: &defaultNs
+ name: "hs-test"
+
+ worker-names:
+ - worker: &worker1
+ name: "kind-worker"
+ - worker: &worker2
+ name: "kind-worker2"
+
+pods:
+ - name: "client-generic"
+ image:
+ - <<: *hs-test
+ container:
+ - <<: *client
+ worker:
+ - <<: *worker1
+ namespace:
+ - <<: *defaultNs
+
+ - name: "server-generic"
+ image:
+ - <<: *hs-test
+ container:
+ - <<: *server
+ worker:
+ - <<: *worker2
+ namespace:
+ - <<: *defaultNs
+
+ - name: "ab"
+ image:
+ - <<: *ab
+ container:
+ - <<: *client
+ worker:
+ - <<: *worker1
+ namespace:
+ - <<: *defaultNs
+
+ - name: "nginx-ldp"
+ image:
+ - <<: *nginx-ldp
+ container:
+ - <<: *server
+ worker:
+ - <<: *worker2
+ namespace:
+ - <<: *defaultNs
+
+ - name: "nginx-proxy"
+ image:
+ - <<: *nginx-ldp
+ container:
+ - <<: *server
+ worker:
+ - <<: *worker2
+ namespace:
+ - <<: *defaultNs