**/test-run-*-*-*
# host stack test framework
-/extras/hs-test/vpp-data
-/extras/hs-test/hs-test
-/extras/hs-test/http_server
-/extras/hs-test/.build.ok
-/extras/hs-test/.build.cov.ok
-/extras/hs-test/.last_hst_ppid
-/extras/hs-test/summary/
-/extras/hs-test/.last_state_hash
-/extras/hs-test/.kind_deps.ok
-/extras/hs-test/.go_cache/
-/extras/hs-test/kubernetes/calico-config.yaml
-/extras/hs-test/kubernetes/.vars
+/test-c/hs-test/vpp-data
+/test-c/hs-test/hs-test
+/test-c/hs-test/http_server
+/test-c/hs-test/.build.ok
+/test-c/hs-test/.build.cov.ok
+/test-c/hs-test/.last_hst_ppid
+/test-c/hs-test/summary/
+/test-c/hs-test/.last_state_hash
+/test-c/hs-test/.go_cache/
+
+# kube-test
+/test-c/kube-test/vpp-data
+/test-c/kube-test/.build.ok
+/test-c/kube-test/.last_ppid
+/test-c/kube-test/summary/
+/test-c/kube-test/.last_state_hash
+/test-c/kube-test/.kube_deps.ok
+/test-c/kube-test/kubernetes/calico-config.yaml
+/test-c/kube-test/kubernetes/.vars
# ./configure
/CMakeFiles
-F: extras/hs-test
+F: test-c/hs-test
+
+Kube test framework
+I: kube-test
+F: test-c/kube-test
THE REST
I: misc
.PHONY: test-cov-hs
test-cov-hs: build-gcov
- @$(MAKE) CC=$(CC) -C extras/hs-test test-cov \
+ @$(MAKE) CC=$(CC) -C test-c/hs-test test-cov \
VPP_BUILD_DIR=$(BR)/build-vpp_gcov-native/vpp
.PHONY: test-cov-post-standalone
.PHONY: test-checkstyle
test-checkstyle:
@$(MAKE) -C test checkstyle-python-all
- @$(MAKE) -C extras/hs-test checkstyle-go
+ @$(MAKE) -C test-c/hs-test checkstyle-go
# Note: All python venv consolidated in test/Makefile, test/requirements*.txt
.PHONY: test-checkstyle-diff
.PHONY: cleanup-hst
cleanup-hst:
- $(MAKE) -C extras/hs-test cleanup-hst
+ $(MAKE) -C test-c/hs-test cleanup-hst
+
+.PHONY: cleanup-perf
+cleanup-perf:
+ $(MAKE) -C test-c/kube-test cleanup-perf
.PHONY: ctags
ctags: ctags.files
.PHONY: checkstyle-go
checkstyle-go:
- @$(MAKE) -C extras/hs-test checkstyle-go
+ @$(MAKE) -C test-c/hs-test checkstyle-go
+ @$(MAKE) -C test-c/kube-test checkstyle-go
.PHONY: fixstyle-go
fixstyle-go:
- @$(MAKE) -C extras/hs-test fixstyle-go
+ @$(MAKE) -C test-c/hs-test fixstyle-go
+ @$(MAKE) -C test-c/kube-test fixstyle-go
.PHONY: checkstyle-all
checkstyle-all: checkstyle-commit checkstyle checkstyle-python docs-spell checkstyle-go
-../../../extras/hs-test/README.rst
\ No newline at end of file
+../../../test-c/hs-test/README.rst
\ No newline at end of file
-export HS_ROOT=$(CURDIR)
-
-# sets WS_ROOT if called from extras/hs-test
-ifeq ($(WS_ROOT),)
-export WS_ROOT=$(HS_ROOT)/../..
-endif
-
-ifeq ($(VERBOSE),)
-VERBOSE=false
-endif
-
-ifeq ($(PERSIST),)
-PERSIST=false
-endif
-
-ifeq ($(UNCONFIGURE),)
-UNCONFIGURE=false
-endif
-
-ifeq ($(TEST),)
-TEST=all
-endif
-
-ifeq ($(TEST-HS),)
-TEST-HS=all
-endif
-
-ifeq ($(DEBUG),)
-DEBUG=false
-endif
-
-ifeq ($(CPUS),)
-CPUS=1
-endif
-
-ifeq ($(VPP_CPUS),)
-VPP_CPUS=1
-endif
-
-ifeq ($(PARALLEL),)
-PARALLEL=1
-endif
-
-ifeq ($(REPEAT),)
-REPEAT=0
-endif
-
-ifeq ($(CPU0),)
-CPU0=false
-endif
-
-ifeq ($(VPPSRC),)
-VPPSRC=$(shell pwd)/../..
-endif
-
-ifeq ($(UBUNTU_CODENAME),)
-UBUNTU_CODENAME=$(shell grep '^UBUNTU_CODENAME=' /etc/os-release | cut -f2- -d=)
-endif
-
-ifeq ($(ARCH),)
-ARCH=$(shell dpkg --print-architecture)
-endif
-
-ifeq ($(NO_COLOR),)
-VERBOSE=false
-endif
-
-ifeq ($(TIMEOUT),)
-TIMEOUT=5
-endif
-
-ifeq ($(GINKGO_TIMEOUT),)
-GINKGO_TIMEOUT=3h
-endif
-
-CORE_PATTERN := $(shell cat /proc/sys/kernel/core_pattern)
-CORE_VOLUME:=
-DOCKER_TTY:=
-
-ifeq ($(shell expr "$(CORE_PATTERN)" : '^/'), 1)
-CORE_VOLUME := -v $(CORE_PATTERN):$(CORE_PATTERN)
-endif
-
-ifeq ($(shell tty -s && echo $$?), 0)
-DOCKER_TTY := -it
-endif
-
-FORCE_BUILD?=true
-
-# privileged is needed for "ip netns" otherwise we are not able to create namespace
-DOCKER_CAPABILITIES:=--privileged
-DOCKER_DEVICES:=--device /dev/vhost-net:/dev/vhost-net --device /dev/net/tun:/dev/net/tun
-DOCKER_VOLUMES:=-v $(WS_ROOT):$(WS_ROOT) -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/hs-test:/tmp/hs-test \
- -v /etc/localtime:/etc/localtime:ro $(CORE_VOLUME) -v $(HS_ROOT)/.go_cache/mod:/root/go/pkg/mod \
- -v $(HS_ROOT)/.go_cache/build:/root/.cache/go-build
-DOCKER_PROXY:=-e HTTP_PROXY=$(HTTP_PROXY) -e HTTPS_PROXY=$(HTTPS_PROXY) -e NO_PROXY=$(NO_PROXY)
-
-.PHONY: help
-help:
- @echo "Make targets:"
- @echo " test - run tests"
- @echo " test-debug - run tests (vpp debug image)"
- @echo " test-leak - run memory leak tests (vpp debug image)"
- @echo " test-perf - run performance tests (requires a running cluster)"
- @echo " build - build test infra"
- @echo " build-cov - coverage build of VPP and Docker images"
- @echo " build-debug - build test infra (vpp debug image)"
- @echo " build-go - just build golang files"
- @echo " cluster-help - print info about KinD cluster setup (perf testing)"
- @echo " master-cluster - setup KinD cluster for performance testing (master CalicoVPP + VPP)"
- @echo " rebuild-master-cluster - rebuild VPP and update related pods without shutting down the cluster"
- @echo " release-cluster - setup KinD cluster for performance testing (latest CalicoVPP release)"
- @echo " checkstyle-go - check style of .go source files"
- @echo " fixstyle-go - format .go source files"
- @echo " cleanup-hst - removes all docker containers and namespaces from last test run"
- @echo " cleanup-perf - removes all kubernetes pods and namespaces from last test run"
- @echo " list-tests - list all tests"
- @echo " install-deps - install software dependencies"
- @echo " install-kind-deps - install software dependencies for cluster"
- @echo
- @echo "'make build' and 'make test' arguments:"
- @echo " UBUNTU_VERSION - ubuntu version for docker image"
- @echo " FORCE_BUILD=[true|false] - force docker image building"
- @echo
- @echo "'make test' specific arguments:"
- @echo " PERSIST=[true|false] - whether clean up topology and dockers after test"
- @echo " VERBOSE=[true|false] - verbose output"
- @echo " UNCONFIGURE=[true|false] - unconfigure selected test"
- @echo " DEBUG=[true|false] - attach VPP to GDB"
- @echo " TEST=[name1,name2...] - specific test(s) to run"
- @echo " SKIP=[name1,name2...] - specific test(s) to skip"
- @echo " CPUS=[n] - number of cpus to allocate to each non-VPP container (default = 1)"
- @echo " VPP_CPUS=[n] - number of cpus to allocate to each VPP container (default = 1)"
- @echo " VPPSRC=[path-to-vpp-src] - path to vpp source files (for gdb)"
- @echo " PARALLEL=[n] - number of test processes to spawn to run in parallel"
- @echo " REPEAT=[n] - repeat tests up to N times or until a failure occurs"
- @echo " CPU0=[true|false] - use cpu0"
- @echo " DRYRUN=[true|false] - set up containers but don't run tests"
- @echo " NO_COLOR=[true|false] - disables colorful Docker and Ginkgo output"
- @echo " TIMEOUT=[minutes] - test timeout override (5 minutes by default)"
- @echo " GINKGO_TIMEOUT=[Ns/m/h] - Ginkgo timeout override (3h by default)"
- @echo
- @echo "'make setup-cluster' arguments:"
- @echo " BASE=[master|latest] - build master CalicoVPP with master VPP or use latest release of CalicoVPP (default = latest)"
-
-.PHONY: list-tests
-list-tests:
- @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --seed=2 | head -n -1 | grep 'test.go' | \
- sed 's/^/* /; s/\(Suite\) /\1\//g'
-
-.PHONY: build-vpp-release
-build-vpp-release:
- @$(MAKE) -C ../.. build-release
-
-.PHONY: build-vpp-debug
-build-vpp-debug:
- @$(MAKE) -C ../.. build
-
-.PHONY: build-vpp-gcov
-build-vpp-gcov:
- @$(MAKE) -C ../.. build-gcov
-
-.build.ok: build
- @touch .build.ok
-
-.build.cov.ok: build-cov
- @touch .build.ok
-
-.build_debug.ok: build-debug
- @touch .build.ok
-
-.PHONY: test
-test: FORCE_BUILD=false
-test: .deps.ok .build.ok
- docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
- -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
- .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \
- --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \
- --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --cpu0=$(CPU0) \
- --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \
- --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \
- ./script/compress.sh $$?
-
-.PHONY: test-debug
-test-debug: FORCE_BUILD=false
-test-debug: .deps.ok .build_debug.ok
- docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
- -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
- .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \
- --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \
- --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --debug_build=true \
- --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \
- --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \
- ./script/compress.sh $$?
-
-.PHONY: wipe-lcov
-wipe-lcov:
- @lcov --zerocounters --directory $(WS_ROOT)/build-root/build-vpp_gcov-native/vpp
-
-.PHONY: test-cov
-test-cov: FORCE_BUILD=false
-test-cov: .deps.ok .build.cov.ok wipe-lcov
- -docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
- -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
- .$(HS_ROOT)/hs_test.sh --coverage=true --persist=$(PERSIST) --verbose=$(VERBOSE) \
- --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST-HS) --cpus=$(CPUS) \
- --vppsrc=$(VPPSRC) --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) \
- --timeout=$(TIMEOUT) --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \
- ./script/compress.sh $$?
- $(MAKE) -C ../.. test-cov-post-standalone HS_TEST=1
-
-.PHONY: test-leak
-test-leak: FORCE_BUILD=false
-test-leak: .deps.ok .build_debug.ok
- docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
- -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
- .$(HS_ROOT)/hs_test.sh --test=$(TEST) --debug_build=true --leak_check=true --vppsrc=$(VPPSRC) --timeout=$(TIMEOUT) \
- --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT);
-
-.PHONY: test-perf
-test-perf: FORCE_BUILD=false
-test-perf: .deps.ok .build.ok
- @bash ./hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \
- --test=$(TEST) --vppsrc=$(VPPSRC) --repeat=$(REPEAT) \
- --skip=$(SKIP) --no_color=$(NO_COLOR) --perf=true --timeout=$(TIMEOUT) \
- --ginkgo_timeout=$(GINKGO_TIMEOUT); \
- ./script/compress.sh $$?
-
-.PHONY: cluster-help
-cluster-help:
- @bash ./kubernetes/setup-cluster.sh help
-
-.PHONY: release-cluster
-release-cluster: .kind_deps.ok
- @bash ./kubernetes/setup-cluster.sh release-cluster
-
-.PHONY: master-cluster
-master-cluster: .kind_deps.ok
- @bash ./kubernetes/setup-cluster.sh master-cluster
-
-.PHONY: rebuild-master-cluster
-rebuild-master-cluster: .kind_deps.ok
- @bash ./kubernetes/setup-cluster.sh rebuild-master-cluster
-
-# this is executed in a container by hs-test.sh
-.PHONY: build-go
-build-go:
- go build --buildvcs=false ./tools/http_server
-
-.PHONY: build
-build: .deps.ok build-vpp-release
- @rm -f .build.ok
- bash ./script/build_hst.sh release $(FORCE_BUILD)
- @touch .build.ok
-
-.PHONY: build-cov
-build-cov: .deps.ok build-vpp-gcov
- @rm -f .build.cov.ok
- bash ./script/build_hst.sh gcov $(FORCE_BUILD)
- @touch .build.cov.ok
-
-.PHONY: build-debug
-build-debug: .deps.ok build-vpp-debug
- @rm -f .build.ok
- bash ./script/build_hst.sh debug $(FORCE_BUILD)
- @touch .build.ok
-
-.deps.ok:
- @$(MAKE) install-deps
-
-.kind_deps.ok:
- @$(MAKE) install-kind-deps
-
-.PHONY: install-kind-deps
-install-kind-deps: .deps.ok
- -@if ! command -v kind >/dev/null 2>&1; then \
- echo "Installing KinD"; \
- echo "Creating symlink from '$(HOME)/go/bin/kind' to '/usr/bin/kind'"; \
- sudo ln -s $(HOME)/go/bin/kind /usr/bin/kind; \
- else \
- echo "KinD is already installed. Skipping."; \
- fi
- @if ! command -v kubectl >/dev/null 2>&1; then \
- echo "kubectl not found. Installing kubectl..."; \
- sudo -E apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg; \
- curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \
- sudo -E chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \
- echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list; \
- sudo -E chmod 644 /etc/apt/sources.list.d/kubernetes.list; \
- sudo apt-get update && sudo apt-get install -y kubectl; \
- else \
- echo "kubectl is already installed. Skipping."; \
- fi
- @touch .kind_deps.ok
-
-.PHONY: install-deps
-install-deps:
- @rm -f .deps.ok
- @if [ -d "/usr/local/go" ]; then \
- echo "Go is already installed. You may have to update it manually if version < 1.23.10"; \
- go version; \
- else \
- echo "Installing Go 1.23"; \
- wget -t 2 https://go.dev/dl/go1.23.10.linux-$(ARCH).tar.gz -O /tmp/go1.23.10.linux-$(ARCH).tar.gz && sudo tar -C /usr/local -xzf /tmp/go1.23.10.linux-$(ARCH).tar.gz; \
- sudo ln -s /usr/local/go/bin/go /usr/bin/go ; \
- fi
- @sudo -E apt-get update
- @sudo -E apt-get install -y apt-transport-https ca-certificates curl software-properties-common \
- bridge-utils gpg
- @if [ ! -f /usr/share/keyrings/docker-archive-keyring.gpg ] ; then \
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg; \
- echo "deb [arch=$(ARCH) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(UBUNTU_CODENAME) stable" \
- | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ; \
- apt-get update; \
- fi
- @sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- @touch .deps.ok
-
-.PHONY: checkstyle-go
-checkstyle-go:
- @output=$$(find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/
[email protected] -d {} +); \
- status=$$?; \
- if [ $$status -ne 0 ]; then \
- exit $$status; \
- elif [ -z "$$output" ]; then \
- echo "******************************************************************************"; \
- echo "* HST Golang Checkstyle OK."; \
- echo "******************************************************************************"; \
- else \
- echo "$$output"; \
- echo "******************************************************************************"; \
- echo "* HST Golang Checkstyle FAILED. Use 'make fixstyle-go' or fix errors manually."; \
- echo "******************************************************************************"; \
- exit 1; \
- fi
-
-.PHONY: fixstyle-go
-fixstyle-go:
- @echo "Modified files:"
- @find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/
[email protected] -w -l {} +
- @go mod tidy
- @echo "*******************************************************************"
- @echo "Fixstyle done."
- @echo "*******************************************************************"
-
-.PHONY: cleanup-hst
-cleanup-hst:
- @if [ ! -f ".last_hst_ppid" ]; then \
- echo "'.last_hst_ppid' file does not exist."; \
- exit 1; \
- fi
- @echo "****************************"
- @echo "Removing docker containers:"
- @# "-" ignores errors
- @-sudo docker rm $$(sudo docker stop $$(sudo docker ps -a -q --filter "name=$$(cat .last_hst_ppid)") -t 0)
- @echo "****************************"
- @echo "Removing IP address files:"
- @find . -type f -regextype egrep -regex '.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' -exec sudo rm -v {} \;
- @find . -type f -name "fd00:0*" -exec sudo rm -v {} \;
- @echo "****************************"
- @echo "Removing network namespaces:"
- @for ns in $$(ip netns list | grep $$(cat .last_hst_ppid) | awk '{print $$1}'); do \
- echo $$ns; \
- sudo ip netns delete $$ns; \
- done
- @echo "****************************"
- @echo "Done."
- @echo "****************************"
-
-.PHONY: cleanup-perf
-cleanup-perf:
- @if [ ! -f ".last_hst_ppid" ]; then \
- echo "'.last_hst_ppid' file does not exist."; \
- exit 1; \
- fi
- @echo "****************************"
- @echo "Removing kubernetes pods:"
- @kubectl delete pods --all --grace-period=0 -n hs-test$$(cat .last_hst_ppid)
- @echo "****************************"
- @echo "Removing kubernetes namespace:"
- @kubectl delete namespace hs-test$$(cat .last_hst_ppid)
- @echo "****************************"
- @echo "Done."
- @echo "****************************"
+# Temp redirect
+%:
+ $(MAKE) -C ../../test-c/hs-test/ -f Makefile $@
\ No newline at end of file
+++ /dev/null
-package hst_common
-
-import (
- "flag"
- "fmt"
- "io"
- "log"
- "net/http"
- "os"
- "strconv"
- "strings"
- "time"
-
- . "github.com/onsi/ginkgo/v2"
- . "github.com/onsi/gomega"
-)
-
-var IsCoverage = flag.Bool("coverage", false, "use coverage run config")
-var IsPersistent = flag.Bool("persist", false, "persists topology config")
-var IsVerbose = flag.Bool("verbose", false, "verbose test output")
-var WhoAmI = flag.String("whoami", "root", "what user ran hs-test")
-var ParallelTotal = flag.Lookup("ginkgo.parallel.total")
-var IsVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
-var DryRun = flag.Bool("dryrun", false, "set up containers but don't run tests")
-var Timeout = flag.Int("timeout", 5, "test timeout override (in minutes)")
-var PerfTesting = flag.Bool("perf", false, "perf test flag")
-var NumaAwareCpuAlloc bool
-var TestTimeout time.Duration
-var RunningInCi bool
-
-const (
- LogDir string = "/tmp/hs-test/"
- VolumeDir string = "/vol"
-)
-
-type HstCommon struct {
- Ppid string
- ProcessIndex string
- Logger *log.Logger
- LogFile *os.File
-}
-
-func (s *HstCommon) Skip(args string) {
- Skip(args)
-}
-
-func (s *HstCommon) SetupTest() {
- TestCounterFunc()
- s.Log("[* TEST SETUP]")
-}
-
-func (s *HstCommon) SetupSuite() {
- s.CreateLogger()
- s.Log("[* SUITE SETUP]")
- s.Ppid = fmt.Sprint(os.Getppid())
- // remove last number so we have space to prepend a process index (interfaces have a char limit)
- s.Ppid = s.Ppid[:len(s.Ppid)-1]
- s.ProcessIndex = fmt.Sprint(GinkgoParallelProcess())
-}
-
-func (s *HstCommon) TeardownTest() {
- if *IsPersistent || *DryRun {
- s.Skip("Skipping test teardown")
- }
- s.Log("[* TEST TEARDOWN]")
-}
-
-func (s *HstCommon) TeardownSuite() {
- if *IsPersistent || *DryRun {
- s.Skip("Skipping suite teardown")
- }
- s.Log("[* SUITE TEARDOWN]")
-}
-
-func (s *HstCommon) GetCurrentSuiteName() string {
- return CurrentSpecReport().ContainerHierarchyTexts[0]
-}
-
-func (s *HstCommon) CreateLogger() {
- suiteName := s.GetCurrentSuiteName()
- var err error
- s.LogFile, err = os.Create("summary/" + suiteName + ".log")
- if err != nil {
- Fail("Unable to create log file.")
- }
- s.Logger = log.New(io.Writer(s.LogFile), "", log.LstdFlags)
-}
-
-// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter
-// to keep console tidy
-func (s *HstCommon) Log(log any, arg ...any) {
- var logStr string
- if len(arg) == 0 {
- logStr = fmt.Sprint(log)
- } else {
- logStr = fmt.Sprintf(fmt.Sprint(log), arg...)
- }
- logs := strings.Split(logStr, "\n")
-
- for _, line := range logs {
- s.Logger.Println(line)
- }
- if *IsVerbose {
- GinkgoWriter.Println(logStr)
- }
-}
-
-func (s *HstCommon) AssertNil(object any, msgAndArgs ...any) {
- ExpectWithOffset(2, object).To(BeNil(), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertNotNil(object any, msgAndArgs ...any) {
- ExpectWithOffset(2, object).ToNot(BeNil(), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertEqual(expected, actual any, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).To(Equal(expected), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertNotEqual(expected, actual any, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).ToNot(Equal(expected), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertContains(testString, contains any, msgAndArgs ...any) {
- ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).To(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertNotContains(testString, contains any, msgAndArgs ...any) {
- ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).ToNot(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertEmpty(object any, msgAndArgs ...any) {
- ExpectWithOffset(2, object).To(BeEmpty(), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertNotEmpty(object any, msgAndArgs ...any) {
- ExpectWithOffset(2, object).ToNot(BeEmpty(), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertMatchError(actual, expected error, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).To(MatchError(expected), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertGreaterEqual(actual, expected any, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).Should(BeNumerically(">=", expected), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertGreaterThan(actual, expected any, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).Should(BeNumerically(">", expected), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertLessEqual(actual, expected any, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).Should(BeNumerically("<=", expected), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertLessThan(actual, expected any, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).Should(BeNumerically("<", expected), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertEqualWithinThreshold(actual, expected, threshold any, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).Should(BeNumerically("~", expected, threshold), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertTimeEqualWithinThreshold(actual, expected time.Time, threshold time.Duration, msgAndArgs ...any) {
- ExpectWithOffset(2, actual).Should(BeTemporally("~", expected, threshold), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertHttpStatus(resp *http.Response, expectedStatus int, msgAndArgs ...any) {
- ExpectWithOffset(2, resp).To(HaveHTTPStatus(expectedStatus), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertHttpHeaderWithValue(resp *http.Response, key string, value any, msgAndArgs ...any) {
- ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue(key, value), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertHttpHeaderNotPresent(resp *http.Response, key string, msgAndArgs ...any) {
- ExpectWithOffset(2, resp.Header.Get(key)).To(BeEmpty(), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertHttpContentLength(resp *http.Response, expectedContentLen int64, msgAndArgs ...any) {
- ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue("Content-Length", strconv.FormatInt(expectedContentLen, 10)), msgAndArgs...)
-}
-
-func (s *HstCommon) AssertHttpBody(resp *http.Response, expectedBody string, msgAndArgs ...any) {
- ExpectWithOffset(2, resp).To(HaveHTTPBody(expectedBody), msgAndArgs...)
-}
-
-// Coverage builds take longer to finish -> assert timeout is set to 'TestTimeout - 30 seconds' to let the test finish properly
-func (s *HstCommon) AssertChannelClosed(timeout time.Duration, channel chan error) {
- if *IsCoverage && timeout > time.Second*30 {
- timeout = TestTimeout - time.Second*30
- s.Log("Coverage build, assert timeout is set to %s", timeout.String())
- }
- EventuallyWithOffset(2, channel).WithTimeout(timeout).Should(BeClosed())
-}
-
-// Pass the parsed result struct and the minimum amount of data transferred in MB.
-// Won't do anything when testing a coverage build.
-func (s *HstCommon) AssertIperfMinTransfer(result IPerfResult, minTransferred int) {
- if *IsCoverage {
- s.Log("Coverage build; not asserting")
- return
- }
- if result.Start.Details.Protocol == "TCP" {
- s.AssertGreaterEqual(result.End.TcpReceived.MBytes, minTransferred)
- } else {
- s.AssertGreaterEqual(result.End.Udp.MBytes, minTransferred)
- }
-}
+++ /dev/null
-package hst_kind
-
-func boolPtr(b bool) *bool {
- return &b
-}
-
-func int64Ptr(integer int64) *int64 {
- return &integer
-}
+++ /dev/null
-export VPP_WS=../../
-
-export HST_LDPRELOAD=${VPP_WS}/build-root/build-vpp-native/vpp/lib/x86_64-linux-gnu/libvcl_ldpreload.so
-export PATH=${VPP_WS}/build-root/build-vpp-native/vpp/bin:$PATH
-
-export UBUNTU_VERSION=$(lsb_release -rs)
-export HST_EXTENDED_TESTS=false
--- /dev/null
+export HS_ROOT=$(CURDIR)
+
+# sets WS_ROOT if called from test-c/hs-test
+ifeq ($(WS_ROOT),)
+export WS_ROOT=$(HS_ROOT)/../..
+endif
+
+ifeq ($(VERBOSE),)
+VERBOSE=false
+endif
+
+ifeq ($(PERSIST),)
+PERSIST=false
+endif
+
+ifeq ($(UNCONFIGURE),)
+UNCONFIGURE=false
+endif
+
+ifeq ($(TEST),)
+TEST=all
+endif
+
+ifeq ($(TEST-HS),)
+TEST-HS=all
+endif
+
+ifeq ($(DEBUG),)
+DEBUG=false
+endif
+
+ifeq ($(CPUS),)
+CPUS=1
+endif
+
+ifeq ($(VPP_CPUS),)
+VPP_CPUS=1
+endif
+
+ifeq ($(PARALLEL),)
+PARALLEL=1
+endif
+
+ifeq ($(REPEAT),)
+REPEAT=0
+endif
+
+ifeq ($(CPU0),)
+CPU0=false
+endif
+
+ifeq ($(VPPSRC),)
+VPPSRC=$(shell pwd)/../..
+endif
+
+ifeq ($(UBUNTU_CODENAME),)
+UBUNTU_CODENAME=$(shell grep '^UBUNTU_CODENAME=' /etc/os-release | cut -f2- -d=)
+endif
+
+ifeq ($(ARCH),)
+ARCH=$(shell dpkg --print-architecture)
+endif
+
+ifeq ($(NO_COLOR),)
+VERBOSE=false
+endif
+
+ifeq ($(TIMEOUT),)
+TIMEOUT=5
+endif
+
+ifeq ($(GINKGO_TIMEOUT),)
+GINKGO_TIMEOUT=3h
+endif
+
+CORE_PATTERN := $(shell cat /proc/sys/kernel/core_pattern)
+CORE_VOLUME:=
+DOCKER_TTY:=
+
+ifeq ($(shell expr "$(CORE_PATTERN)" : '^/'), 1)
+CORE_VOLUME := -v $(CORE_PATTERN):$(CORE_PATTERN)
+endif
+
+ifeq ($(shell tty -s && echo $$?), 0)
+DOCKER_TTY := -it
+endif
+
+FORCE_BUILD?=true
+
+# privileged is needed for "ip netns" otherwise we are not able to create namespace
+DOCKER_CAPABILITIES:=--privileged
+DOCKER_DEVICES:=--device /dev/vhost-net:/dev/vhost-net --device /dev/net/tun:/dev/net/tun
+DOCKER_VOLUMES:=-v $(WS_ROOT):$(WS_ROOT) -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/hs-test:/tmp/hs-test \
+ -v /etc/localtime:/etc/localtime:ro $(CORE_VOLUME) -v $(HS_ROOT)/.go_cache/mod:/root/go/pkg/mod \
+ -v $(HS_ROOT)/.go_cache/build:/root/.cache/go-build
+DOCKER_PROXY:=-e HTTP_PROXY=$(HTTP_PROXY) -e HTTPS_PROXY=$(HTTPS_PROXY) -e NO_PROXY=$(NO_PROXY)
+
+.PHONY: help
+help:
+ @echo "Make targets:"
+ @echo " test - run tests"
+ @echo " test-debug - run tests (vpp debug image)"
+ @echo " test-leak - run memory leak tests (vpp debug image)"
+ @echo " build - build test infra"
+ @echo " build-cov - coverage build of VPP and Docker images"
+ @echo " build-debug - build test infra (vpp debug image)"
+ @echo " build-go - just build golang files"
+ @echo " checkstyle-go - check style of .go source files"
+ @echo " fixstyle-go - format .go source files"
+ @echo " cleanup-hst - removes all docker containers and namespaces from last test run"
+ @echo " list-tests - list all tests"
+ @echo " install-deps - install software dependencies"
+ @echo
+ @echo "'make build' and 'make test' arguments:"
+ @echo " UBUNTU_VERSION - ubuntu version for docker image"
+ @echo " FORCE_BUILD=[true|false] - force docker image building"
+ @echo
+ @echo "'make test' specific arguments:"
+ @echo " PERSIST=[true|false] - whether clean up topology and dockers after test"
+ @echo " VERBOSE=[true|false] - verbose output"
+ @echo " UNCONFIGURE=[true|false] - unconfigure selected test"
+ @echo " DEBUG=[true|false] - attach VPP to GDB"
+ @echo " TEST=[name1,name2...] - specific test(s) to run"
+ @echo " SKIP=[name1,name2...] - specific test(s) to skip"
+ @echo " CPUS=[n] - number of cpus to allocate to each non-VPP container (default = 1)"
+ @echo " VPP_CPUS=[n] - number of cpus to allocate to each VPP container (default = 1)"
+ @echo " VPPSRC=[path-to-vpp-src] - path to vpp source files (for gdb)"
+ @echo " PARALLEL=[n] - number of test processes to spawn to run in parallel"
+ @echo " REPEAT=[n] - repeat tests up to N times or until a failure occurs"
+ @echo " CPU0=[true|false] - use cpu0"
+ @echo " DRYRUN=[true|false] - set up containers but don't run tests"
+ @echo " NO_COLOR=[true|false] - disables colorful Docker and Ginkgo output"
+ @echo " TIMEOUT=[minutes] - test timeout override (5 minutes by default)"
+ @echo " GINKGO_TIMEOUT=[Ns/m/h] - Ginkgo timeout override (3h by default)"
+
+.PHONY: list-tests
+list-tests:
+ @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --seed=2 | head -n -1 | grep 'test.go' | \
+ sed 's/^/* /; s/\(Suite\) /\1\//g'
+
+.PHONY: build-vpp-release
+build-vpp-release:
+ @$(MAKE) -C ../.. build-release
+
+.PHONY: build-vpp-debug
+build-vpp-debug:
+ @$(MAKE) -C ../.. build
+
+.PHONY: build-vpp-gcov
+build-vpp-gcov:
+ @$(MAKE) -C ../.. build-gcov
+
+.build.ok: build
+ @touch .build.ok
+
+.build.cov.ok: build-cov
+ @touch .build.ok
+
+.build_debug.ok: build-debug
+ @touch .build.ok
+
+.PHONY: test
+test: FORCE_BUILD=false
+test: .deps.ok .build.ok
+ docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
+ -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
+ .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \
+ --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \
+ --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --cpu0=$(CPU0) \
+ --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \
+ --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \
+ ./script/compress.sh $$?
+
+.PHONY: test-debug
+test-debug: FORCE_BUILD=false
+test-debug: .deps.ok .build_debug.ok
+ docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
+ -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
+ .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \
+ --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \
+ --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --debug_build=true \
+ --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \
+ --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \
+ ./script/compress.sh $$?
+
+.PHONY: wipe-lcov
+wipe-lcov:
+ @lcov --zerocounters --directory $(WS_ROOT)/build-root/build-vpp_gcov-native/vpp
+
+.PHONY: test-cov
+test-cov: FORCE_BUILD=false
+test-cov: .deps.ok .build.cov.ok wipe-lcov
+ -docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
+ -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
+ .$(HS_ROOT)/hs_test.sh --coverage=true --persist=$(PERSIST) --verbose=$(VERBOSE) \
+ --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST-HS) --cpus=$(CPUS) \
+ --vppsrc=$(VPPSRC) --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) \
+ --timeout=$(TIMEOUT) --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \
+ ./script/compress.sh $$?
+ $(MAKE) -C ../.. test-cov-post-standalone HS_TEST=1
+
+.PHONY: test-leak
+test-leak: FORCE_BUILD=false
+test-leak: .deps.ok .build_debug.ok
+ docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\
+ -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \
+ .$(HS_ROOT)/hs_test.sh --test=$(TEST) --debug_build=true --leak_check=true --vppsrc=$(VPPSRC) --timeout=$(TIMEOUT) \
+ --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT);
+
+# this is executed in a container by hs-test.sh
+.PHONY: build-go
+build-go:
+ go build --buildvcs=false ./tools/http_server
+
+.PHONY: build
+build: .deps.ok build-vpp-release
+ @rm -f .build.ok
+ bash ./script/build_hst.sh release $(FORCE_BUILD)
+ @touch .build.ok
+
+.PHONY: build-cov
+build-cov: .deps.ok build-vpp-gcov
+ @rm -f .build.cov.ok
+ bash ./script/build_hst.sh gcov $(FORCE_BUILD)
+ @touch .build.cov.ok
+
+.PHONY: build-debug
+build-debug: .deps.ok build-vpp-debug
+ @rm -f .build.ok
+ bash ./script/build_hst.sh debug $(FORCE_BUILD)
+ @touch .build.ok
+
+.deps.ok:
+ @$(MAKE) install-deps
+
+.PHONY: install-deps
+install-deps:
+ @rm -f .deps.ok
+ @if [ -d "/usr/local/go" ]; then \
+ echo "Go is already installed. You may have to update it manually if version < 1.23.10"; \
+ go version; \
+ else \
+ echo "Installing Go 1.23"; \
+ wget -t 2 https://go.dev/dl/go1.23.10.linux-$(ARCH).tar.gz -O /tmp/go1.23.10.linux-$(ARCH).tar.gz && sudo tar -C /usr/local -xzf /tmp/go1.23.10.linux-$(ARCH).tar.gz; \
+ sudo ln -s /usr/local/go/bin/go /usr/bin/go ; \
+ fi
+ @sudo -E apt-get update
+ @sudo -E apt-get install -y apt-transport-https ca-certificates curl software-properties-common \
+ bridge-utils gpg
+ @if [ ! -f /usr/share/keyrings/docker-archive-keyring.gpg ] ; then \
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg; \
+ echo "deb [arch=$(ARCH) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(UBUNTU_CODENAME) stable" \
+ | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ; \
+ apt-get update; \
+ fi
+ @sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+ @touch .deps.ok
+
+.PHONY: checkstyle-go
+checkstyle-go:
+ @output=$$(find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/
[email protected] -d {} +); \
+ status=$$?; \
+ if [ $$status -ne 0 ]; then \
+ exit $$status; \
+ elif [ -z "$$output" ]; then \
+ echo "******************************************************************************"; \
+ echo "* HST Golang Checkstyle OK."; \
+ echo "******************************************************************************"; \
+ else \
+ echo "$$output"; \
+ echo "******************************************************************************"; \
+ echo "* HST Golang Checkstyle FAILED. Use 'make fixstyle-go' or fix errors manually."; \
+ echo "******************************************************************************"; \
+ exit 1; \
+ fi
+
+.PHONY: fixstyle-go
+fixstyle-go:
+ @echo "Modified files:"
+ @find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/
[email protected] -w -l {} +
+ @go mod tidy
+ @echo "*******************************************************************"
+ @echo "Fixstyle done."
+ @echo "*******************************************************************"
+
+.PHONY: cleanup-hst
+cleanup-hst:
+ @if [ ! -f ".last_hst_ppid" ]; then \
+ echo "'.last_hst_ppid' file does not exist."; \
+ exit 1; \
+ fi
+ @echo "****************************"
+ @echo "Removing docker containers:"
+ @# "-" ignores errors
+ @-sudo docker rm $$(sudo docker stop $$(sudo docker ps -a -q --filter "name=$$(cat .last_hst_ppid)") -t 0)
+ @echo "****************************"
+ @echo "Removing IP address files:"
+ @find . -type f -regextype egrep -regex '.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' -exec sudo rm -v {} \;
+ @find . -type f -name "fd00:0*" -exec sudo rm -v {} \;
+ @echo "****************************"
+ @echo "Removing network namespaces:"
+ @for ns in $$(ip netns list | grep $$(cat .last_hst_ppid) | awk '{print $$1}'); do \
+ echo $$ns; \
+ sudo ip netns delete $$ns; \
+ done
+ @echo "****************************"
+ @echo "Done."
+ @echo "****************************"
"testing"
"time"
- . "fd.io/hs-test/infra/common"
+ . "fd.io/hs-test/infra"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
+var _ = ReportBeforeSuite(func(report Report) {
+ TestsThatWillRun = report.PreRunStats.SpecsThatWillRun
+})
+
var _ = ReportAfterSuite("VPP version under test", func(report Report) {
for i := range report.SpecReports {
specReport := report.SpecReports[i]
go.fd.io/govpp v0.12.0
golang.org/x/net v0.37.0
gopkg.in/yaml.v3 v3.0.1
- k8s.io/api v0.30.2
- k8s.io/apimachinery v0.30.2
- k8s.io/client-go v0.30.2
)
require (
github.com/Microsoft/go-winio v0.6.2 // indirect
- github.com/a8m/envsubst v1.4.2
github.com/containerd/log v0.1.0 // indirect
- github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
- github.com/emicklei/go-restful/v3 v3.11.2 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
- github.com/go-openapi/jsonpointer v0.21.0 // indirect
- github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/strfmt v0.23.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/protobuf v1.5.4 // indirect
- github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.7.0 // indirect
- github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
- github.com/google/uuid v1.6.0 // indirect
- github.com/gorilla/websocket v1.5.1 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
- github.com/imdario/mergo v0.3.16 // indirect
- github.com/joho/godotenv v1.5.1
- github.com/josharian/intern v1.0.0 // indirect
- github.com/json-iterator/go v1.1.12 // indirect
github.com/lunixbochs/struc v0.0.0-20200521075829-a4cb8d33dbbe // indirect
- github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
- github.com/moby/spdystream v0.2.0 // indirect
- github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
- github.com/modern-go/reflect2 v1.0.2 // indirect
- github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
- github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
- github.com/spf13/pflag v1.0.6 // indirect
github.com/spf13/viper v1.19.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
golang.org/x/mod v0.23.0 // indirect
- golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.31.0 // indirect
- golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.30.0 // indirect
- google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.36.5 // indirect
- gopkg.in/inf.v0 v0.9.1 // indirect
- gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gotest.tools/v3 v3.5.1 // indirect
+ k8s.io/apimachinery v0.30.2 // indirect
+ k8s.io/client-go v0.30.2 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
- k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
- sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
- sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
- sigs.k8s.io/yaml v1.4.0 // indirect
)
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
-github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg=
-github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
-github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
-github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/edwarnicke/exechelper v1.0.3 h1:OY2ocGAITTqnEDvZk0dRQSeMIQvyH0SyL/4ncz+5GeQ=
github.com/edwarnicke/exechelper v1.0.3/go.mod h1:R65OUPKns4bgeHkCmfSHbmqLBU8aHZxTgLmEyUBUk4U=
-github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU=
-github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
-github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
-github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
-github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
-github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
-github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
-github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
-github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
-github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
-github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
-github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
-github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
-github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
-github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
-github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
-github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.fd.io/govpp v0.12.0 h1:5HnMzsKHSFdxglsFyEhR0g+CzncWiLYXG2NDYgNUrnE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
-golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
-golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
-golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
-google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
-gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
-k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI=
-k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50=
k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
-k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak=
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
-sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
-sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
#!/usr/bin/env bash
-source vars
-
args=
focused_test=0
persist_set=0
skip_names=()
dryrun=
no_color=
-perf=
hs_root=
for i in "$@"
ginkgo_args="$ginkgo_args --no-color"
fi
;;
- --perf=*)
- perf="${i#*=}"
- args="$args -perf"
- ;;
--timeout=*)
args="$args -timeout ${i#*=}"
;;
esac
done
-if [ "$perf" = "true" ]; then
- ginkgo_args="$ginkgo_args --label-filter=Perf"
-else
- ginkgo_args="$ginkgo_args --label-filter=!Perf"
-fi
-
if [ ${#tc_names[@]} -gt 1 ]
then
focused_test=0
make build-go
mkdir -p summary
+rm -f summary/*
# shellcheck disable=SC2086
-CMD="sudo -E go run github.com/onsi/ginkgo/v2/ginkgo --json-report=summary/report.json $ginkgo_args -- $args"
+CMD="go run github.com/onsi/ginkgo/v2/ginkgo --json-report=summary/report.json $ginkgo_args -- $args"
echo "$CMD"
$CMD
exit_status=$?
-if [ -e "summary/failed-summary.log" ]; then
- rm summary/failed-summary.log
-fi
-
if [ $exit_status != 0 ]; then
jq -r '.[0] | .SpecReports[] | select((.State == "failed") or (.State == "timedout") or (.State == "panicked")) | select(.Failure != null) |
"TestName:
--- /dev/null
+package hst
+
+import (
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ . "github.com/onsi/gomega"
+)
+
+func (s *HstSuite) AssertNil(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).To(BeNil(), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertNotNil(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).ToNot(BeNil(), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertEqual(expected, actual any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).To(Equal(expected), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertNotEqual(expected, actual any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).ToNot(Equal(expected), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertContains(testString, contains any, msgAndArgs ...any) {
+ ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).To(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertNotContains(testString, contains any, msgAndArgs ...any) {
+ ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).ToNot(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertEmpty(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).To(BeEmpty(), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertNotEmpty(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).ToNot(BeEmpty(), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertMatchError(actual, expected error, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).To(MatchError(expected), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertGreaterEqual(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically(">=", expected), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertGreaterThan(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically(">", expected), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertLessEqual(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically("<=", expected), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertLessThan(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically("<", expected), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertEqualWithinThreshold(actual, expected, threshold any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically("~", expected, threshold), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertTimeEqualWithinThreshold(actual, expected time.Time, threshold time.Duration, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeTemporally("~", expected, threshold), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertHttpStatus(resp *http.Response, expectedStatus int, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPStatus(expectedStatus), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertHttpHeaderWithValue(resp *http.Response, key string, value any, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue(key, value), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertHttpHeaderNotPresent(resp *http.Response, key string, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp.Header.Get(key)).To(BeEmpty(), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertHttpContentLength(resp *http.Response, expectedContentLen int64, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue("Content-Length", strconv.FormatInt(expectedContentLen, 10)), msgAndArgs...)
+}
+
+func (s *HstSuite) AssertHttpBody(resp *http.Response, expectedBody string, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPBody(expectedBody), msgAndArgs...)
+}
+
+// Coverage builds take longer to finish -> assert timeout is set to 'TestTimeout - 30 seconds' to let the test finish properly
+func (s *HstSuite) AssertChannelClosed(timeout time.Duration, channel chan error) {
+ if *IsCoverage && timeout > time.Second*30 {
+ timeout = TestTimeout - time.Second*30
+ s.Log("Coverage build, assert timeout is set to %s", timeout.String())
+ }
+ EventuallyWithOffset(2, channel).WithTimeout(timeout).Should(BeClosed())
+}
+
+// Pass the parsed result struct and the minimum amount of data transferred in MB.
+// Won't do anything when testing a coverage build.
+func (s *HstSuite) AssertIperfMinTransfer(result IPerfResult, minTransferred int) {
+ if *IsCoverage {
+ s.Log("Coverage build; not asserting")
+ return
+ }
+ if result.Start.Details.Protocol == "TCP" {
+ s.AssertGreaterEqual(result.End.TcpReceived.MBytes, minTransferred)
+ } else {
+ s.AssertGreaterEqual(result.End.Udp.MBytes, minTransferred)
+ }
+}
"text/template"
"time"
- . "fd.io/hs-test/infra/common"
"github.com/cilium/cilium/pkg/sysctl"
containerTypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"os"
"os/exec"
"strings"
-
- . "fd.io/hs-test/infra/common"
)
var CgroupPath = "/sys/fs/cgroup/"
"bufio"
"flag"
"fmt"
+ "io"
+ "log"
"net/http"
"net/http/httputil"
"os"
"strings"
"time"
- . "fd.io/hs-test/infra/common"
containerTypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/edwarnicke/exechelper"
var IsDebugBuild = flag.Bool("debug_build", false, "some paths are different with debug build")
var UseCpu0 = flag.Bool("cpu0", false, "use cpu0")
var IsLeakCheck = flag.Bool("leak_check", false, "run leak-check tests")
+var IsCoverage = flag.Bool("coverage", false, "use coverage run config")
+var IsPersistent = flag.Bool("persist", false, "persists topology config")
+var IsVerbose = flag.Bool("verbose", false, "verbose test output")
+var WhoAmI = flag.String("whoami", "root", "what user ran hs-test")
+var ParallelTotal = flag.Lookup("ginkgo.parallel.total")
+var IsVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
+var DryRun = flag.Bool("dryrun", false, "set up containers but don't run tests")
+var Timeout = flag.Int("timeout", 5, "test timeout override (in minutes)")
+var PerfTesting = flag.Bool("perf", false, "perf test flag")
+var NumaAwareCpuAlloc bool
+var TestTimeout time.Duration
+var RunningInCi bool
+var TestsThatWillRun int
+
+const (
+ LogDir string = "/tmp/hs-test/"
+ VolumeDir string = "/vol"
+)
type HstSuite struct {
- HstCommon
+ Ppid string
+ ProcessIndex string
+ Logger *log.Logger
+ LogFile *os.File
AllContainers map[string]*Container
StartedContainers []*Container
NetConfigs []NetConfig
s.Log("docker client created")
}
-func (s *HstSuite) SetupSuite() {
- RegisterFailHandler(func(message string, callerSkip ...int) {
- s.HstFail()
- Fail(message, callerSkip...)
- })
- s.HstCommon.SetupSuite()
- s.newDockerClient()
-
- var err error
- s.CpuAllocator, err = CpuAllocator()
- s.CpuAllocator.suite = s
- if err != nil {
- Fail("failed to init cpu allocator: " + fmt.Sprint(err))
- }
- s.CpusPerContainer = *NConfiguredCpus
- s.CpusPerVppContainer = *NConfiguredVppCpus
- s.CoverageRun = *IsCoverage
-}
-
func (s *HstSuite) AllocateCpus(containerName string) []int {
var cpuCtx *CpuContext
var err error
s.CpuContexts = append(s.CpuContexts, cpuCtx)
}
+func (s *HstSuite) Skip(args string) {
+ Skip(args)
+}
+
+func (s *HstSuite) CreateLogger() {
+ suiteName := s.GetCurrentSuiteName()
+ var err error
+ s.LogFile, err = os.Create("summary/" + suiteName + ".log")
+ if err != nil {
+ Fail("Unable to create log file.")
+ }
+ s.Logger = log.New(io.Writer(s.LogFile), "", log.LstdFlags)
+}
+
+func (s *HstSuite) SetupSuite() {
+ RegisterFailHandler(func(message string, callerSkip ...int) {
+ s.HstFail()
+ Fail(message, callerSkip...)
+ })
+ s.CreateLogger()
+ s.Log("[* SUITE SETUP]")
+ s.Ppid = fmt.Sprint(os.Getppid())
+ // remove last number so we have space to prepend a process index (interfaces have a char limit)
+ s.Ppid = s.Ppid[:len(s.Ppid)-1]
+ s.ProcessIndex = fmt.Sprint(GinkgoParallelProcess())
+ s.newDockerClient()
+
+ var err error
+ s.CpuAllocator, err = CpuAllocator()
+ s.CpuAllocator.suite = s
+ if err != nil {
+ Fail("failed to init cpu allocator: " + fmt.Sprint(err))
+ }
+ s.CpusPerContainer = *NConfiguredCpus
+ s.CpusPerVppContainer = *NConfiguredVppCpus
+ s.CoverageRun = *IsCoverage
+}
+
func (s *HstSuite) TeardownSuite() {
- s.HstCommon.TeardownSuite()
+ if *IsPersistent || *DryRun {
+ s.Skip("Skipping suite teardown")
+ }
+ s.Log("[* SUITE TEARDOWN]")
// allow ports to be reused by removing them from reservedPorts slice
reservedPorts = reservedPorts[:len(reservedPorts)-s.numOfNewPorts]
if s.Ip4AddrAllocator != nil {
s.UnconfigureNetworkTopology()
}
+func (s *HstSuite) SetupTest() {
+ TestCounterFunc()
+ s.Log("[* TEST SETUP]")
+ // doesn't impact MW/solo tests
+ s.CpuAllocator.lastCpu = (GinkgoParallelProcess() - 1) * 4
+ s.StartedContainers = s.StartedContainers[:0]
+ s.SkipIfUnconfiguring()
+ s.SetupContainers()
+}
+
func (s *HstSuite) TeardownTest() {
- s.HstCommon.TeardownTest()
+ if *IsPersistent || *DryRun {
+ s.Skip("Skipping test teardown")
+ }
+ s.Log("[* TEST TEARDOWN]")
s.SkipIfNotEnoguhCpus = false
// reset to defaults
s.CpusPerContainer = *NConfiguredCpus
}
}
-func (s *HstSuite) SetupTest() {
- s.HstCommon.SetupTest()
- // doesn't impact MW/solo tests
- s.CpuAllocator.lastCpu = (GinkgoParallelProcess() - 1) * 4
- s.StartedContainers = s.StartedContainers[:0]
- s.SkipIfUnconfiguring()
- s.SetupContainers()
-}
-
func (s *HstSuite) SetupContainers() {
for _, container := range s.AllContainers {
if !container.IsOptional {
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"strings"
"time"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"time"
"fd.io/hs-test/h2spec_extras"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
"github.com/summerwind/h2spec"
"github.com/summerwind/h2spec/config"
switch sp.tg {
case GenericTestGroup:
tg = generic.Spec()
- break
case HpackTestGroup:
tg = hpack.Spec()
- break
case Http2TestGroup:
tg = http2.Spec()
- break
case ExtrasTestGroup:
tg = h2spec_extras.Spec()
- break
}
tg.Test(conf)
defer resp.Body.Close()
report, err := io.ReadAll(resp.Body)
s.AssertContains(string(report), "0 failed")
+ s.AssertNil(err)
expected := fmt.Sprintf("<div>%d tests, %d passed", nExecuted, nExecuted)
- if !strings.Contains(string(report), expected) {
- return false
- }
- return true
+ return strings.Contains(string(report), expected)
}
var _ = Describe("H2SpecClientSuite", Ordered, Serial, func() {
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"strings"
"time"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"strings"
"time"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"strings"
"time"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
"time"
"fd.io/hs-test/h2spec_extras"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
"github.com/summerwind/h2spec/config"
)
"fd.io/hs-test/h2spec_extras"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
"github.com/summerwind/h2spec/config"
)
import (
"crypto/tls"
+ "encoding/json"
"errors"
"fmt"
"io"
"net/http/httputil"
"os"
"os/exec"
+ "path/filepath"
"regexp"
+ "runtime"
"strconv"
"strings"
"time"
"github.com/edwarnicke/exechelper"
+ . "github.com/onsi/ginkgo/v2"
)
const networkTopologyDir string = "topo-network/"
}
return uVal, nil
}
+
+// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter
+// to keep console tidy
+func (s *HstSuite) Log(log any, arg ...any) {
+ var logStr string
+ if len(arg) == 0 {
+ logStr = fmt.Sprint(log)
+ } else {
+ logStr = fmt.Sprintf(fmt.Sprint(log), arg...)
+ }
+ logs := strings.Split(logStr, "\n")
+
+ for _, line := range logs {
+ s.Logger.Println(line)
+ }
+ if *IsVerbose {
+ GinkgoWriter.Println(logStr)
+ }
+}
+
+func GetTestFilename() string {
+ _, filename, _, _ := runtime.Caller(2)
+ return filepath.Base(filename)
+}
+
+var testCounter uint16
+var startTime time.Time = time.Now()
+
+func TestCounterFunc() {
+ if ParallelTotal.Value.String() != "1" {
+ return
+ }
+ testCounter++
+ fmt.Printf("Test counter: %d/%d (%.2f%%)\n"+
+ "Time elapsed: %.2fs\n",
+ testCounter, TestsThatWillRun, float64(testCounter)/float64(TestsThatWillRun)*100, time.Since(startTime).Seconds())
+}
+
+type IPerfResult struct {
+ Start struct {
+ Timestamp struct {
+ Time string `json:"time"`
+ } `json:"timestamp"`
+ Connected []struct {
+ Socket int `json:"socket"`
+ LocalHost string `json:"local_host"`
+ LocalPort int `json:"local_port"`
+ RemoteHost string `json:"remote_host"`
+ RemotePort int `json:"remote_port"`
+ } `json:"connected"`
+ Version string `json:"version"`
+ Details struct {
+ Protocol string `json:"protocol"`
+ } `json:"test_start"`
+ } `json:"start"`
+ End struct {
+ TcpSent *struct {
+ MbitsPerSecond float64 `json:"bits_per_second"`
+ MBytes float64 `json:"bytes"`
+ } `json:"sum_sent,omitempty"`
+ TcpReceived *struct {
+ MbitsPerSecond float64 `json:"bits_per_second"`
+ MBytes float64 `json:"bytes"`
+ } `json:"sum_received,omitempty"`
+ Udp *struct {
+ MbitsPerSecond float64 `json:"bits_per_second"`
+ JitterMs float64 `json:"jitter_ms,omitempty"`
+ LostPackets int `json:"lost_packets,omitempty"`
+ Packets int `json:"packets,omitempty"`
+ LostPercent float64 `json:"lost_percent,omitempty"`
+ MBytes float64 `json:"bytes"`
+ } `json:"sum,omitempty"`
+ } `json:"end"`
+}
+
+func (s *HstSuite) ParseJsonIperfOutput(jsonResult []byte) IPerfResult {
+ var result IPerfResult
+
+ // VCL/LDP debugging can pollute output so find the first occurrence of a curly brace to locate the start of JSON data
+ jsonStart := -1
+ jsonEnd := len(jsonResult)
+ braceCount := 0
+ for i := 0; i < len(jsonResult); i++ {
+ if jsonResult[i] == '{' {
+ if jsonStart == -1 {
+ jsonStart = i
+ }
+ braceCount++
+ } else if jsonResult[i] == '}' {
+ braceCount--
+ if braceCount == 0 {
+ jsonEnd = i + 1
+ break
+ }
+ }
+ }
+ jsonResult = jsonResult[jsonStart:jsonEnd]
+
+ // remove iperf warning line if present
+ if strings.Contains(string(jsonResult), "warning") {
+ index := strings.Index(string(jsonResult), "\n")
+ jsonResult = jsonResult[index+1:]
+ }
+
+ err := json.Unmarshal(jsonResult, &result)
+ s.AssertNil(err)
+
+ if result.Start.Details.Protocol == "TCP" {
+ result.End.TcpSent.MbitsPerSecond = result.End.TcpSent.MbitsPerSecond / 1000000
+ result.End.TcpSent.MBytes = result.End.TcpSent.MBytes / 1000000
+ result.End.TcpReceived.MbitsPerSecond = result.End.TcpReceived.MbitsPerSecond / 1000000
+ result.End.TcpReceived.MBytes = result.End.TcpReceived.MBytes / 1000000
+ } else {
+ result.End.Udp.MBytes = result.End.Udp.MBytes / 1000000
+ result.End.Udp.MbitsPerSecond = result.End.Udp.MbitsPerSecond / 1000000
+ }
+
+ return result
+}
+
+func (s *HstSuite) LogJsonIperfOutput(result IPerfResult) {
+ s.Log("\n*******************************************\n"+
+ "%s\n"+
+ "[%s] %s:%d connected to %s:%d\n"+
+ "Started: %s\n",
+ result.Start.Version,
+ result.Start.Details.Protocol,
+ result.Start.Connected[0].LocalHost, result.Start.Connected[0].LocalPort,
+ result.Start.Connected[0].RemoteHost, result.Start.Connected[0].RemotePort,
+ result.Start.Timestamp.Time)
+
+ if result.Start.Details.Protocol == "TCP" {
+ s.Log("Transfer (sent): %.2f MBytes\n"+
+ "Bitrate (sent): %.2f Mbits/sec\n"+
+ "Transfer (received): %.2f MBytes\n"+
+ "Bitrate (received): %.2f Mbits/sec",
+ result.End.TcpSent.MBytes,
+ result.End.TcpSent.MbitsPerSecond,
+ result.End.TcpReceived.MBytes,
+ result.End.TcpReceived.MbitsPerSecond)
+ } else {
+ s.Log("Transfer: %.2f MBytes\n"+
+ "Bitrate: %.2f Mbits/sec\n"+
+ "Jitter: %.3f ms\n"+
+ "Packets: %d\n"+
+ "Packets lost: %d\n"+
+ "Percent lost: %.2f%%",
+ result.End.Udp.MBytes,
+ result.End.Udp.MbitsPerSecond,
+ result.End.Udp.JitterMs,
+ result.End.Udp.Packets,
+ result.End.Udp.LostPackets,
+ result.End.Udp.LostPercent)
+ }
+ s.Log("*******************************************\n")
+}
"syscall"
"time"
- . "fd.io/hs-test/infra/common"
"go.fd.io/govpp/binapi/ethernet_types"
"github.com/edwarnicke/exechelper"
"time"
. "fd.io/hs-test/infra"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
--- /dev/null
+ifeq ($(VERBOSE),)
+VERBOSE=false
+endif
+
+ifeq ($(PERSIST),)
+PERSIST=false
+endif
+
+ifeq ($(TEST),)
+TEST=all
+endif
+
+ifeq ($(REPEAT),)
+REPEAT=0
+endif
+
+ifeq ($(UBUNTU_CODENAME),)
+UBUNTU_CODENAME=$(shell grep '^UBUNTU_CODENAME=' /etc/os-release | cut -f2- -d=)
+endif
+
+ifeq ($(ARCH),)
+ARCH=$(shell dpkg --print-architecture)
+endif
+
+ifeq ($(NO_COLOR),)
+VERBOSE=false
+endif
+
+ifeq ($(TIMEOUT),)
+TIMEOUT=30
+endif
+
+ifeq ($(GINKGO_TIMEOUT),)
+GINKGO_TIMEOUT=3h
+endif
+
+FORCE_BUILD?=true
+
+.PHONY: help
+help:
+ @echo "Make targets:"
+ @echo " test - run kube-test (requires a running cluster)"
+ @echo " build - build test infra"
+ @echo " build-debug - build test infra (vpp debug image)"
+ @echo " cluster-help - print info about KinD cluster setup (perf testing)"
+ @echo " master-cluster - setup KinD cluster for performance testing (master CalicoVPP + VPP)"
+ @echo " rebuild-master-cluster - rebuild VPP and update related pods without shutting down the cluster"
+ @echo " release-cluster - setup KinD cluster for performance testing (latest CalicoVPP release)"
+ @echo " checkstyle-go - check style of .go source files"
+ @echo " fixstyle-go - format .go source files"
+ @echo " cleanup-kube - removes all kubernetes pods and namespaces from last test run"
+ @echo " list-tests - list all tests"
+ @echo " install-deps - install software dependencies"
+ @echo " install-kube-deps - install software dependencies for kind cluster"
+ @echo
+ @echo "'make build' and 'make test' arguments:"
+ @echo " UBUNTU_VERSION - ubuntu version for docker image"
+ @echo " FORCE_BUILD=[true|false] - force docker image building"
+ @echo
+ @echo "'make test' specific arguments:"
+ @echo " PERSIST=[true|false] - whether clean up topology and dockers after test"
+ @echo " VERBOSE=[true|false] - verbose output"
+ @echo " TEST=[name1,name2...] - specific test(s) to run"
+ @echo " SKIP=[name1,name2...] - specific test(s) to skip"
+ @echo " REPEAT=[n] - repeat tests up to N times or until a failure occurs"
+ @echo " DRYRUN=[true|false] - set up containers but don't run tests"
+ @echo " NO_COLOR=[true|false] - disables colorful Docker and Ginkgo output"
+ @echo " TIMEOUT=[minutes] - test timeout override (30 minutes by default)"
+ @echo " GINKGO_TIMEOUT=[Ns/m/h] - Ginkgo timeout override (3h by default)"
+
+.PHONY: list-tests
+list-tests:
+ @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --seed=2 | head -n -1 | grep 'test.go' | \
+ sed 's/^/* /; s/\(Suite\) /\1\//g'
+
+.PHONY: build-vpp-release
+build-vpp-release:
+ @$(MAKE) -C ../.. build-release
+
+.PHONY: build-vpp-debug
+build-vpp-debug:
+ @$(MAKE) -C ../.. build
+
+.build.ok: build
+ @touch .build.ok
+
+.build_debug.ok: build-debug
+ @touch .build.ok
+
+.PHONY: test
+test: FORCE_BUILD=false
+test: .deps.ok .build.ok
+ @bash ./kube_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \
+ --test=$(TEST) --repeat=$(REPEAT) --skip=$(SKIP) \
+ --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \
+ --ginkgo_timeout=$(GINKGO_TIMEOUT); \
+ ./script/compress.sh $$?
+
+.PHONY: cluster-help
+cluster-help:
+ @bash ./script/setup-cluster.sh help
+
+.PHONY: release-cluster
+release-cluster: .kube_deps.ok
+ @bash ./script/setup-cluster.sh release-cluster
+
+.PHONY: master-cluster
+master-cluster: .kube_deps.ok
+ @bash ./script/setup-cluster.sh master-cluster
+
+.PHONY: rebuild-master-cluster
+rebuild-master-cluster: .kube_deps.ok
+ @bash ./script/setup-cluster.sh rebuild-master-cluster
+
+.PHONY: build
+build: .deps.ok build-vpp-release
+ @rm -f .build.ok
+ bash ./script/build_kube.sh release $(FORCE_BUILD)
+ @touch .build.ok
+
+.PHONY: build-debug
+build-debug: .deps.ok build-vpp-debug
+ @rm -f .build.ok
+ bash ./script/build_kube.sh debug $(FORCE_BUILD)
+ @touch .build.ok
+
+.deps.ok:
+ @$(MAKE) install-deps
+
+.kube_deps.ok:
+ @$(MAKE) install-kube-deps
+
+.PHONY: install-kube-deps
+install-kube-deps: .deps.ok
+ -@if ! command -v kube >/dev/null 2>&1; then \
+ echo "Installing KinD"; \
+ echo "Creating symlink from '$(HOME)/go/bin/kind' to '/usr/bin/kind'"; \
+ sudo ln -s $(HOME)/go/bin/kind /usr/bin/kind; \
+ else \
+ echo "KinD is already installed. Skipping."; \
+ fi
+ @if ! command -v kubectl >/dev/null 2>&1; then \
+ echo "kubectl not found. Installing kubectl..."; \
+ sudo -E apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg; \
+ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \
+ sudo -E chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \
+ echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list; \
+ sudo -E chmod 644 /etc/apt/sources.list.d/kubernetes.list; \
+ sudo apt-get update && sudo apt-get install -y kubectl; \
+ else \
+ echo "kubectl is already installed. Skipping."; \
+ fi
+ @touch .kube_deps.ok
+
+.PHONY: install-deps
+install-deps:
+ @rm -f .deps.ok
+ @if [ -d "/usr/local/go" ]; then \
+ echo "Go is already installed. You may have to update it manually if version < 1.23.10"; \
+ go version; \
+ else \
+ echo "Installing Go 1.23"; \
+ wget -t 2 https://go.dev/dl/go1.23.10.linux-$(ARCH).tar.gz -O /tmp/go1.23.10.linux-$(ARCH).tar.gz && sudo tar -C /usr/local -xzf /tmp/go1.23.10.linux-$(ARCH).tar.gz; \
+ sudo ln -s /usr/local/go/bin/go /usr/bin/go ; \
+ fi
+ @sudo -E apt-get update
+ @sudo -E apt-get install -y apt-transport-https ca-certificates curl software-properties-common \
+ bridge-utils gpg
+ @if [ ! -f /usr/share/keyrings/docker-archive-keyring.gpg ] ; then \
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg; \
+ echo "deb [arch=$(ARCH) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(UBUNTU_CODENAME) stable" \
+ | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ; \
+ apt-get update; \
+ fi
+ @sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+ @touch .deps.ok
+
+.PHONY: checkstyle-go
+checkstyle-go:
+ @output=$$(find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/
[email protected] -d {} +); \
+ status=$$?; \
+ if [ $$status -ne 0 ]; then \
+ exit $$status; \
+ elif [ -z "$$output" ]; then \
+ echo "******************************************************************************"; \
+ echo "* Kube-Test Golang Checkstyle OK."; \
+ echo "******************************************************************************"; \
+ else \
+ echo "$$output"; \
+ echo "******************************************************************************"; \
+ echo "* Kube-Test Golang Checkstyle FAILED. Use 'make fixstyle-go' or fix errors manually."; \
+ echo "******************************************************************************"; \
+ exit 1; \
+ fi
+
+.PHONY: fixstyle-go
+fixstyle-go:
+ @echo "Modified files:"
+ @find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/
[email protected] -w -l {} +
+ @go mod tidy
+ @echo "*******************************************************************"
+ @echo "Fixstyle done."
+ @echo "*******************************************************************"
+
+.PHONY: cleanup-kube
+cleanup-kube:
+ @if [ ! -f ".last_ppid" ]; then \
+ echo "'.last_ppid' file does not exist."; \
+ exit 1; \
+ fi
+ @echo "****************************"
+ @echo "Removing kubernetes pods:"
+ @kubectl delete pods --all --grace-period=0 -n kube-test$$(cat .last_ppid)
+ @echo "****************************"
+ @echo "Removing kubernetes namespace:"
+ @kubectl delete namespace kube-test$$(cat .last_ppid)
+ @echo "****************************"
+ @echo "Done."
+ @echo "****************************"
--- /dev/null
+# Apache Bench container that uses the base image
+ARG UBUNTU_VERSION=22.04
+FROM localhost:5001/vpp-test-base:latest
+
+# apache2-utils is now installed in the base image
+
+ENTRYPOINT ["ab"]
--- /dev/null
+ARG UBUNTU_VERSION=22.04
+FROM ubuntu:${UBUNTU_VERSION} AS base
+
+# Set environment variables
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Install common dependencies needed across multiple containers
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ # Basic utilities
+ ca-certificates \
+ wget \
+ curl \
+ file \
+ gnupg \
+ gnupg2 \
+ git \
+ iproute2 \
+ iputils-ping \
+ less \
+ lsb-release \
+ ubuntu-keyring \
+ vim \
+ # Development & debugging
+ gdb \
+ libunwind-dev \
+ # Libraries frequently needed
+ libapr1 \
+ libnl-3-dev \
+ libnl-route-3-dev \
+ libnuma1 \
+ libsubunit0 \
+ openssl \
+ python3 \
+ # Tools used in tests
+ iperf3 \
+ xz-utils \
+ # Tools moved from derived images
+ apache2-utils \
+ nghttp2 \
+ wrk
+
+# Because of http/3 support we can't use stock nginx in ubuntu 24.04
+RUN curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
+| tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
+RUN echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
+ http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
+ | tee /etc/apt/sources.list.d/nginx.list
+RUN bash -c 'echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
+| tee /etc/apt/preferences.d/99nginx'
+
+RUN apt update && apt install -y nginx=1.28.0* \
+ # Clean up
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+# Add a non-root user (useful for containers that need it)
+RUN groupadd -r vpp && useradd -r -g vpp -s /bin/bash vpp
+
+# Set default command
+CMD ["/bin/bash"]
--- /dev/null
+# nginx container that uses the base image
+ARG UBUNTU_VERSION=22.04
+FROM localhost:5001/vpp-test-base:latest
+
+# nginx is now installed in the base image
+
+COPY resources/nginx/nginx.conf /nginx.conf
+COPY script/nginx_ldp.sh /usr/bin/nginx_ldp.sh
+
+ENV VCL_CONFIG=/tmp/nginx/vcl.conf
+ENV LDP=/usr/lib/libvcl_ldpreload.so
+ENV LDP_DEBUG=0
+ENV VCL_DEBUG=0
+ENV LDP_SID_BIT=8
+
+# copy vpp-data last to take advantage of caching (do not change)
+COPY vpp-data/lib/* /usr/lib/
+
+ENTRYPOINT ["nginx_ldp.sh", "nginx", "-c", "/nginx.conf"]
--- /dev/null
+# VPP container that uses the base image
+ARG UBUNTU_VERSION=22.04
+FROM localhost:5001/vpp-test-base:latest
+
+# We don't need to install these packages as they're in the base image
+# Just install anything specific to VPP that isn't in the base
+
+ARG OS_ARCH
+RUN echo "I'm building for $OS_ARCH"
+
+ENV DIR=vpp-data/lib/vpp_plugins
+COPY \
+ $DIR/af_packet_plugin.so \
+ $DIR/hs_apps_plugin.so \
+ $DIR/http_plugin.so \
+ $DIR/http_unittest_plugin.so \
+ $DIR/unittest_plugin.so \
+ $DIR/quic_plugin.so \
+ $DIR/quic_quicly_plugin.so \
+ $DIR/hsi_plugin.so \
+ $DIR/http_static_plugin.so \
+ $DIR/ping_plugin.so \
+ $DIR/nsim_plugin.so \
+ $DIR/prom_plugin.so \
+ $DIR/tlsopenssl_plugin.so \
+ $DIR/mactime_plugin.so \
+ $DIR/arping_plugin.so \
+ /usr/lib/$OS_ARCH-linux-gnu/vpp_plugins/
+
+COPY vpp-data/bin/vpp /usr/bin/
+COPY vpp-data/bin/vppctl /usr/bin/
+COPY vpp-data/bin/vpp_echo /usr/bin/
+COPY vpp-data/bin/vcl_* /usr/bin/
+COPY vpp-data/lib/*.so /usr/lib/
+
+# Group already created in base image
+
+ENTRYPOINT ["tail", "-f", "/dev/null"]
--- /dev/null
+# wrk HTTP benchmarking container that uses the base image
+ARG UBUNTU_VERSION=22.04
+FROM localhost:5001/vpp-test-base:latest
+
+# wrk is installed in the base image
+
+ENTRYPOINT ["wrk"]
--- /dev/null
+#!/bin/bash
+# Script to set up a local Docker registry
+
+set -e
+
+DOCKER_LOGIN_SCRIPT="/scratch/nomad/.docker-ro/dlogin.sh"
+if [ -x "$DOCKER_LOGIN_SCRIPT" ] ; then
+ $DOCKER_LOGIN_SCRIPT
+fi
+
+# Check if Docker is running
+if ! docker info &>/dev/null; then
+ echo "Error: Docker is not running. Please start Docker and try again."
+ exit 1
+fi
+
+# Registry container name
+REGISTRY_NAME="local-registry"
+REGISTRY_PORT=${1:-5001}
+
+# Check if registry container is already running
+if docker container inspect "$REGISTRY_NAME" &>/dev/null; then
+ echo "=== Local registry '$REGISTRY_NAME' is already running ==="
+ REGISTRY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$REGISTRY_NAME")
+ echo "Registry is available at: localhost:$REGISTRY_PORT or $REGISTRY_IP:$REGISTRY_PORT"
+else
+ echo "=== Setting up local Docker registry ==="
+
+ # Create a new registry container
+ docker run -d \
+ --name "$REGISTRY_NAME" \
+ --restart=always \
+ -p "$REGISTRY_PORT:5000" \
+ -v /var/lib/registry:/var/lib/registry \
+ registry:2
+
+ REGISTRY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$REGISTRY_NAME")
+ echo "Registry container created successfully!"
+ echo "Registry is available at: localhost:$REGISTRY_PORT or $REGISTRY_IP:$REGISTRY_PORT"
+
+ # Configure Docker to trust this insecure registry
+ echo "=== Configuring Docker to trust insecure registry ==="
+ if [ -f /etc/docker/daemon.json ]; then
+ # Check if the file already has an insecure-registries entry
+ if grep -q "insecure-registries" /etc/docker/daemon.json; then
+ echo "Insecure registries already configured. Please make sure 'localhost:$REGISTRY_PORT' is included."
+ else
+ echo "Adding 'localhost:$REGISTRY_PORT' to insecure-registries in /etc/docker/daemon.json"
+ echo "You may need to restart Docker for changes to take effect"
+ echo "Please add the following to /etc/docker/daemon.json:"
+ echo "{
+ \"insecure-registries\": [\"localhost:$REGISTRY_PORT\"]
+}"
+ fi
+ else
+ echo "Creating /etc/docker/daemon.json with insecure-registries configuration"
+ echo "You may need to restart Docker for changes to take effect"
+ echo "Please create /etc/docker/daemon.json with the following content:"
+ echo "{
+ \"insecure-registries\": [\"localhost:$REGISTRY_PORT\"]
+}"
+ fi
+fi
+
+echo ""
+echo "=== Local Registry Setup Complete ==="
+echo "To use the local registry, prefix your image tags with 'localhost:$REGISTRY_PORT/'"
+echo "For example: localhost:$REGISTRY_PORT/hs-test/vpp:latest"
--- /dev/null
+package main
+
+import (
+ "fmt"
+ "os"
+ "testing"
+ "time"
+
+ . "fd.io/kube-test/infra"
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+)
+
+var _ = ReportAfterSuite("VPP version under test", func(report Report) {
+ for i := range report.SpecReports {
+ specReport := report.SpecReports[i]
+ for j := range specReport.ReportEntries {
+ reportEntry := specReport.ReportEntries[j]
+ if reportEntry.Name == "VPP version" {
+ fmt.Println(reportEntry.Value)
+ return
+ }
+ }
+ }
+})
+
+func TestKube(t *testing.T) {
+ TestTimeout = time.Minute * time.Duration(*Timeout)
+
+ // creates a file with PPID, used for 'make cleanup-kube'
+ ppid := fmt.Sprint(os.Getppid())
+ ppid = ppid[:len(ppid)-1]
+ f, _ := os.Create(".last_ppid")
+ f.Write([]byte(ppid))
+ f.Close()
+
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Kube Test")
+ if *DryRun || *IsPersistent {
+ fmt.Println("\033[36m" + "Use 'make cleanup-kube' to remove pods " +
+ "and namespaces. \nPPID: " + ppid + "\033[0m")
+ }
+}
--- /dev/null
+module fd.io/kube-test
+
+go 1.23.8
+
+toolchain go1.23.10
+
+require (
+ github.com/onsi/ginkgo/v2 v2.23.3
+ github.com/onsi/gomega v1.37.0
+ gopkg.in/yaml.v3 v3.0.1
+ k8s.io/api v0.30.2
+)
+
+require (
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+ github.com/emicklei/go-restful/v3 v3.11.2 // indirect
+ github.com/go-openapi/jsonpointer v0.21.0 // indirect
+ github.com/go-openapi/jsonreference v0.21.0 // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
+ github.com/google/gnostic-models v0.6.8 // indirect
+ github.com/google/gofuzz v1.2.0 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/gorilla/websocket v1.5.1 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/moby/spdystream v0.2.0 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+ github.com/spf13/pflag v1.0.6 // indirect
+ golang.org/x/net v0.37.0 // indirect
+ golang.org/x/oauth2 v0.18.0 // indirect
+ golang.org/x/term v0.30.0 // indirect
+ google.golang.org/appengine v1.6.8 // indirect
+ gopkg.in/inf.v0 v0.9.1 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
+ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
+ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
+ sigs.k8s.io/yaml v1.4.0 // indirect
+)
+
+require (
+ github.com/a8m/envsubst v1.4.2
+ github.com/go-logr/logr v1.4.2 // indirect
+ github.com/go-openapi/swag v0.23.0 // indirect
+ github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/google/go-cmp v0.7.0 // indirect
+ github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
+ github.com/imdario/mergo v0.3.16 // indirect
+ github.com/joho/godotenv v1.5.1
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ golang.org/x/sys v0.31.0 // indirect
+ golang.org/x/text v0.24.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
+ golang.org/x/tools v0.30.0 // indirect
+ google.golang.org/protobuf v1.36.5 // indirect
+ k8s.io/apimachinery v0.30.2
+ k8s.io/client-go v0.30.2
+ k8s.io/klog/v2 v2.120.1 // indirect
+ k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
+)
--- /dev/null
+github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg=
+github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU=
+github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
+github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
+github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
+github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
+github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
+github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
+github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
+github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
+github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
+github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
+github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
+github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0=
+github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
+github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
+github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
+github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
+golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
+golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
+golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
+golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
+golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
+golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
+golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
+google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI=
+k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
+k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
+k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
+k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50=
+k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs=
+k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
+k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
+k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak=
+k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
+sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
--- /dev/null
+package kube_test
+
+import (
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ . "github.com/onsi/gomega"
+)
+
+func (s *BaseSuite) AssertNil(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).To(BeNil(), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertNotNil(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).ToNot(BeNil(), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertEqual(expected, actual any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).To(Equal(expected), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertNotEqual(expected, actual any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).ToNot(Equal(expected), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertContains(testString, contains any, msgAndArgs ...any) {
+ ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).To(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertNotContains(testString, contains any, msgAndArgs ...any) {
+ ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).ToNot(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertEmpty(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).To(BeEmpty(), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertNotEmpty(object any, msgAndArgs ...any) {
+ ExpectWithOffset(2, object).ToNot(BeEmpty(), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertMatchError(actual, expected error, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).To(MatchError(expected), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertGreaterEqual(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically(">=", expected), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertGreaterThan(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically(">", expected), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertLessEqual(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically("<=", expected), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertLessThan(actual, expected any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically("<", expected), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertEqualWithinThreshold(actual, expected, threshold any, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeNumerically("~", expected, threshold), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertTimeEqualWithinThreshold(actual, expected time.Time, threshold time.Duration, msgAndArgs ...any) {
+ ExpectWithOffset(2, actual).Should(BeTemporally("~", expected, threshold), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertHttpStatus(resp *http.Response, expectedStatus int, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPStatus(expectedStatus), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertHttpHeaderWithValue(resp *http.Response, key string, value any, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue(key, value), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertHttpHeaderNotPresent(resp *http.Response, key string, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp.Header.Get(key)).To(BeEmpty(), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertHttpContentLength(resp *http.Response, expectedContentLen int64, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue("Content-Length", strconv.FormatInt(expectedContentLen, 10)), msgAndArgs...)
+}
+
+func (s *BaseSuite) AssertHttpBody(resp *http.Response, expectedBody string, msgAndArgs ...any) {
+ ExpectWithOffset(2, resp).To(HaveHTTPBody(expectedBody), msgAndArgs...)
+}
+
+// Coverage builds take longer to finish -> assert timeout is set to 'TestTimeout - 30 seconds' to let the test finish properly
+func (s *BaseSuite) AssertChannelClosed(timeout time.Duration, channel chan error) {
+ if *IsCoverage && timeout > time.Second*30 {
+ timeout = TestTimeout - time.Second*30
+ s.Log("Coverage build, assert timeout is set to %s", timeout.String())
+ }
+ EventuallyWithOffset(2, channel).WithTimeout(timeout).Should(BeClosed())
+}
+
+// Pass the parsed result struct and the minimum amount of data transferred in MB.
+// Won't do anything when testing a coverage build.
+func (s *BaseSuite) AssertIperfMinTransfer(result IPerfResult, minTransferred int) {
+ if *IsCoverage {
+ s.Log("Coverage build; not asserting")
+ return
+ }
+ if result.Start.Details.Protocol == "TCP" {
+ s.AssertGreaterEqual(result.End.TcpReceived.MBytes, minTransferred)
+ } else {
+ s.AssertGreaterEqual(result.End.Udp.MBytes, minTransferred)
+ }
+}
-package hst_kind
+package kube_test
import (
"context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
-func (s *KindSuite) loadDockerImages() {
+func (s *KubeSuite) loadDockerImages() {
s.Log("This may take a while. If you encounter problems, " +
"try loading docker images manually: 'kind load docker-image [image]'")
}
}
-func (s *KindSuite) createNamespace(name string) {
+func (s *KubeSuite) createNamespace(name string) {
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: name,
s.Log("Namespace '%s' created", name)
}
-func (s *KindSuite) deletePod(namespace string, podName string) error {
+func (s *KubeSuite) 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) deleteNamespace(namespace string) error {
+func (s *KubeSuite) deleteNamespace(namespace string) error {
return s.ClientSet.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{})
}
-func (s *KindSuite) DeployPod(pod *Pod) {
+func (s *KubeSuite) DeployPod(pod *Pod) {
pod.CreatedPod = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: s.Namespace,
Name: pod.Name,
Labels: map[string]string{
- "app": "HST",
+ "app": "Kube-Test",
},
Annotations: map[string]string{
"cni.projectcalico.org/vppVcl": "enable",
-package hst_kind
+package kube_test
import (
"bytes"
"context"
+ "errors"
+ "fmt"
"os"
"os/exec"
"slices"
"text/template"
- . "fd.io/hs-test/infra/common"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/remotecommand"
)
type Pod struct {
- suite *KindSuite
+ suite *KubeSuite
Name string
Image string
ContainerName string
Pods []PodYaml `yaml:"pods"`
}
-func (s *KindSuite) LoadPodConfigs() {
+func (s *KubeSuite) LoadPodConfigs() {
data, err := os.ReadFile("kubernetes/pod-definitions.yaml")
s.AssertNil(err)
}
}
-func newPod(suite *KindSuite, input PodYaml) (*Pod, error) {
+func newPod(suite *KubeSuite, input PodYaml) (*Pod, error) {
var pod = new(Pod)
pod.suite = suite
pod.Name = input.Name + suite.Ppid
return pod, nil
}
-func (s *KindSuite) initPods() {
+func (s *KubeSuite) initPods() {
s.Pods.Ab = s.getPodsByName("ab")
s.Pods.ClientGeneric = s.getPodsByName("client-generic")
s.Pods.ServerGeneric = s.getPodsByName("server-generic")
s.Pods.NginxProxy = s.getPodsByName("nginx-proxy")
}
-func (s *KindSuite) getPodsByName(podName string) *Pod {
+func (s *KubeSuite) getPodsByName(podName string) *Pod {
return s.AllPods[podName+s.Ppid]
}
executor, err := remotecommand.NewSPDYExecutor(pod.suite.Config, "POST", req.URL())
if err != nil {
- pod.suite.Log("Error creating executor: %s", err.Error())
+ return "", err
}
err = executor.StreamWithContext(ctx, remotecommand.StreamOptions{
Tty: true,
})
- output := stdout.String() + stderr.String()
-
- if err != nil {
- return output, err
+ output := stdout.String()
+ if stderr.String() != "" {
+ err = errors.New(stderr.String())
}
- return output, nil
+ return output, err
}
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)
+ f, err := os.CreateTemp(LogDir, "kube-config")
+ pod.suite.AssertNil(err, fmt.Sprint(err))
defer os.Remove(f.Name())
err = template.Execute(f, values)
--- /dev/null
+package kube_test
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+ "time"
+
+ "github.com/joho/godotenv"
+ . "github.com/onsi/ginkgo/v2"
+)
+
+var IsCoverage = flag.Bool("coverage", false, "use coverage run config")
+var IsPersistent = flag.Bool("persist", false, "persists topology config")
+var IsVerbose = flag.Bool("verbose", false, "verbose test output")
+var WhoAmI = flag.String("whoami", "root", "what user ran kube-test")
+var IsVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
+var DryRun = flag.Bool("dryrun", false, "set up containers but don't run tests")
+var Timeout = flag.Int("timeout", 30, "test timeout override (in minutes)")
+var TestTimeout time.Duration
+
+const (
+ LogDir string = "/tmp/kube-test/"
+)
+
+type BaseSuite struct {
+ Ppid string
+ Logger *log.Logger
+ LogFile *os.File
+}
+
+func init() {
+ cmd := exec.Command("mkdir", "-p", LogDir)
+ if err := cmd.Run(); err != nil {
+ panic(err)
+ }
+}
+
+func (s *BaseSuite) Skip(args string) {
+ Skip(args)
+}
+
+func (s *BaseSuite) SetupTest() {
+ TestCounterFunc()
+ s.Log("[* TEST SETUP]")
+}
+
+func (s *BaseSuite) SetupSuite() {
+ s.CreateLogger()
+ s.Log("[* SUITE SETUP]")
+ s.Ppid = fmt.Sprint(os.Getppid())
+ // remove last number so we have space to prepend a process index (interfaces have a char limit)
+ s.Ppid = s.Ppid[:len(s.Ppid)-1]
+}
+
+func (s *BaseSuite) TeardownTest() {
+ if *IsPersistent || *DryRun {
+ s.Skip("Skipping test teardown")
+ }
+ s.Log("[* TEST TEARDOWN]")
+}
+
+func (s *BaseSuite) TeardownSuite() {
+ if *IsPersistent || *DryRun {
+ s.Skip("Skipping suite teardown")
+ }
+ s.Log("[* SUITE TEARDOWN]")
+}
+
+func (s *BaseSuite) GetCurrentSuiteName() string {
+ return CurrentSpecReport().ContainerHierarchyTexts[0]
+}
+
+func (s *BaseSuite) CreateLogger() {
+ suiteName := s.GetCurrentSuiteName()
+ var err error
+ s.LogFile, err = os.Create("summary/" + suiteName + ".log")
+ if err != nil {
+ Fail("Unable to create log file.")
+ }
+ s.Logger = log.New(io.Writer(s.LogFile), "", log.LstdFlags)
+}
+
+// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter
+// to keep console tidy
+func (s *BaseSuite) Log(log any, arg ...any) {
+ var logStr string
+ if len(arg) == 0 {
+ logStr = fmt.Sprint(log)
+ } else {
+ logStr = fmt.Sprintf(fmt.Sprint(log), arg...)
+ }
+ logs := strings.Split(logStr, "\n")
+
+ for _, line := range logs {
+ s.Logger.Println(line)
+ }
+ if *IsVerbose {
+ GinkgoWriter.Println(logStr)
+ }
+}
+
+// sets CALICO_NETWORK_CONFIG, ADDITIONAL_VPP_CONFIG, env vars, applies configs and rollout restarts cluster
+func (s *KubeSuite) SetMtuAndRestart(CALICO_NETWORK_CONFIG string, ADDITIONAL_VPP_CONFIG string) {
+ os.Setenv("CALICO_NETWORK_CONFIG", CALICO_NETWORK_CONFIG)
+ os.Setenv("ADDITIONAL_VPP_CONFIG", ADDITIONAL_VPP_CONFIG)
+ s.AssertNil(godotenv.Load("kubernetes/.vars"))
+
+ s.Envsubst("kubernetes/calico-config-template.yaml", "kubernetes/calico-config.yaml")
+
+ cmd := exec.Command("kubectl", "apply", "-f", "kubernetes/calico-config.yaml")
+ s.Log(cmd.String())
+ o, err := cmd.CombinedOutput()
+ s.Log(string(o))
+ s.AssertNil(err)
+
+ cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "restart", "ds/calico-vpp-node")
+ s.Log(cmd.String())
+ o, err = cmd.CombinedOutput()
+ s.Log(string(o))
+ s.AssertNil(err)
+
+ cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "status", "ds/calico-vpp-node")
+ s.Log(cmd.String())
+ o, err = cmd.CombinedOutput()
+ s.Log(string(o))
+ s.AssertNil(err)
+
+ cmd = exec.Command("kubectl", "-n", "calico-system", "rollout", "status", "ds/calico-node")
+ s.Log(cmd.String())
+ o, err = cmd.CombinedOutput()
+ s.Log(string(o))
+ s.AssertNil(err)
+
+ // let vpp-dataplane recover, should help with stability issues
+ s.Log("Waiting for 10 seconds")
+ time.Sleep(time.Second * 10)
+}
-package hst_kind
+package kube_test
import (
"context"
"fmt"
"os"
- "os/exec"
"reflect"
"regexp"
"runtime"
"strings"
- "time"
- . "fd.io/hs-test/infra/common"
"github.com/a8m/envsubst"
. "github.com/onsi/ginkgo/v2"
- "github.com/joho/godotenv"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
-type KindSuite struct {
- HstCommon
+type KubeSuite struct {
+ BaseSuite
ClientSet *kubernetes.Clientset
Config *rest.Config
Namespace string
}
var imagesLoaded bool
-var kindTests = map[string][]func(s *KindSuite){}
+var kubeTests = map[string][]func(s *KubeSuite){}
const VclConfIperf = "echo \"vcl {\n" +
"rx-fifo-size 4000000\n" +
"app-socket-api abstract:vpp/session\n" +
"}\" > /vcl.conf"
-func RegisterKindTests(tests ...func(s *KindSuite)) {
- kindTests[GetTestFilename()] = tests
+func RegisterKubeTests(tests ...func(s *KubeSuite)) {
+ kubeTests[GetTestFilename()] = tests
}
-func (s *KindSuite) SetupTest() {
+func (s *KubeSuite) SetupTest() {
s.MainContext = context.Background()
- s.HstCommon.SetupTest()
+ s.BaseSuite.SetupTest()
}
-func (s *KindSuite) SetupSuite() {
- s.HstCommon.SetupSuite()
+func (s *KubeSuite) SetupSuite() {
+ s.BaseSuite.SetupSuite()
s.CurrentlyRunning = make(map[string]*Pod)
s.LoadPodConfigs()
}
}
-// sets CALICO_NETWORK_CONFIG, ADDITIONAL_VPP_CONFIG, env vars, applies configs and rollout restarts cluster
-func (s *KindSuite) SetMtuAndRestart(CALICO_NETWORK_CONFIG string, ADDITIONAL_VPP_CONFIG string) {
- os.Setenv("CALICO_NETWORK_CONFIG", CALICO_NETWORK_CONFIG)
- os.Setenv("ADDITIONAL_VPP_CONFIG", ADDITIONAL_VPP_CONFIG)
- s.AssertNil(godotenv.Load("kubernetes/.vars"))
-
- s.Envsubst("kubernetes/calico-config-template.yaml", "kubernetes/calico-config.yaml")
-
- cmd := exec.Command("kubectl", "apply", "-f", "kubernetes/calico-config.yaml")
- s.Log(cmd.String())
- o, err := cmd.CombinedOutput()
- s.Log(string(o))
- s.AssertNil(err)
-
- cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "restart", "ds/calico-vpp-node")
- s.Log(cmd.String())
- o, err = cmd.CombinedOutput()
- s.Log(string(o))
- s.AssertNil(err)
-
- cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "status", "ds/calico-vpp-node")
- s.Log(cmd.String())
- o, err = cmd.CombinedOutput()
- s.Log(string(o))
- s.AssertNil(err)
-
- cmd = exec.Command("kubectl", "-n", "calico-system", "rollout", "status", "ds/calico-node")
- s.Log(cmd.String())
- o, err = cmd.CombinedOutput()
- s.Log(string(o))
- s.AssertNil(err)
-
- // let vpp-dataplane recover (tests might timeout otherwise)
- s.Log("Waiting for 10 seconds")
- time.Sleep(time.Second * 10)
-}
-
-func (s *KindSuite) TeardownTest() {
- s.HstCommon.TeardownTest()
+func (s *KubeSuite) TeardownTest() {
+ s.BaseSuite.TeardownTest()
if len(s.CurrentlyRunning) != 0 {
s.Log("Removing:")
for _, pod := range s.CurrentlyRunning {
}
}
-func (s *KindSuite) TeardownSuite() {
- s.HstCommon.TeardownSuite()
+func (s *KubeSuite) TeardownSuite() {
+ s.BaseSuite.TeardownSuite()
if len(s.CurrentlyRunning) == 0 {
return
}
// Quick and dirty fix for now. Runs 'ldd /usr/lib/libvcl_ldpreload.so'
// and searches for the first version string, then creates symlinks.
-func (s *KindSuite) FixVersionNumber(pods ...*Pod) {
+func (s *KubeSuite) FixVersionNumber(pods ...*Pod) {
regex := regexp.MustCompile(`lib.*\.so\.([0-9]+\.[0-9]+)`)
var match []string
for _, pod := range pods {
}
}
-func (s *KindSuite) CreateNginxConfig(pod *Pod) {
+func (s *KubeSuite) CreateNginxConfig(pod *Pod) {
values := struct {
Workers uint8
Port uint16
)
}
-func (s *KindSuite) Envsubst(inputPath string, outputPath string) {
+func (s *KubeSuite) Envsubst(inputPath string, outputPath string) {
o, err := envsubst.ReadFile(inputPath)
s.AssertNil(err)
os.WriteFile(outputPath, o, 0644)
}
-func (s *KindSuite) CreateNginxProxyConfig(pod *Pod) {
+func (s *KubeSuite) CreateNginxProxyConfig(pod *Pod) {
pod.Exec(context.TODO(), []string{"/bin/bash", "-c", "mkdir -p /tmp/nginx"})
values := struct {
Workers uint8
)
}
-var _ = Describe("KindSuite", Ordered, ContinueOnFailure, Label("Perf"), func() {
- var s KindSuite
+var _ = Describe("KubeSuite", Ordered, ContinueOnFailure, Label("Perf"), func() {
+ var s KubeSuite
BeforeAll(func() {
s.SetupSuite()
s.SetMtuAndRestart("", "")
s.TeardownSuite()
})
- for filename, tests := range kindTests {
+ for filename, tests := range kubeTests {
for _, test := range tests {
test := test
pc := reflect.ValueOf(test).Pointer()
-package hst_kind
+package kube_test
import (
"reflect"
"runtime"
"strings"
- . "fd.io/hs-test/infra/common"
. "github.com/onsi/ginkgo/v2"
)
type LargeMtuSuite struct {
- KindSuite
+ KubeSuite
}
var largeMtuTests = map[string][]func(s *LargeMtuSuite){}
}
func (s *LargeMtuSuite) SetupSuite() {
- s.KindSuite.SetupSuite()
+ s.KubeSuite.SetupSuite()
s.SetMtuAndRestart("mtu: 9000", "tcp { mtu 8960 }")
}
-package hst_common
+package kube_test
import (
"encoding/json"
"time"
)
+func boolPtr(b bool) *bool {
+ return &b
+}
+
+func int64Ptr(integer int64) *int64 {
+ return &integer
+}
+
func GetTestFilename() string {
_, filename, _, _ := runtime.Caller(2)
return filepath.Base(filename)
var startTime time.Time = time.Now()
func TestCounterFunc() {
- if ParallelTotal.Value.String() != "1" {
- return
- }
testCounter++
fmt.Printf("Test counter: %d\n"+
"Time elapsed: %.2fs\n",
} `json:"end"`
}
-func (s *HstCommon) ParseJsonIperfOutput(jsonResult []byte) IPerfResult {
+func (s *BaseSuite) ParseJsonIperfOutput(jsonResult []byte) IPerfResult {
var result IPerfResult
// VCL/LDP debugging can pollute output so find the first occurrence of a curly brace to locate the start of JSON data
return result
}
-func (s *HstCommon) LogJsonIperfOutput(result IPerfResult) {
+func (s *BaseSuite) LogJsonIperfOutput(result IPerfResult) {
s.Log("\n*******************************************\n"+
"%s\n"+
"[%s] %s:%d connected to %s:%d\n"+
"fmt"
"time"
- . "fd.io/hs-test/infra/common"
- . "fd.io/hs-test/infra/kind"
+ . "fd.io/kube-test/infra"
. "github.com/onsi/ginkgo/v2"
)
func init() {
- RegisterKindTests(KindTcpIperfVclTest, KindUdpIperfVclTest, NginxRpsTest, NginxProxyMirroringTest)
- RegisterLargeMtuTests(KindTcpIperfVclLargeMTUTest)
+ RegisterKubeTests(KubeTcpIperfVclTest, KubeUdpIperfVclTest, NginxRpsTest, NginxProxyMirroringTest)
+ RegisterLargeMtuTests(KubeTcpIperfVclLargeMTUTest)
}
const vcl string = "VCL_CONFIG=/vcl.conf"
const ldp string = "LD_PRELOAD=/usr/lib/libvcl_ldpreload.so"
-func kindIperfVclTest(s *KindSuite, clientArgs string) IPerfResult {
+func kubeIperfVclTest(s *KubeSuite, clientArgs string) IPerfResult {
s.DeployPod(s.Pods.ClientGeneric)
s.DeployPod(s.Pods.ServerGeneric)
- ctx, cancel := context.WithTimeout(s.MainContext, time.Second*40)
+ ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*2)
defer cancel()
+ defer func() {
+ o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c", "cat /iperf_server.log"})
+ s.Log(o)
+ s.AssertNil(err)
+ }()
_, err := s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", VclConfIperf})
s.AssertNil(err)
s.FixVersionNumber(s.Pods.ClientGeneric, s.Pods.ServerGeneric)
- iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -b 40g -c %s",
+ iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -4 -b 40g -c %s",
vcl, ldp, clientArgs, s.Pods.ServerGeneric.IpAddress)
o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c",
- vcl + " " + ldp + " iperf3 -s -D -4 -B " + s.Pods.ServerGeneric.IpAddress})
+ vcl + " " + ldp + " iperf3 -s -D --logfile /iperf_server.log -B " + s.Pods.ServerGeneric.IpAddress})
+ s.Log("Sleeping for 2s")
+ time.Sleep(time.Second * 2)
s.AssertNil(err, o)
- o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd})
+ o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd})
s.AssertNil(err, o)
result := s.ParseJsonIperfOutput([]byte(o))
s.LogJsonIperfOutput(result)
}
// TODO: use interfaces to avoid duplicated code
-func kindIperfVclMtuTest(s *LargeMtuSuite, clientArgs string) IPerfResult {
+func kubeIperfVclMtuTest(s *LargeMtuSuite, clientArgs string) IPerfResult {
s.DeployPod(s.Pods.ClientGeneric)
s.DeployPod(s.Pods.ServerGeneric)
- ctx, cancel := context.WithTimeout(s.MainContext, time.Second*40)
+ ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*2)
defer cancel()
+ defer func() {
+ o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c", "cat /iperf_server.log"})
+ s.Log(o)
+ s.AssertNil(err)
+ }()
_, err := s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", VclConfIperf})
s.AssertNil(err)
s.FixVersionNumber(s.Pods.ClientGeneric, s.Pods.ServerGeneric)
- iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -b 40g -c %s",
+ iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -4 -b 40g -c %s",
vcl, ldp, clientArgs, s.Pods.ServerGeneric.IpAddress)
o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c",
- vcl + " " + ldp + " iperf3 -s -D -4 -B " + s.Pods.ServerGeneric.IpAddress})
+ vcl + " " + ldp + " iperf3 -s -D --logfile /iperf_server.log -B " + s.Pods.ServerGeneric.IpAddress})
+ s.Log("Sleeping for 2s")
+ time.Sleep(time.Second * 2)
s.AssertNil(err, o)
- o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd})
+ o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd})
s.AssertNil(err, o)
result := s.ParseJsonIperfOutput([]byte(o))
s.LogJsonIperfOutput(result)
return result
}
-func KindTcpIperfVclTest(s *KindSuite) {
- s.AssertIperfMinTransfer(kindIperfVclTest(s, "-M 1460"), 2000)
+func KubeTcpIperfVclTest(s *KubeSuite) {
+ s.AssertIperfMinTransfer(kubeIperfVclTest(s, "-M 1460"), 2000)
}
-func KindTcpIperfVclLargeMTUTest(s *LargeMtuSuite) {
- s.AssertIperfMinTransfer(kindIperfVclMtuTest(s, "-M 8960"), 2000)
+func KubeTcpIperfVclLargeMTUTest(s *LargeMtuSuite) {
+ s.AssertIperfMinTransfer(kubeIperfVclMtuTest(s, "-M 8900"), 2000)
}
-func KindUdpIperfVclTest(s *KindSuite) {
- s.AssertIperfMinTransfer(kindIperfVclTest(s, "-l 1460 -u"), 2000)
+func KubeUdpIperfVclTest(s *KubeSuite) {
+ s.AssertIperfMinTransfer(kubeIperfVclTest(s, "-l 1460 -u"), 2000)
}
-func NginxRpsTest(s *KindSuite) {
- ctx, cancel := context.WithCancel(s.MainContext)
+func NginxRpsTest(s *KubeSuite) {
+ ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*3)
defer cancel()
s.DeployPod(s.Pods.Nginx)
s.AssertNil(err)
}
-func NginxProxyMirroringTest(s *KindSuite) {
- ctx, cancel := context.WithCancel(s.MainContext)
+func NginxProxyMirroringTest(s *KubeSuite) {
+ ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*3)
defer cancel()
s.DeployPod(s.Pods.Nginx)
--- /dev/null
+#!/usr/bin/env bash
+
+args=
+focused_test=0
+persist_set=0
+dryrun_set=0
+debug_set=0
+debug_build=
+ginkgo_args=
+tc_names=()
+skip_names=()
+dryrun=
+no_color=
+
+for i in "$@"
+do
+case "${i}" in
+ --persist=*)
+ persist="${i#*=}"
+ if [ "$persist" = "true" ]; then
+ args="$args -persist"
+ persist_set=1
+ fi
+ ;;
+ --verbose=*)
+ verbose="${i#*=}"
+ if [ "$verbose" = "true" ]; then
+ args="$args -verbose"
+ fi
+ ;;
+ --test=*)
+ tc_list="${i#*=}"
+ ginkgo_args="$ginkgo_args -v"
+ if [ "$tc_list" != "all" ]; then
+ focused_test=1
+ IFS=',' read -r -a tc_names <<< "$tc_list"
+ args="$args -verbose"
+ fi
+ ;;
+ --skip=*)
+ skip_list="${i#*=}"
+ IFS=',' read -r -a skip_names <<< "$skip_list"
+ ;;
+ --ginkgo_timeout=*)
+ ginkgo_args="$ginkgo_args --timeout=${i#*=}"
+ ;;
+ --repeat=*)
+ ginkgo_args="$ginkgo_args --repeat=${i#*=}"
+ ;;
+ --dryrun=*)
+ dryrun="${i#*=}"
+ if [ "$dryrun" = "true" ]; then
+ args="$args -dryrun"
+ dryrun_set=1
+ fi
+ ;;
+ --no_color=*)
+ no_color="${i#*=}"
+ if [ "$no_color" = "true" ]; then
+ ginkgo_args="$ginkgo_args --no-color"
+ fi
+ ;;
+ --timeout=*)
+ args="$args -timeout ${i#*=}"
+ ;;
+esac
+done
+
+if [ ${#tc_names[@]} -gt 1 ]
+then
+ focused_test=0
+fi
+
+for name in "${tc_names[@]}"; do
+ ginkgo_args="$ginkgo_args --focus $name"
+done
+
+for skip in "${skip_names[@]}"; do
+ ginkgo_args="$ginkgo_args --skip $skip"
+done
+
+if [ $focused_test -eq 0 ] && { [ $persist_set -eq 1 ] || [ $dryrun_set -eq 1 ]; }; then
+ echo -e "\e[1;31mpersist/dryrun flag is not supported while running all tests!\e[1;0m"
+ exit 2
+fi
+
+args="$args -whoami $(whoami)"
+
+if [ -n "${BUILD_NUMBER}" ]; then
+ ginkgo_args="$ginkgo_args --no-color"
+fi
+
+mkdir -p summary
+rm -f summary/*
+# shellcheck disable=SC2086
+CMD="go run github.com/onsi/ginkgo/v2/ginkgo --json-report=summary/report.json $ginkgo_args -- $args"
+echo "$CMD"
+$CMD
+exit_status=$?
+
+if [ $exit_status -ne 0 ]; then
+ jq -r '.[0] | .SpecReports[] | select((.State == "failed") or (.State == "timedout") or (.State == "panicked")) | select(.Failure != null) |
+"TestName:
+ \(.LeafNodeText)
+Suite:
+ \(.Failure.FailureNodeLocation.FileName)
+Message:\n"
++ (
+ if .ReportEntries? then
+ (.ReportEntries[] | select(.Name | contains("Backtrace")) |
+ "\tFull Back Trace:
+\(.Value.Representation | ltrimstr("{{red}}") | rtrimstr("{{/}}"))"
+ ) // "\(.Failure.Message)"
+ else
+ "parse error"
+ end
+)
++ (
+ if .Failure.Message == "A spec timeout occurred" then
+ "\n"
+ else
+ "\nFull Stack Trace:
+\(.Failure.Location.FullStackTrace)\n"
+ end
+)' summary/report.json > summary/failed-summary.log \
+&& echo "Summary generated -> summary/failed-summary.log"
+ exit $exit_status
+else
+ exit $exit_status
+fi
definitions:
image-names:
- - image: &hs-test
- name: "hs-test/vpp:latest"
+ - image: &kube-test
+ name: "kube-test/vpp:latest"
- image: &nginx-ldp
- name: "hs-test/nginx-ldp:latest"
+ name: "kube-test/nginx-ldp:latest"
- image: &ab
- name: "hs-test/ab:latest"
+ name: "kube-test/ab:latest"
container-names:
- container: &client
namespace-names:
- namespace: &defaultNs
- name: "hs-test"
+ name: "kube-test"
worker-names:
- worker: &worker1
pods:
- name: "client-generic"
image:
- - <<: *hs-test
+ - <<: *kube-test
container:
- <<: *client
worker:
- name: "server-generic"
image:
- - <<: *hs-test
+ - <<: *kube-test
container:
- <<: *server
worker:
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIDZTCCAk2gAwIBAgIUF116CAipHqQBCyAEvNesV0u4u0swDQYJKoZIhvcNAQEL
+BQAwQjELMAkGA1UEBhMCU0sxEDAOBgNVBAgMB1ZwcExhbmQxITAfBgNVBAoMGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA1MjkxMDI0MjhaFw0yNDA1Mjgx
+MDI0MjhaMEIxCzAJBgNVBAYTAlNLMRAwDgYDVQQIDAdWcHBMYW5kMSEwHwYDVQQK
+DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCy40rDzrrHPGIyhP24hOBQefEgKD5uUGgSUyJTCur4yB/r2PGt
+LlfipKwDmNArmZuFOgKh8evipu2jYaxf4GHQmi7PGLddvPkqo5FWtVW8oAVJMcp+
+fwfs7OgkqtYD6Y7qjmjfXb9+rMpPN8WZ7cKbJwZpF3lf8GGaLqRmPiQg2j8qzcVy
+nz8cIwBZP8BJVclA9GIagijY7Zcmz0HnTPrPoLMeyLJOTqPMfkUYA2H2eHeISkQP
+BeoFoiwCI5eM35UiWiLyiv9Kojn4BHx6MLrfKBjV13WtcRMgYm5VftsWOZ92lmHm
+bpj9mGgtd84JWtWxs33oG4mNRSAeujf9AE5VAgMBAAGjUzBRMB0GA1UdDgQWBBTj
+s+A5M/Cao+0Phgg6xFBKIPxLqjAfBgNVHSMEGDAWgBTjs+A5M/Cao+0Phgg6xFBK
+IPxLqjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3EcGDby5u
+cEGjgAFR18kH4ztnYUdZUrPI72sOFfjRLtJpx00n759SBawqNW1Y2a1QRd+GgUBK
+YpYd2gzWYFjf/4c5BN4SrjeZGnQ8N0YomqqGKvOQO0YdYK4i/lWJjLRaLiVBn9EX
+Z+odYhGqQgoAJHnm5Mmqhx9ts8qxZLbdsh+T93mKvj+/yuai2Is+AJfLgZpdKPQN
+bCoZemRm+nghRvEP8aX/469wiz7SOLqUzxrTOtXV48wTU5LWLDCs1lF9ZdGHR9/r
+vj8unnEHIZiH3ZjN7OgaAoNHZE26Ywbmllc/a0vPw8iHdrLe7+Wtp4zXe2rcxhW7
+b+X1/yRCZ+Wg
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCy40rDzrrHPGIy
+hP24hOBQefEgKD5uUGgSUyJTCur4yB/r2PGtLlfipKwDmNArmZuFOgKh8evipu2j
+Yaxf4GHQmi7PGLddvPkqo5FWtVW8oAVJMcp+fwfs7OgkqtYD6Y7qjmjfXb9+rMpP
+N8WZ7cKbJwZpF3lf8GGaLqRmPiQg2j8qzcVynz8cIwBZP8BJVclA9GIagijY7Zcm
+z0HnTPrPoLMeyLJOTqPMfkUYA2H2eHeISkQPBeoFoiwCI5eM35UiWiLyiv9Kojn4
+BHx6MLrfKBjV13WtcRMgYm5VftsWOZ92lmHmbpj9mGgtd84JWtWxs33oG4mNRSAe
+ujf9AE5VAgMBAAECggEANwiZ/bdh2t2G0Ef9zoCCif+Z4OzAmCuAePK+gpG/TB41
+Q9eQMlkpjH5gtRKUKHWvVMNOAAhvK2FzhmoMH8rmDMkCUZAnCV2TwjxkACr1X3xT
+Y/s/cr8d7xPLL0ynXrjB0QNS3DT5Lr111/0ue3acAiN1Y2tnWc6YGFj1FsdTUg+O
+zRysrpNUp3LAK+MXIhAXMCGKOOLxpjeyrcnUokH0I8e06of1AfAHX8jTn65MG5Ex
+n9wBYPl+u2J3SjILHoqBKjcSoNILUfBN9mQGeXhoqCzwcnygDtOxIu9xgu2nCcJr
+C1R/WXoQ8Jr6wa1n0aEVXDJeOEK9kKXLTt2/I4HB2QKBgQDemLy+o2/tbFwlU2Xy
+8/tZa30kfLCAZ+kq+lE3Kkfqt3pPYzH+lfO7u/UWtavKRQRdsKsNKbpe/EdGq7c4
+YN3L1KG5JiIo3TxilUPilYacGHklfMMbEK7cs8Jebsl6rL7BgnKuqlXGY0HEEx8L
+XqIKN1RdzL04WLOiA8qDGwYp7wKBgQDNu3DECCTkTa+mZdNDRntoffkgyd0AnwPA
+PEf43BHORpKcfGwFIrf8QWRXcLdh72Yrc9o3D53GCq+NSYGPL2OiY+/3HoAy1mH1
+EBgS08qfkZBKr6+VGjWuVAlD2m2jW+AhGXMS+Lu4yzK3V+0EzlAu4WZVBUngg1//
+6ZtyvXLf+wKBgQCozmO0nvUutFJc7BYQXP5sHZvVo8mmVyb4NMSKdUH8ug/DTJKJ
+YuZnpG6FPlh9GEHrWyMc5Fw11FOpQGe+FZeeEC5k3ophOwWkLVZB6useTWDyEN9V
+Ex3IuXnZa2LX6VDwJyEZXIuX24XwUB/m22k/Hh6Y079bj8kKQJ2/NytBeQKBgQCZ
+RGMmJ8sUKqwJEyLoo8GcfvzyaHC03cI1nLMhuxGo0vq2ihsPWGYpD65pVhfIZkl/
+ZbfT/VZVC/DtGS3kNjHL8Rf8ykRHm18u6uaEYDQ73H3apjfwpK4JSaH9YuT7Jp87
+CXKpV5TCft8xp9d0FR+3TUSnYmE/WaBTTv335RuHsQKBgCFLyxzs0hM/MhCLHJ6b
+AqyNPz36Xcwsgit1Svhwm1IC6FqkSJl3cRKhp1AP5w6ktUfUGNpF/TYI3x2jCg/m
+c0nwmqi/3Cha64XKJcI4iT2+lyuE8jXovMdNiJEEKCDalpyYJbhzRaLsoSFSbiD1
+mFDl8/aNVaQKDDboSuj9AkKs
+-----END PRIVATE KEY-----
--- /dev/null
+<http>
+ <title>nginx docker with quic</title>
+<body>
+ <p>Greetings!</p>
+</body>
+</http>
--- /dev/null
+master_process on;
+worker_rlimit_nofile 10240;
+worker_processes {{.Workers}};
+daemon off;
+
+events {
+ use epoll;
+ worker_connections 10240;
+ accept_mutex off;
+ multi_accept off;
+}
+
+http {
+ keepalive_timeout 300s;
+ keepalive_requests 1000000;
+ sendfile on;
+ server {
+ listen {{.Port}};
+ listen [::]:{{.Port}};
+ root /usr/share/nginx;
+ index index.html index.htm;
+ location /return_ok
+ {
+ return 200 '';
+ }
+ location /64B.json
+ {
+ return 200 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+ }
+ }
+}
--- /dev/null
+master_process on;
+worker_processes 2;
+daemon off;
+
+error_log /tmp/nginx/{{.LogPrefix}}-error.log info;
+
+events {
+ use epoll;
+ accept_mutex off;
+ multi_accept off;
+}
+
+http {
+ quic_gso on;
+ quic_retry off;
+
+ access_log /tmp/nginx/{{.LogPrefix}}-access.log;
+ keepalive_timeout 300s;
+ sendfile on;
+ server {
+ listen {{.Address}}:{{.Port}} quic;
+ root /usr/share/nginx;
+ ssl_certificate /etc/nginx/ssl/localhost.crt;
+ ssl_certificate_key /etc/nginx/ssl/localhost.key;
+ index index.html index.htm;
+ }
+}
--- /dev/null
+master_process on;
+worker_processes {{.Workers}};
+worker_rlimit_nofile 102400;
+daemon off;
+
+error_log /tmp/nginx/{{.LogPrefix}}-error.log info;
+
+events {
+ use epoll;
+ worker_connections 102400;
+ accept_mutex off;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ access_log off;
+
+ keepalive_timeout 300;
+ keepalive_requests 1000000;
+
+ proxy_connect_timeout 300;
+ large_client_header_buffers 4 512k;
+ client_max_body_size 3000m;
+ client_header_buffer_size 2048m;
+ client_body_buffer_size 1024m;
+ proxy_buffers 16 10240k;
+ proxy_buffer_size 10240k;
+
+ gzip on;
+
+ upstream bk {
+ server {{.Server}}:{{.Upstream1}};
+ keepalive 30000;
+ }
+ upstream bk1 {
+ server {{.Server}}:{{.Upstream2}};
+ keepalive 30000;
+ }
+ upstream bk2 {
+ server {{.Server}}:{{.Upstream3}};
+ keepalive 30000;
+ }
+
+ server {
+ access_log /tmp/nginx/{{.LogPrefix}}-access.log;
+ listen {{.Port}};
+ server_name {{.Proxy}};
+
+ server_tokens off;
+
+ proxy_redirect off;
+
+ location / {
+ root html;
+ index index.html index.htm;
+ proxy_pass http://bk;
+ proxy_set_header Connection "";
+ proxy_set_header X-Original-URI $request_uri;
+ proxy_set_header Host $host:$server_port;
+ chunked_transfer_encoding on;
+ proxy_http_version 1.1;
+ mirror /mimic1;
+ mirror /mimic2;
+ mirror_request_body on;
+ }
+ location /mimic1 {
+ proxy_pass http://bk1$request_uri;
+ proxy_set_header X-Original-URI $request_uri;
+ proxy_set_header Connection "";
+ chunked_transfer_encoding on;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host:$server_port;
+ }
+ location /mimic2 {
+ proxy_pass http://bk2$request_uri;
+ proxy_set_header X-Original-URI $request_uri;
+ proxy_set_header Host $host:$server_port;
+ proxy_set_header Connection "";
+ proxy_http_version 1.1;
+ chunked_transfer_encoding on;
+ }
+ }
+}
--- /dev/null
+master_process on;
+worker_rlimit_nofile 10240;
+worker_processes 2;
+daemon off;
+
+error_log /tmp/nginx/{{.LogPrefix}}-error.log info;
+
+events {
+ use epoll;
+ worker_connections 10240;
+ accept_mutex off;
+ multi_accept off;
+}
+
+http {
+ log_format access_log_fmt '$remote_addr - $remote_user [$time_local] '
+ '"$request" $status $body_bytes_sent '
+ '"$http_referer" "$http_user_agent" '
+ 'scheme=$scheme conn=$connection conn_reqs=$connection_requests';
+ keepalive_timeout 300s;
+ keepalive_requests 1000000;
+ client_body_timeout {{.Timeout}}s;
+ client_header_timeout {{.Timeout}}s;
+ send_timeout {{.Timeout}}s;
+ sendfile on;
+ server {
+ access_log /tmp/nginx/{{.LogPrefix}}-access.log access_log_fmt;
+ listen {{.Port}};
+ listen {{.PortSsl}} ssl;
+ server_name {{.Address}};
+ root /usr/share/nginx;
+ ssl_certificate /etc/nginx/ssl/localhost.crt;
+ ssl_certificate_key /etc/nginx/ssl/localhost.key;
+ http2 {{.Http2}};
+ index index.html index.htm;
+ # to allow POST on static pages
+ error_page 405 =200 $uri;
+ location ~ "/upload/([0-9a-zA-Z-.]*)$" {
+ alias /usr/share/nginx/upload/$1;
+ client_body_temp_path /tmp;
+ client_max_body_size 200M;
+ dav_methods PUT;
+ create_full_put_path off;
+ dav_access all:rw;
+ }
+ location /64B {
+ return 200 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+ }
+ location / {
+ sendfile on;
+ }
+ # HTTP2 will not wait for the post body and return 200
+ location = /test_upload {
+ proxy_pass http://127.0.0.1:{{.Port}}/dev-null;
+ }
+ location = /dev-null {
+ return 200;
+ }
+ # HTTP2 upload fix end
+ }
+}
--- /dev/null
+master_process on;
+worker_rlimit_nofile 10240;
+worker_processes 2;
+daemon off;
+
+error_log /tmp/nginx/{{.LogPrefix}}-error.log info;
+
+events {
+ use epoll;
+ worker_connections 10240;
+ accept_mutex off;
+ multi_accept off;
+}
+
+http {
+ keepalive_timeout 300s;
+ keepalive_requests 1000000;
+ sendfile on;
+ server {
+ access_log /tmp/nginx/{{.LogPrefix}}-access.log;
+ listen {{.Address}}:{{.Upstream1}};
+ listen {{.Address}}:{{.Upstream2}};
+ listen {{.Address}}:{{.Upstream3}};
+ root /usr/share/nginx;
+ index index.html index.htm;
+ location /64B {
+ return 200 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+ }
+ location / {
+ sendfile on;
+ }
+ }
+}
--- /dev/null
+vcl {
+ heapsize 64M
+ segment-size 4000000000
+ add-segment-size 4000000000
+ rx-fifo-size 4000000
+ tx-fifo-size 4000000
+ event-queue-size 100000
+ use-mq-eventfd
+ app-socket-api /tmp/nginx/var/run/app_ns_sockets/default
+}
--- /dev/null
+#!/usr/bin/env bash
+# Build script for all Docker images based on the common base image
+
+set -e
+
+# Get default architecture for multi-arch builds
+ARCH=${OS_ARCH:-$(dpkg --print-architecture)}
+CODENAME=$(lsb_release -cs)
+
+# Set up buildx configuration
+DOCKER_BUILD_DIR="/scratch/docker-build"
+DOCKER_CACHE_DIR="${DOCKER_BUILD_DIR}/docker_cache"
+DOCKER_HST_BUILDER="hst_builder"
+DOCKER_LOGIN_SCRIPT="/scratch/nomad/.docker-ro/dlogin.sh"
+
+if [ -d "${DOCKER_BUILD_DIR}" ] ; then
+ mkdir -p "${DOCKER_CACHE_DIR}"
+
+ if [ -x "$DOCKER_LOGIN_SCRIPT" ] ; then
+ $DOCKER_LOGIN_SCRIPT
+ fi
+
+ # Create buildx builder if it doesn't exist
+ if ! docker buildx ls --format "{{.Name}}" | grep -q "${DOCKER_HST_BUILDER}"; then
+ docker buildx create --use \
+ --driver-opt env.http_proxy="$HTTP_PROXY" \
+ --driver-opt env.https_proxy="$HTTP_PROXY" \
+ --driver-opt '"env.no_proxy='"$NO_PROXY"'"' \
+ --name=${DOCKER_HST_BUILDER} \
+ --driver=docker-container \
+ --use --bootstrap || true
+ fi
+
+ DOCKER_CACHE_ARGS="--builder=${DOCKER_HST_BUILDER} --load --cache-to type=local,dest=${DOCKER_CACHE_DIR},mode=max --cache-from type=local,src=${DOCKER_CACHE_DIR}"
+fi
+
+# Set the tag for the base image
+BASE_TAG=${BASE_TAG:-"localhost:5001/vpp-kube-test-base:latest"}
+
+echo "=== Building base image ==="
+# shellcheck disable=2086
+docker buildx build ${DOCKER_CACHE_ARGS} \
+ --build-arg UBUNTU_VERSION="${UBUNTU_VERSION:-22.04}" \
+ --build-arg http_proxy="$HTTP_PROXY" \
+ --build-arg https_proxy="$HTTP_PROXY" \
+ --build-arg HTTP_PROXY="$HTTP_PROXY" \
+ --build-arg HTTPS_PROXY="$HTTP_PROXY" \
+ -t $BASE_TAG -f docker/Dockerfile.base . || {
+ echo "Error: Failed to build base image"
+ exit 1
+}
+
+# Push the base image to the local registry
+docker push $BASE_TAG || {
+ echo "Error: Failed to push base image to local registry"
+ exit 1
+}
+
+# Function to build each image
+build_image() {
+ local dockerfile="docker/$1"
+ local tag=$2
+ local add_args="${3:-}"
+
+ if [ ! -f "$dockerfile" ]; then
+ echo "Warning: Dockerfile $dockerfile doesn't exist, skipping"
+ return 0
+ fi
+
+ echo "=== Building $tag from $dockerfile ==="
+ echo "Building with architecture: $ARCH"
+
+ # Check if the necessary files for VPP-based images are available
+ if [[ "$dockerfile" == *"vpp"* || "$dockerfile" == *"nginx"* || "$dockerfile" == *"vcl"* ]]; then
+ # Check for essential VPP files
+ for file in vpp-data/bin/vpp vpp-data/lib/*.so; do
+ if [ ! -e "$file" ]; then
+ echo "Warning: Required VPP file $file doesn't exist."
+ fi
+ done
+ fi
+
+ # Build the image
+ # shellcheck disable=2086
+ docker build \
+ --build-arg UBUNTU_VERSION="${UBUNTU_VERSION:-22.04}" \
+ --build-arg OS_ARCH="$ARCH" \
+ --build-arg CODENAME="$CODENAME" \
+ --build-arg http_proxy="$HTTP_PROXY" \
+ --build-arg https_proxy="$HTTP_PROXY" \
+ --build-arg HTTP_PROXY="$HTTP_PROXY" \
+ --build-arg HTTPS_PROXY="$HTTP_PROXY" \
+ $add_args \
+ -t "$tag" \
+ -f "$dockerfile" . || {
+ echo "Error: Failed to build $tag"
+ return 1
+ }
+
+ echo "=== Successfully built and pushed $tag ==="
+}
+
+# Build all standard images
+echo "=== Building standard images ==="
+build_image "Dockerfile.vpp" "kube-test/vpp"
+build_image "Dockerfile.nginx" "kube-test/nginx-ldp"
+build_image "Dockerfile.ab" "kube-test/ab"
+build_image "Dockerfile.wrk" "kube-test/wrk"
+
+# make cache directory multi-user friendly if it exists
+if [ -d "${DOCKER_CACHE_DIR}" ] ; then
+ chgrp -R docker "${DOCKER_CACHE_DIR}" 2>/dev/null || true
+ chmod -R g+rwx "${DOCKER_CACHE_DIR}" 2>/dev/null || true
+fi
+
+# cleanup detached images
+images=$(docker images --filter "dangling=true" -q --no-trunc)
+if [ -n "$images" ]; then
+ echo "=== Cleaning up dangling images ==="
+ # shellcheck disable=SC2086
+ docker rmi $images || true
+fi
+
+echo "=== All container images built successfully ==="
--- /dev/null
+#!/usr/bin/env bash
+
+if [ "$(lsb_release -is)" != Ubuntu ]; then
+ echo "Host stack test framework is supported only on Ubuntu"
+ exit 1
+fi
+
+export VPP_WS=../..
+export UBUNTU_VERSION=${UBUNTU_VERSION:-"$(lsb_release -rs)"}
+echo "Ubuntu version is set to ${UBUNTU_VERSION}"
+
+if [ "$1" == "debug" ]; then
+ VPP_BUILD_ROOT=${VPP_WS}/build-root/build-vpp_debug-native/vpp
+else
+ VPP_BUILD_ROOT=${VPP_WS}/build-root/build-vpp-native/vpp
+fi
+
+LAST_STATE_FILE=".last_state_hash"
+
+# get current state hash and ubuntu version
+ctime_hash1=$(stat -c %Z "$VPP_BUILD_ROOT"/.mu_build_install_timestamp | sha1sum | awk '{print $1}')
+ctime_hash2=$(stat -c %Z docker/* | sha1sum | awk '{print $1}')
+current_state_hash=$ctime_hash1-$ctime_hash2-$UBUNTU_VERSION$1
+
+if [ -f "$LAST_STATE_FILE" ]; then
+ last_state_hash=$(cat "$LAST_STATE_FILE")
+else
+ last_state_hash=""
+fi
+
+# compare current state with last state and check FORCE_BUILD
+if [ "$current_state_hash" = "$last_state_hash" ] && [ "$2" = "false" ]; then
+ echo "*** Skipping docker build - no new changes ***"
+ exit 0
+fi
+
+OS_ARCH="$(uname -m)"
+DOCKER_BUILD_DIR="/scratch/docker-build"
+DOCKER_CACHE_DIR="${DOCKER_BUILD_DIR}/docker_cache"
+DOCKER_LOGIN_SCRIPT="/scratch/nomad/.docker-ro/dlogin.sh"
+REGISTRY_PORT=5001
+if [ -x "$DOCKER_LOGIN_SCRIPT" ] ; then
+ $DOCKER_LOGIN_SCRIPT
+fi
+
+# Set up the local registry before creating containers
+echo "=== Setting up local registry ==="
+if [ -x "$(dirname "$0")/../docker/setup-local-registry.sh" ]; then
+ "$(dirname "$0")/../docker/setup-local-registry.sh" "$REGISTRY_PORT"
+else
+ echo "Warning: setup-local-registry.sh not found or not executable"
+ echo "Attempting to create and use local registry at localhost:5000"
+ if ! docker ps | grep -q "local-registry"; then
+ docker run -d --restart=always -p $REGISTRY_PORT:5000 --name local-registry registry:2
+ fi
+fi
+
+echo "Taking build objects from ${VPP_BUILD_ROOT}"
+
+export PATH=${VPP_BUILD_ROOT}/bin:$PATH
+
+bin=vpp-data/bin
+lib=vpp-data/lib
+
+mkdir -p ${bin} ${lib} || true
+rm -rf vpp-data/bin/* || true
+rm -rf vpp-data/lib/* || true
+
+declare -i res=0
+cp ${VPP_BUILD_ROOT}/bin/* ${bin}
+res+=$?
+cp -r ${VPP_BUILD_ROOT}/lib/"${OS_ARCH}"-linux-gnu/* ${lib}
+res+=$?
+if [ "$res" -ne 0 ]; then
+ echo "Failed to copy VPP files. Is VPP built? Try running 'make build' in VPP directory."
+ exit 1
+fi
+
+# Use the build-images.sh script to build all containers
+echo "=== Building all containers using build-images.sh ==="
+(
+ # Export necessary environment variables for build-images.sh
+ export BASE_TAG="localhost:$REGISTRY_PORT/vpp-test-base:latest"
+ export OS_ARCH
+ export UBUNTU_VERSION
+ export HTTP_PROXY
+ export HTTPS_PROXY
+ export NO_PROXY
+ export DOCKER_CACHE_DIR="${DOCKER_CACHE_DIR}"
+ export DOCKER_HST_BUILDER="${DOCKER_HST_BUILDER}"
+
+ # Run the build script
+ ./script/build-images.sh
+)
+
+# Check if the build was successful
+if [ $? -ne 0 ]; then
+ echo "Failed to build Docker images. Check the output above for errors."
+ exit 1
+fi
+
+echo "$current_state_hash" > "$LAST_STATE_FILE"
--- /dev/null
+#!/usr/bin/env bash
+
+if [ $1 == 2 ]
+then
+ exit 1
+fi
+
+# if failed-summary.log is not empty, exit status = 1
+if [ -s "${HS_ROOT}/summary/failed-summary.log" ]
+then
+ if [ -n "${WORKSPACE}" ]
+ then
+ echo -n "Copying docker logs..."
+ dirs=$(jq -r '.[0] | .SpecReports[] | select((.State == "failed") or (.State == "timedout") or (.State == "panicked")) | .LeafNodeText | split("/")[1]' ${HS_ROOT}/summary/report.json)
+ for dirName in $dirs; do
+ logDir=/tmp/kube-test/$dirName
+ if [ -d "$logDir" ]; then
+ mkdir -p ${WORKSPACE}/archives/summary
+ rsync -a --exclude 'vol' $logDir ${WORKSPACE}/archives/summary/
+ fi
+ done
+ echo "Done."
+
+ echo -n "Copying failed test logs into build log archive directory (${WORKSPACE}/archives)... "
+ mkdir -p ${WORKSPACE}/archives/summary
+ cp -a ${HS_ROOT}/summary/* ${WORKSPACE}/archives/summary
+ echo "Done."
+
+ echo -n "Compressing files in ${WORKSPACE}/archives from test runs... "
+ cd ${WORKSPACE}/archives
+ find . -type f \( -name "*.json" -o -name "*.log" \) -exec gzip {} \;
+ echo "Done."
+
+ else
+ echo "Not compressing files in temporary directories from test runs."
+ fi
+ echo "*************************** SUMMARY ***************************"
+ cat "${HS_ROOT}/summary/failed-summary.log"
+ exit 1
+else
+ exit $1
+fi
--- /dev/null
+#!/usr/bin/env bash
+
+# shellcheck disable=SC2068
+$1 -v && LD_PRELOAD=$LDP $@ > /proc/1/fd/1 2>&1
COMMAND=$1
CALICOVPP_DIR="$HOME/vpp-dataplane"
VPP_DIR=$(pwd)
-VPP_DIR=${VPP_DIR%extras*}
+VPP_DIR=${VPP_DIR%test-c*}
COMMIT_HASH=$(git rev-parse HEAD)
reg_name='kind-registry'
reg_port='5000'
+BASE=${BASE:-"$COMMIT_HASH"}
export CALICO_NETWORK_CONFIG=${CALICO_NETWORK_CONFIG:-"mtu: 9000"}
export CALICOVPP_VERSION="${CALICOVPP_VERSION:-latest}"
echo "Usage:"
echo -e " make master-cluster | rebuild-master-cluster | release-cluster\n"
- echo "'master-cluster' pulls CalicoVPP and builds VPP from this directory, then brings up a KinD cluster."
+ echo "'master-cluster' pulls CalicoVPP and builds VPP from this directory, then brings up a KinD cluster. You can
+ override the version with: BASE=[(remote or local branch) | (commit hash)], e.g. BASE=origin/master"
echo "'rebuild-master-cluster' stops CalicoVPP pods, rebuilds VPP and restarts CalicoVPP pods. Cluster keeps running."
echo "'release-cluster' starts up a KinD cluster and uses latest CalicoVPP release (e.g. v3.29),
or you can override versions by using env variables 'CALICOVPP_VERSION' and 'TIGERA_VERSION':
STASHED_CHANGES=0
echo "checkpoint: $COMMIT_HASH"
# chery-vpp hard resets the repo to a commit - we want to keep our changes
- if [[ -n $(git status --porcelain) ]]; then
+ if ! git diff --quiet; then
echo "Saving stash"
- git stash save "HST: temp stash"
+ git stash push -u
STASHED_CHANGES=1
fi
- make -C $CALICOVPP_DIR cherry-vpp FORCE=y BASE=origin/master VPP_DIR=$VPP_DIR
+ make -C $CALICOVPP_DIR cherry-vpp FORCE=y BASE=$BASE VPP_DIR=$VPP_DIR
# pop the stash to build VPP with CalicoVPP's patches + our changes
if [ $STASHED_CHANGES -eq 1 ]; then
}
build_load_start_cni() {
- make -C $VPP_DIR/extras/hs-test build-vpp-release
+ make -C $VPP_DIR/test-c/kube-test build-vpp-release
make -C $CALICOVPP_DIR dev-kind
make -C $CALICOVPP_DIR load-kind
kubectl create --save-config -f kubernetes/calico-config.yaml
restore_repo() {
# stash changes, reset local repo to the original state and unstash changes (removes CalicoVPP's patches)
- if [[ -n $(git status --porcelain) ]]; then
+ if ! git diff --quiet; then
echo "Saving stash"
- git stash save "HST: temp stash"
+ git stash push -u
git reset --hard $COMMIT_HASH
git stash pop
else
else
cd $CALICOVPP_DIR
git pull
- cd $VPP_DIR/extras/hs-test
+ cd $VPP_DIR/test-c/kube-test
fi
echo -e "$kind_config" | kind create cluster --config=-