Merge branch 'kubernetes:master' into no-kubernetes-skip-downloads
commit
9d0cf672d7
7
Makefile
7
Makefile
|
|
@ -902,6 +902,7 @@ generate-licenses:
|
||||||
gomodtidy: ## run go mod tidy everywhere needed
|
gomodtidy: ## run go mod tidy everywhere needed
|
||||||
go mod tidy
|
go mod tidy
|
||||||
cd hack && go mod tidy
|
cd hack && go mod tidy
|
||||||
|
cd hack/prow/minitest && env -u GOTOOLCHAIN go mod tidy
|
||||||
|
|
||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
|
|
@ -1126,3 +1127,9 @@ get-dependency-version:
|
||||||
.PHONY: _update-all
|
.PHONY: _update-all
|
||||||
_update-all:
|
_update-all:
|
||||||
@(cd hack && go run update/update_all/update_all.go)
|
@(cd hack && go run update/update_all/update_all.go)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# targets for tests on prow
|
||||||
|
include ./hack/prow/prow.mk
|
||||||
|
|
||||||
|
|
|
||||||
4
go.mod
4
go.mod
|
|
@ -62,7 +62,7 @@ require (
|
||||||
github.com/spf13/viper v1.20.1
|
github.com/spf13/viper v1.20.1
|
||||||
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097
|
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097
|
||||||
go.opentelemetry.io/otel v1.38.0
|
go.opentelemetry.io/otel v1.38.0
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0
|
go.opentelemetry.io/otel/sdk v1.38.0
|
||||||
go.opentelemetry.io/otel/trace v1.38.0
|
go.opentelemetry.io/otel/trace v1.38.0
|
||||||
golang.org/x/build v0.0.0-20190927031335-2835ba2e683f
|
golang.org/x/build v0.0.0-20190927031335-2835ba2e683f
|
||||||
golang.org/x/crypto v0.41.0
|
golang.org/x/crypto v0.41.0
|
||||||
|
|
@ -233,7 +233,7 @@ require (
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/net v0.43.0 // indirect
|
golang.org/x/net v0.43.0 // indirect
|
||||||
|
|
|
||||||
8
go.sum
8
go.sum
|
|
@ -711,10 +711,10 @@ go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1x
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw=
|
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ require (
|
||||||
github.com/spf13/viper v1.20.1
|
github.com/spf13/viper v1.20.1
|
||||||
go.opentelemetry.io/otel v1.38.0
|
go.opentelemetry.io/otel v1.38.0
|
||||||
go.opentelemetry.io/otel/metric v1.38.0
|
go.opentelemetry.io/otel/metric v1.38.0
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.36.0
|
go.opentelemetry.io/otel/sdk/metric v1.38.0
|
||||||
golang.org/x/mod v0.27.0
|
golang.org/x/mod v0.27.0
|
||||||
golang.org/x/oauth2 v0.30.0
|
golang.org/x/oauth2 v0.30.0
|
||||||
gonum.org/v1/plot v0.16.0
|
gonum.org/v1/plot v0.16.0
|
||||||
|
|
@ -208,7 +208,7 @@ require (
|
||||||
go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect
|
go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
|
|
|
||||||
|
|
@ -515,10 +515,10 @@ go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1x
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw=
|
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# The script expects the following env variables:
|
||||||
|
# OS: The operating system
|
||||||
|
# ARCH: The architecture
|
||||||
|
# DRIVER: the driver to use for the test
|
||||||
|
# CONTAINER_RUNTIME: the container runtime to use for the test
|
||||||
|
# EXTRA_START_ARGS: additional flags to pass into minikube start
|
||||||
|
# EXTRA_TEST_ARGS: additional flags to pass into go test
|
||||||
|
# JOB_NAME: the name of the logfile and check name to update on github
|
||||||
|
# PULL_NUMBER: the PR number, if applicable
|
||||||
|
|
||||||
|
function print_test_info() {
|
||||||
|
echo ">> Starting at $(date)"
|
||||||
|
echo ""
|
||||||
|
echo "user: $(whoami)"
|
||||||
|
echo "arch: ${OS_ARCH}"
|
||||||
|
echo "pr: ${PULL_NUMBER}"
|
||||||
|
echo "driver: ${DRIVER}"
|
||||||
|
echo "runtime: ${CONTAINER_RUNTIME}"
|
||||||
|
echo "job: ${JOB_NAME}"
|
||||||
|
echo "test home: ${TEST_HOME}"
|
||||||
|
echo "kernel: $(uname -v)"
|
||||||
|
echo "uptime: $(uptime)"
|
||||||
|
# Setting KUBECONFIG prevents the version check from erroring out due to permission issues
|
||||||
|
echo "kubectl: $(env KUBECONFIG=${TEST_HOME} kubectl version --client)"
|
||||||
|
echo "docker: $(docker version --format '{{ .Client.Version }}')"
|
||||||
|
echo "podman: $(sudo podman version --format '{{.Version}}' || true)"
|
||||||
|
echo "go: $(go version || true)"
|
||||||
|
|
||||||
|
case "${DRIVER}" in
|
||||||
|
kvm2)
|
||||||
|
echo "virsh: $(virsh --version)"
|
||||||
|
;;
|
||||||
|
virtualbox)
|
||||||
|
echo "vbox: $(vboxmanage --version)"
|
||||||
|
;;
|
||||||
|
vfkit)
|
||||||
|
echo "vfkit: $(vfkit --version)"
|
||||||
|
;;
|
||||||
|
krunkit)
|
||||||
|
echo "krunkit: $(krunkit --version)"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_dependencies() {
|
||||||
|
# We need pstree for the restart cronjobs
|
||||||
|
if [ "$(uname)" != "Darwin" ]; then
|
||||||
|
sudo apt-get -y install lsof psmisc dnsutils
|
||||||
|
else
|
||||||
|
brew install pstree coreutils pidof
|
||||||
|
ln -s /usr/local/bin/gtimeout /usr/local/bin/timeout || true
|
||||||
|
fi
|
||||||
|
# install golang if not present
|
||||||
|
sudo hack/prow/installer/check_install_golang.sh /usr/local 1.24.5 || true
|
||||||
|
# install gotestsum if not present
|
||||||
|
GOROOT="/usr/local/go" hack/prow/installer/check_install_gotestsum.sh || true
|
||||||
|
# install gopogh
|
||||||
|
hack/prow/installer/check_install_gopogh.sh || true
|
||||||
|
|
||||||
|
# install jq
|
||||||
|
if ! type "jq" >/dev/null; then
|
||||||
|
echo ">> Installing jq"
|
||||||
|
if [ "${ARCH}" == "arm64" && "${OS}" == "linux" ]; then
|
||||||
|
sudo apt-get install jq -y
|
||||||
|
elif [ "${ARCH}" == "arm64" ]; then
|
||||||
|
echo "Unable to install 'jq' automatically for arm64 on Darwin, please install 'jq' manually."
|
||||||
|
exit 5
|
||||||
|
elif [ "${OS}" != "darwin" ]; then
|
||||||
|
curl -LO https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 && sudo install jq-linux64 /usr/local/bin/jq
|
||||||
|
else
|
||||||
|
curl -LO https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 && sudo install jq-osx-amd64 /usr/local/bin/jq
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function docker_setup() {
|
||||||
|
|
||||||
|
# clean all docker artifacts up
|
||||||
|
docker system prune -a --volumes -f || true
|
||||||
|
docker system df || true
|
||||||
|
docker rm -f -v $(docker ps -aq) >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# read only token, never expires
|
||||||
|
#todo: do we need this token
|
||||||
|
# docker login -u minikubebot -p "$DOCKERHUB_READONLY_TOKEN"
|
||||||
|
}
|
||||||
|
|
||||||
|
function gvisor_image_build() {
|
||||||
|
# Build the gvisor image so that we can integration test changes to pkg/gvisor
|
||||||
|
chmod +x testdata/gvisor-addon
|
||||||
|
# skipping gvisor mac because ofg https://github.com/kubernetes/minikube/issues/5137
|
||||||
|
if [ "$(uname)" != "Darwin" ]; then
|
||||||
|
# Should match GVISOR_IMAGE_VERSION in Makefile
|
||||||
|
docker build -t gcr.io/k8s-minikube/gvisor-addon:2 -f testdata/gvisor-addon-Dockerfile ./testdata
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_gopogh() {
|
||||||
|
# todo: currently we do not save to gopogh db
|
||||||
|
echo "Not saving to DB"
|
||||||
|
gopogh -in "${JSON_OUT}" -out_html "${HTML_OUT}" -out_summary "${SUMMARY_OUT}" -name "${JOB_NAME}" -pr "${PULL_NUMBER}" -repo github.com/kubernetes/minikube/ -details "${COMMIT}:$(date +%Y-%m-%d)"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# this is where the script starts
|
||||||
|
readonly OS_ARCH="${OS}-${ARCH}"
|
||||||
|
readonly TEST_ROOT="${HOME}/minikube-integration"
|
||||||
|
readonly TEST_HOME="${TEST_ROOT}/${MINIKUBE_LOCATION}-$$"
|
||||||
|
|
||||||
|
export GOPATH="$HOME/go"
|
||||||
|
export KUBECONFIG="${TEST_HOME}/kubeconfig"
|
||||||
|
export PATH=$PATH:"/usr/local/bin/:/usr/local/go/bin/:$GOPATH/bin"
|
||||||
|
export MINIKUBE_SUPPRESS_DOCKER_PERFORMANCE=true
|
||||||
|
|
||||||
|
readonly TIMEOUT=120m
|
||||||
|
|
||||||
|
cp -r test/integration/testdata .
|
||||||
|
|
||||||
|
# Add the out/ directory to the PATH, for using new drivers.
|
||||||
|
export PATH="$(pwd)/out/":$PATH
|
||||||
|
mkdir -p "${TEST_ROOT}"
|
||||||
|
mkdir -p "${TEST_HOME}"
|
||||||
|
export MINIKUBE_HOME="${TEST_HOME}/.minikube"
|
||||||
|
export MINIKUBE_BIN="out/minikube-${OS_ARCH}"
|
||||||
|
export E2E_BIN="out/e2e-${OS_ARCH}"
|
||||||
|
|
||||||
|
install_dependencies
|
||||||
|
docker_setup
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$CONTAINER_RUNTIME" == "containerd" ]; then
|
||||||
|
cp out/gvisor-addon testdata/
|
||||||
|
gvisor_image_build
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_test_info
|
||||||
|
|
||||||
|
readonly TEST_OUT="${TEST_HOME}/testout.txt"
|
||||||
|
readonly JSON_OUT="${TEST_HOME}/test.json"
|
||||||
|
readonly JUNIT_OUT="${TEST_HOME}/junit-unit.xml"
|
||||||
|
readonly HTML_OUT="${TEST_HOME}/test.html"
|
||||||
|
readonly SUMMARY_OUT="${TEST_HOME}/test_summary.json"
|
||||||
|
|
||||||
|
touch "${TEST_OUT}"
|
||||||
|
touch "${JSON_OUT}"
|
||||||
|
touch "${JUNIT_OUT}"
|
||||||
|
touch "${HTML_OUT}"
|
||||||
|
touch "${SUMMARY_OUT}"
|
||||||
|
|
||||||
|
e2e_start_time="$(date -u +%s)"
|
||||||
|
echo ""
|
||||||
|
echo ">> Starting ${E2E_BIN} at $(date)"
|
||||||
|
set -x
|
||||||
|
|
||||||
|
EXTRA_START_ARGS="${EXTRA_START_ARGS} --container-runtime=${CONTAINER_RUNTIME}"
|
||||||
|
echo $PATH
|
||||||
|
gotestsum --jsonfile "${JSON_OUT}" --junitfile="${JUNIT_OUT}" -f standard-verbose --raw-command -- \
|
||||||
|
go tool test2json -t \
|
||||||
|
${E2E_BIN} \
|
||||||
|
-minikube-start-args="--driver=${DRIVER} ${EXTRA_START_ARGS}" \
|
||||||
|
-test.timeout=${TIMEOUT} -test.v \
|
||||||
|
${EXTRA_TEST_ARGS} \
|
||||||
|
-binary="${MINIKUBE_BIN}" 2>&1 |
|
||||||
|
tee "${TEST_OUT}"
|
||||||
|
|
||||||
|
result=${PIPESTATUS[0]} # capture the exit code of the first cmd in pipe.
|
||||||
|
set +x
|
||||||
|
echo ">> ${E2E_BIN} exited with ${result} at $(date)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# calculate the time took to finish running e2e binary test.
|
||||||
|
e2e_end_time="$(date -u +%s)"
|
||||||
|
elapsed=$(($e2e_end_time - $e2e_start_time))
|
||||||
|
min=$(($elapsed / 60))
|
||||||
|
sec=$(tail -c 3 <<<$((${elapsed}00 / 60)))
|
||||||
|
elapsed=$min.$sec
|
||||||
|
|
||||||
|
#todo: currently we skip gopogh upload , we shall add it back
|
||||||
|
run_gopogh
|
||||||
|
|
||||||
|
# according to prow's requirement, upload the test report to $ARTIFACTS
|
||||||
|
cp ${TEST_OUT} .
|
||||||
|
cp ${JSON_OUT} .
|
||||||
|
cp ${JUNIT_OUT} .
|
||||||
|
cp ${HTML_OUT} .
|
||||||
|
cp ${SUMMARY_OUT} .
|
||||||
|
if [[ $result -eq 0 ]]; then
|
||||||
|
echo "minikube: SUCCESS"
|
||||||
|
else
|
||||||
|
echo "minikube: FAIL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$result"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"Image": "debian"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -eux -o pipefail
|
||||||
|
|
||||||
|
ARCH=${ARCH:=amd64}
|
||||||
|
|
||||||
|
|
||||||
|
echo "Installing latest docker"
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sudo sh get-docker.sh
|
||||||
|
rm get-docker.sh
|
||||||
|
|
||||||
|
sudo usermod -aG docker minitest || true
|
||||||
|
|
||||||
|
echo "Installing latest kubectl"
|
||||||
|
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl"
|
||||||
|
sudo install ./kubectl /usr/local/bin/kubectl
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# This script requires two parameters:
|
||||||
|
# $1. INSTALL_PATH: The path to install the golang binary
|
||||||
|
# $2. GO_VERSION: The version of golang to install
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set -eux -o pipefail
|
||||||
|
|
||||||
|
if (($# < 2)); then
|
||||||
|
echo "ERROR: given ! ($#) parameters but expected 2."
|
||||||
|
echo "USAGE: ./check_install_golang.sh INSTALL_PATH GO_VERSION"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION_TO_INSTALL=${2}
|
||||||
|
INSTALL_PATH=${1}
|
||||||
|
|
||||||
|
function current_arch() {
|
||||||
|
case $(arch) in
|
||||||
|
"x86_64" | "i386")
|
||||||
|
echo "amd64"
|
||||||
|
;;
|
||||||
|
"aarch64" | "arm64")
|
||||||
|
echo "arm64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unexpected arch: $(arch). use amd64" 1>&2
|
||||||
|
echo "amd64"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
ARCH=${ARCH:=$(current_arch)}
|
||||||
|
|
||||||
|
# installs or updates golang if right version doesn't exists
|
||||||
|
function check_and_install_golang() {
|
||||||
|
if ! go version &>/dev/null; then
|
||||||
|
echo "WARNING: No golang installation found in your environment."
|
||||||
|
install_golang "$VERSION_TO_INSTALL" "$INSTALL_PATH"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo chown -R $USER:$USER "$INSTALL_PATH"/go
|
||||||
|
|
||||||
|
# golang has been installed and check its version
|
||||||
|
if [[ $(go version | cut -d' ' -f 3) =~ go(([0-9]+)\.([0-9]+).([0-9]+)*) ]]; then
|
||||||
|
HOST_VERSION=${BASH_REMATCH[1]}
|
||||||
|
if [ $HOST_VERSION == $VERSION_TO_INSTALL ]; then
|
||||||
|
echo "go version on the host looks good : $HOST_VERSION"
|
||||||
|
else
|
||||||
|
echo "WARNING: expected go version to be $VERSION_TO_INSTALL but got $HOST_VERSION"
|
||||||
|
install_golang "$VERSION_TO_INSTALL" "$INSTALL_PATH"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "ERROR: Failed to parse golang version: $(go version)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# install_golang takes two parameters version and path to install.
|
||||||
|
function install_golang() {
|
||||||
|
local -r GO_VER="$1"
|
||||||
|
local -r GO_DIR="$2/go"
|
||||||
|
echo "Installing golang version: $GO_VER in $GO_DIR"
|
||||||
|
|
||||||
|
INSTALLOS=linux
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
INSTALLOS=darwin
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -r GO_TGZ="go${GO_VER}.${INSTALLOS}-${ARCH}.tar.gz"
|
||||||
|
pushd /tmp
|
||||||
|
|
||||||
|
# using sudo because previously installed versions might have been installed by a different user.
|
||||||
|
sudo rm -rf "$GO_TGZ"
|
||||||
|
curl -qL -O "https://storage.googleapis.com/golang/$GO_TGZ"
|
||||||
|
sudo rm -rf "$GO_DIR"
|
||||||
|
sudo mkdir -p "$GO_DIR"
|
||||||
|
sudo tar -C "$GO_DIR" --strip-components=1 -xzf "$GO_TGZ"
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
echo "installed in $GO_DIR: $($GO_DIR/bin/go version)"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_and_install_golang
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# this script requires golang to be installed
|
||||||
|
|
||||||
|
set -eux -o pipefail
|
||||||
|
|
||||||
|
go install github.com/medyagh/gopogh/cmd/gopogh@v0.29.0
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2021 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -eux -o pipefail
|
||||||
|
|
||||||
|
function install_gotestsum() {
|
||||||
|
rm -f $(which gotestsum)
|
||||||
|
sudo env "GOBIN=$GOROOT/bin" "PATH=$PATH" go install gotest.tools/gotestsum@v1.12.3
|
||||||
|
}
|
||||||
|
echo "Installing gotestsum"
|
||||||
|
which gotestsum || install_gotestsum
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
OS="linux"
|
||||||
|
ARCH="amd64"
|
||||||
|
DRIVER="kvm2"
|
||||||
|
CONTAINER_RUNTIME="docker"
|
||||||
|
# in prow, if you want libvirtd to be run, you have to start a privileged container as root
|
||||||
|
EXTRA_START_ARGS=""
|
||||||
|
EXTRA_TEST_ARGS=""
|
||||||
|
JOB_NAME="KVM_Linux"
|
||||||
|
|
||||||
|
COMMIT=$(git rev-parse HEAD)
|
||||||
|
MINIKUBE_LOCATION=$COMMIT
|
||||||
|
echo "running test in $(pwd)"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
sleep 5 # wait for libvirtd to be running
|
||||||
|
echo "=========libvirtd status=========="
|
||||||
|
sudo systemctl status libvirtd
|
||||||
|
echo "=========Check virtualization support=========="
|
||||||
|
grep -E -q 'vmx|svm' /proc/cpuinfo && echo yes || echo no
|
||||||
|
echo "=========virt-host-validate=========="
|
||||||
|
virt-host-validate
|
||||||
|
|
||||||
|
set -e
|
||||||
|
source ./hack/prow/common.sh
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
OS="linux"
|
||||||
|
ARCH="amd64"
|
||||||
|
DRIVER="kvm2"
|
||||||
|
CONTAINER_RUNTIME="docker"
|
||||||
|
# in prow, if you want libvirtd to be run, you have to start a privileged container as root
|
||||||
|
EXTRA_START_ARGS=""
|
||||||
|
EXTRA_TEST_ARGS=""
|
||||||
|
JOB_NAME="KVM_Linux"
|
||||||
|
|
||||||
|
|
||||||
|
# install docker if not present
|
||||||
|
ARCH="$ARCH" hack/prow/installer/check_install_docker.sh || true
|
||||||
|
sudo adduser $(whoami) docker || true
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install qemu-system qemu-kvm libvirt-clients libvirt-daemon-system ebtables iptables dnsmasq
|
||||||
|
sudo adduser $(whoami) libvirt || true
|
||||||
|
|
||||||
|
# start libvirtd
|
||||||
|
sudo systemctl start libvirtd
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"GCPZone": "us-central1-b",
|
||||||
|
"InstanceImage": "ubuntu-os-cloud/ubuntu-2404-lts-amd64",
|
||||||
|
"InstanceType": "n2-standard-8",
|
||||||
|
"DiskGiB": 300,
|
||||||
|
"BoskosAcquireTimeoutSeconds": 180,
|
||||||
|
"BoskosHeartbeatIntervalSeconds": 10,
|
||||||
|
"BoskosLocation": "http://boskos.test-pods.svc.cluster.local"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# This script requires 3 parameter:
|
||||||
|
# $1. GO_VERSION: The version of golang to install
|
||||||
|
# $2. OS: The operating system
|
||||||
|
# $3. ARCH: The architecture
|
||||||
|
set -eux -o pipefail
|
||||||
|
GO_VERSION=$1
|
||||||
|
OS=$2
|
||||||
|
ARCH=$3
|
||||||
|
readonly OS_ARCH="${OS}-${ARCH}"
|
||||||
|
|
||||||
|
echo "running build in $(pwd), current pr number: ${PULL_NUMBER:-none}"
|
||||||
|
|
||||||
|
# hack/prow/installer/check_install_golang.sh /usr/local $GO_VERSION
|
||||||
|
# declare -rx GOPATH="$HOME/go"
|
||||||
|
|
||||||
|
declare -rx BUILD_IN_DOCKER=y
|
||||||
|
make -j 16 \
|
||||||
|
out/minikube-${OS_ARCH} \
|
||||||
|
out/e2e-${OS_ARCH} \
|
||||||
|
out/gvisor-addon \
|
||||||
|
&& failed=$? || failed=$?
|
||||||
|
|
||||||
|
export MINIKUBE_BIN="out/minikube-${OS_ARCH}"
|
||||||
|
export E2E_BIN="out/e2e-${OS_ARCH}"
|
||||||
|
chmod +x "${MINIKUBE_BIN}" "${E2E_BIN}"
|
||||||
|
|
||||||
|
BUILT_VERSION=$("out/minikube-$(go env GOOS)-$(go env GOARCH)" version)
|
||||||
|
echo ${BUILT_VERSION}
|
||||||
|
|
||||||
|
COMMIT=$(echo ${BUILT_VERSION} | grep 'commit:' | awk '{print $2}')
|
||||||
|
if (echo ${COMMIT} | grep -q dirty); then
|
||||||
|
echo "'minikube version' reports dirty commit: ${COMMIT}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${failed}" -ne 0 ]]; then
|
||||||
|
echo "build failed"
|
||||||
|
exit "${failed}"
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deployer
|
||||||
|
|
||||||
|
type MiniTestBoskosConfig struct {
|
||||||
|
GCPZone string
|
||||||
|
InstanceImage string
|
||||||
|
InstanceType string
|
||||||
|
DiskGiB int
|
||||||
|
// Boskos flags correspond to https://github.com/kubernetes-sigs/kubetest2/blob/71238a9645df6fbd7eaac9a36f635c22f1566168/kubetest2-gce/deployer/deployer.go
|
||||||
|
BoskosAcquireTimeoutSeconds int
|
||||||
|
BoskosHeartbeatIntervalSeconds int
|
||||||
|
BoskosLocation string
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,273 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deployer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
"sigs.k8s.io/boskos/client"
|
||||||
|
"sigs.k8s.io/kubetest2/pkg/boskos"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// gceProjectResourceType is called "gce" project in Boskos,
|
||||||
|
// while it is called "gcp" project in this CLI.
|
||||||
|
gceProjectResourceType = "gce-project"
|
||||||
|
runDirSSHKeys = "gce-ssh-keys"
|
||||||
|
remoteUserName = "minitest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MiniTestBosKosDeployer struct {
|
||||||
|
ctx context.Context
|
||||||
|
config *MiniTestBoskosConfig
|
||||||
|
isUp bool
|
||||||
|
|
||||||
|
id string
|
||||||
|
gcpProject string
|
||||||
|
remoteUserName string
|
||||||
|
networkName string
|
||||||
|
firewallRuleName string
|
||||||
|
instanceName string
|
||||||
|
sshAddr string
|
||||||
|
|
||||||
|
boskosClient *client.Client
|
||||||
|
// this channel serves as a signal channel for the hearbeat goroutine
|
||||||
|
// so that it can be explicitly closed
|
||||||
|
boskosHeartbeatClose chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMiniTestBosKosDeployerFromConfigFile(path string) MiniTestDeployer {
|
||||||
|
config := MiniTestBoskosConfig{}
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
klog.Fatalf("failed to read config file %s: %v", path, err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(data, &config); err != nil {
|
||||||
|
klog.Fatalf("failed to parse config file %s: %v", path, err)
|
||||||
|
}
|
||||||
|
return NewMiniTestBosKosDeployer(&config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMiniTestBosKosDeployer(config *MiniTestBoskosConfig) MiniTestDeployer {
|
||||||
|
boskosClient, err := boskos.NewClient(config.BoskosLocation)
|
||||||
|
if err != nil {
|
||||||
|
klog.Fatalf("failed to make boskos client: %v", err)
|
||||||
|
}
|
||||||
|
id := uuid.New().String()[:8]
|
||||||
|
return &MiniTestBosKosDeployer{
|
||||||
|
ctx: context.TODO(),
|
||||||
|
config: config,
|
||||||
|
boskosClient: boskosClient,
|
||||||
|
boskosHeartbeatClose: make(chan struct{}),
|
||||||
|
remoteUserName: remoteUserName,
|
||||||
|
id: id,
|
||||||
|
networkName: "minitest-network-" + id,
|
||||||
|
firewallRuleName: "minitest-firewall-" + id,
|
||||||
|
instanceName: "minitest-vm-" + id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) Up() error {
|
||||||
|
|
||||||
|
if err := m.requestGCPProject(); err != nil {
|
||||||
|
klog.Errorf("Failed to request gcp project from boskos: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := m.gcpVMSetUp(); err != nil {
|
||||||
|
klog.Errorf("Failed to start a vm in gcp: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := m.gcpSSHSetUp(); err != nil {
|
||||||
|
klog.Errorf("Failed to set up ssh: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := sshConnectionCheck(m.ctx, m.remoteUserName, m.sshAddr, nil); err != nil {
|
||||||
|
klog.Errorf("Failed to conntect via ssh: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.Infof("Successfully started vm in gcp: %s", m.instanceName)
|
||||||
|
m.isUp = true
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) Down() error {
|
||||||
|
//todo: clean up the VM?
|
||||||
|
|
||||||
|
klog.Info("Releasing bosko project")
|
||||||
|
if m.boskosClient == nil {
|
||||||
|
return fmt.Errorf("m.boskosClient not set")
|
||||||
|
}
|
||||||
|
err := boskos.Release(
|
||||||
|
m.boskosClient,
|
||||||
|
[]string{m.gcpProject},
|
||||||
|
m.boskosHeartbeatClose,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("down failed to release boskos project: %v", err)
|
||||||
|
}
|
||||||
|
m.isUp = false
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) IsUp() (bool, error) {
|
||||||
|
return m.isUp, nil
|
||||||
|
}
|
||||||
|
func (m *MiniTestBosKosDeployer) Execute(args ...string) error {
|
||||||
|
return executeSSHCommand(m.ctx, m.remoteUserName, m.sshAddr, nil, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) SyncToRemote(src string, dst string, excludedPattern []string) error {
|
||||||
|
excludedArgs := make([]string, 0, len(excludedPattern)*2)
|
||||||
|
for _, pattern := range excludedPattern {
|
||||||
|
excludedArgs = append(excludedArgs, "--exclude", pattern)
|
||||||
|
}
|
||||||
|
dstRemote := fmt.Sprintf("%s@%s:%s", m.remoteUserName, m.sshAddr, dst)
|
||||||
|
return executeRsyncSSHCommand(m.ctx, nil, src, dstRemote, excludedArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) SyncToHost(src string, dst string, excludedPattern []string) error {
|
||||||
|
excludedArgs := make([]string, 0, len(excludedPattern)*2)
|
||||||
|
for _, pattern := range excludedPattern {
|
||||||
|
excludedArgs = append(excludedArgs, "--exclude", pattern)
|
||||||
|
}
|
||||||
|
srcRemote := fmt.Sprintf("%s@%s:%s", m.remoteUserName, m.sshAddr, src)
|
||||||
|
return executeRsyncSSHCommand(m.ctx, nil, srcRemote, dst, excludedArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) requestGCPProject() error {
|
||||||
|
|
||||||
|
resource, err := boskos.Acquire(
|
||||||
|
m.boskosClient,
|
||||||
|
gceProjectResourceType,
|
||||||
|
time.Duration(m.config.BoskosAcquireTimeoutSeconds)*time.Second,
|
||||||
|
time.Duration(m.config.BoskosHeartbeatIntervalSeconds)*time.Second,
|
||||||
|
m.boskosHeartbeatClose,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get project from boskos: %v", err)
|
||||||
|
}
|
||||||
|
if resource.Name == "" {
|
||||||
|
return fmt.Errorf("boskos returned an empty resource name, resource: %v", resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.Infof("Got project %q from boskos", resource.Name)
|
||||||
|
m.gcpProject = resource.Name
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) gcpVMSetUp() error {
|
||||||
|
// ensure gcp zone is set to start a vm
|
||||||
|
if m.config.GCPZone == "" {
|
||||||
|
return fmt.Errorf("GCPZone is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute gcloud commands to set environment up a vm
|
||||||
|
if err := m.executeLocalGloudCommand("services", "enable", "compute.googleapis.com"); err != nil {
|
||||||
|
klog.Warningf("failed to enable service: %v", err)
|
||||||
|
}
|
||||||
|
if err := m.executeLocalGloudCommand("compute", "networks", "create", m.networkName); err != nil {
|
||||||
|
klog.Warningf("failed to set up network: %v", err)
|
||||||
|
}
|
||||||
|
if err := m.executeLocalGloudCommand("compute", "firewall-rules", "create", m.firewallRuleName, "--network="+m.networkName, "--allow=tcp:22"); err != nil {
|
||||||
|
klog.Warningf("failed to set up firewalls: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the vm
|
||||||
|
description := fmt.Sprintf("%s instance (login ID: %q)", m.instanceName, m.remoteUserName)
|
||||||
|
instImgPair := strings.SplitN(m.config.InstanceImage, "/", 2)
|
||||||
|
if err := m.executeLocalGloudCommand("compute", "instances", "create",
|
||||||
|
"--enable-nested-virtualization",
|
||||||
|
"--zone="+m.config.GCPZone,
|
||||||
|
"--description="+description,
|
||||||
|
"--network="+m.networkName,
|
||||||
|
"--image-project="+instImgPair[0],
|
||||||
|
"--image-family="+instImgPair[1],
|
||||||
|
"--machine-type="+m.config.InstanceType,
|
||||||
|
fmt.Sprintf("--boot-disk-size=%dGiB", m.config.DiskGiB),
|
||||||
|
"--boot-disk-type=pd-ssd",
|
||||||
|
"--metadata=block-project-ssh-keys=TRUE",
|
||||||
|
|
||||||
|
m.instanceName,
|
||||||
|
); err != nil {
|
||||||
|
klog.Errorf("failed to start a gcp vm: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) gcpSSHSetUp() error {
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to find home dir: %v", err)
|
||||||
|
}
|
||||||
|
gcePubPath := filepath.Join(home, ".ssh/google_compute_engine.pub")
|
||||||
|
gcePubContent, err := os.ReadFile(gcePubPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read GCE public key: %v", err)
|
||||||
|
}
|
||||||
|
sshKeysContent := []byte(m.remoteUserName + ":" + string(gcePubContent))
|
||||||
|
runDir, err := os.MkdirTemp("", "rundir")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create temp dir: %v", err)
|
||||||
|
}
|
||||||
|
sshKeysPath := filepath.Join(runDir, runDirSSHKeys)
|
||||||
|
_ = os.RemoveAll(sshKeysPath)
|
||||||
|
if err = os.WriteFile(sshKeysPath, sshKeysContent, 0400); err != nil {
|
||||||
|
return fmt.Errorf("failed to create new public key file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up ssh login with pub key
|
||||||
|
if err := m.executeLocalGloudCommand("compute", "instances", "add-metadata", m.instanceName, "--zone="+m.config.GCPZone, "--metadata-from-file=ssh-keys="+sshKeysPath); err != nil {
|
||||||
|
klog.Warningf("failed to add metadata: %v", err)
|
||||||
|
// continue anyway
|
||||||
|
}
|
||||||
|
// update the local ssh config
|
||||||
|
if err := m.executeLocalGloudCommand("compute", "config-ssh"); err != nil {
|
||||||
|
klog.Warningf("failed to compute ssh: %v", err)
|
||||||
|
// continue anyway
|
||||||
|
}
|
||||||
|
|
||||||
|
// set sshAddr field
|
||||||
|
if m.instanceName == "" || m.config.GCPZone == "" || m.gcpProject == "" {
|
||||||
|
return fmt.Errorf("gcp project configuration incorrect: %s.%s.%s", m.instanceName, m.config.GCPZone, m.gcpProject)
|
||||||
|
}
|
||||||
|
m.sshAddr = fmt.Sprintf("%s.%s.%s", m.instanceName, m.config.GCPZone, m.gcpProject)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestBosKosDeployer) executeLocalGloudCommand(args ...string) error {
|
||||||
|
|
||||||
|
if err := executeLocalCommand(m.ctx, "gcloud", append([]string{"--project=" + m.gcpProject}, args...)...); err != nil {
|
||||||
|
return fmt.Errorf("failed to run %v: %v", args, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deployer
|
||||||
|
|
||||||
|
type MiniTestDeployer interface {
|
||||||
|
// Up should provision the environment for testing
|
||||||
|
Up() error
|
||||||
|
// Down should tear down the environment if any
|
||||||
|
Down() error
|
||||||
|
// IsUp should return true if a test cluster is successfully provisioned
|
||||||
|
IsUp() (bool, error)
|
||||||
|
// Execute execute a command in the deployed environment
|
||||||
|
Execute(args ...string) error
|
||||||
|
// SyncToRemote sync file or folder from src on host to dst on deployed environment
|
||||||
|
SyncToRemote(src string, dst string, excludedPattern []string) error
|
||||||
|
// SyncToRemote sync file or folder from src on remote to host
|
||||||
|
SyncToHost(src string, dst string, excludedPattern []string) error
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deployer
|
||||||
|
|
||||||
|
type MiniTestDockerConfig struct {
|
||||||
|
Image string
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,314 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deployer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/docker/go-connections/nat"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/moby/moby/api/types/container"
|
||||||
|
"github.com/moby/moby/client"
|
||||||
|
"github.com/phayes/freeport"
|
||||||
|
gossh "golang.org/x/crypto/ssh"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sshSetupScript = `
|
||||||
|
#!/bin/bash
|
||||||
|
USERNAME=%s
|
||||||
|
apt update
|
||||||
|
apt install -y openssh-server rsync
|
||||||
|
service ssh start
|
||||||
|
useradd -m -s /bin/bash ${USERNAME}
|
||||||
|
passwd -d ${USERNAME}
|
||||||
|
|
||||||
|
USER_HOME=$(eval echo "~${USERNAME}")
|
||||||
|
mkdir -p $USER_HOME/.ssh
|
||||||
|
chmod 700 $USER_HOME/.ssh
|
||||||
|
echo "%s" >> $USER_HOME/.ssh/authorized_keys
|
||||||
|
chmod 600 $USER_HOME/.ssh/authorized_keys
|
||||||
|
chown -R $USERNAME:$USERNAME "$USER_HOME/.ssh"
|
||||||
|
`
|
||||||
|
|
||||||
|
type MiniTestDockerDeployer struct {
|
||||||
|
ctx context.Context
|
||||||
|
config *MiniTestDockerConfig
|
||||||
|
isUp bool
|
||||||
|
|
||||||
|
dockerClient *client.Client
|
||||||
|
containerSHA string
|
||||||
|
|
||||||
|
sshPrivateKeyFile string
|
||||||
|
sshPublicKeyFile string
|
||||||
|
sshPublicKeyContent string
|
||||||
|
sshPort string
|
||||||
|
|
||||||
|
sshTempDir string
|
||||||
|
remoteUserName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMiniTestDockerDeployerFromConfigFile(path string) MiniTestDeployer {
|
||||||
|
config := MiniTestDockerConfig{}
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
klog.Fatalf("failed to read config file %s: %v", path, err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(data, &config); err != nil {
|
||||||
|
klog.Fatalf("failed to parse config file %s: %v", path, err)
|
||||||
|
}
|
||||||
|
return NewMiniTestDockerDeployer(&config)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMiniTestDockerDeployer(config *MiniTestDockerConfig) MiniTestDeployer {
|
||||||
|
return &MiniTestDockerDeployer{
|
||||||
|
ctx: context.TODO(),
|
||||||
|
config: config,
|
||||||
|
isUp: false,
|
||||||
|
remoteUserName: remoteUserName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) Up() error {
|
||||||
|
dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create docker api client: %v", err)
|
||||||
|
}
|
||||||
|
m.dockerClient = dockerClient
|
||||||
|
|
||||||
|
// pull the image
|
||||||
|
reader, err := dockerClient.ImagePull(m.ctx, m.config.Image, client.ImagePullOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to pull image %s: %v", m.config.Image, err)
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
_, err = io.Copy(os.Stdout, reader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read image pull response: %v", err)
|
||||||
|
}
|
||||||
|
// find a free port for ssh
|
||||||
|
port, err := freeport.GetFreePort()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get a free port for ssh: %v", err)
|
||||||
|
}
|
||||||
|
m.sshPort = strconv.Itoa(port)
|
||||||
|
klog.Infof("Using port %s for ssh", m.sshPort)
|
||||||
|
|
||||||
|
// start the container
|
||||||
|
id := uuid.New().String()[:8]
|
||||||
|
//todo: remove hard coded ports
|
||||||
|
exposedPorts, portBindings, _ := nat.ParsePortSpecs([]string{m.sshPort + ":22"})
|
||||||
|
response, err := dockerClient.ContainerCreate(
|
||||||
|
m.ctx,
|
||||||
|
&container.Config{
|
||||||
|
Image: m.config.Image,
|
||||||
|
Tty: true, //-t
|
||||||
|
OpenStdin: true, // -i
|
||||||
|
//Entrypoint: []string{"/usr/sbin/init"},
|
||||||
|
ExposedPorts: exposedPorts,
|
||||||
|
},
|
||||||
|
|
||||||
|
&container.HostConfig{
|
||||||
|
Privileged: true,
|
||||||
|
PortBindings: portBindings,
|
||||||
|
}, nil, nil, "minitest-"+id)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("failed to create container from image %s: %v", m.config.Image, err)
|
||||||
|
return fmt.Errorf("failed to create container from image %s: %v", m.config.Image, err)
|
||||||
|
}
|
||||||
|
m.containerSHA = response.ID
|
||||||
|
|
||||||
|
err = dockerClient.ContainerStart(m.ctx, m.containerSHA,
|
||||||
|
client.ContainerStartOptions{})
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("failed to start container %s: %v", m.containerSHA, err)
|
||||||
|
return fmt.Errorf("failed to start container %s: %v", m.containerSHA, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up ssh keys
|
||||||
|
if err := m.sshSetUp(); err != nil {
|
||||||
|
klog.Errorf("failed to set up ssh: %v", err)
|
||||||
|
return fmt.Errorf("failed to set up ssh: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up sshd server
|
||||||
|
err = m.executeDockerShellCommand("root", fmt.Sprintf(sshSetupScript, m.remoteUserName, m.sshPublicKeyContent))
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("failed to set up sshd server in container %s: %v", m.containerSHA, err)
|
||||||
|
return fmt.Errorf("failed to set up sshd server in container %s: %v", m.containerSHA, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check ssh connectivity
|
||||||
|
if err := sshConnectionCheck(m.ctx, m.remoteUserName, "localhost", m.sshAdditionalArgs()); err != nil {
|
||||||
|
klog.Errorf("Failed to conntect via ssh: %v", err)
|
||||||
|
return fmt.Errorf("Failed to conntect via ssh: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.isUp = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) Down() error {
|
||||||
|
os.RemoveAll(m.sshTempDir)
|
||||||
|
|
||||||
|
if m.dockerClient == nil {
|
||||||
|
klog.Errorf("m.dockerClient not set")
|
||||||
|
return fmt.Errorf("m.dockerClient not set")
|
||||||
|
}
|
||||||
|
if err := m.dockerClient.ContainerRemove(m.ctx, m.containerSHA, client.ContainerRemoveOptions{Force: true}); err != nil {
|
||||||
|
klog.Errorf("failed to remove container %s: %v", m.containerSHA, err)
|
||||||
|
return fmt.Errorf("failed to remove container %s: %v", m.containerSHA, err)
|
||||||
|
}
|
||||||
|
// close the docker client
|
||||||
|
m.dockerClient.Close()
|
||||||
|
m.isUp = false
|
||||||
|
klog.Infof("Successfully removed container %s", m.containerSHA)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (m *MiniTestDockerDeployer) IsUp() (bool, error) {
|
||||||
|
return m.isUp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) Execute(args ...string) error {
|
||||||
|
return executeSSHCommand(m.ctx, m.remoteUserName, "localhost", m.sshAdditionalArgs(), args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) SyncToRemote(src string, dst string, excludedPattern []string) error {
|
||||||
|
excludedArgs := make([]string, 0, len(excludedPattern)*2)
|
||||||
|
for _, pattern := range excludedPattern {
|
||||||
|
excludedArgs = append(excludedArgs, "--exclude", pattern)
|
||||||
|
}
|
||||||
|
dstRemote := fmt.Sprintf("%s@%s:%s", m.remoteUserName, "localhost", dst)
|
||||||
|
return executeRsyncSSHCommand(m.ctx, m.sshAdditionalArgs(), src, dstRemote, excludedArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) SyncToHost(src string, dst string, excludedPattern []string) error {
|
||||||
|
excludedArgs := make([]string, 0, len(excludedPattern)*2)
|
||||||
|
for _, pattern := range excludedPattern {
|
||||||
|
excludedArgs = append(excludedArgs, "--exclude", pattern)
|
||||||
|
}
|
||||||
|
srcRemote := fmt.Sprintf("%s@%s:%s", m.remoteUserName, "localhost", src)
|
||||||
|
return executeRsyncSSHCommand(m.ctx, m.sshAdditionalArgs(), srcRemote, dst, excludedArgs)
|
||||||
|
//return executeScpCommand(m.ctx, m.remoteUserName, "localhost", m.scpAdditionalArgs(), src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) executeDockerShellCommand(user string, args ...string) error {
|
||||||
|
execResp, err := m.dockerClient.ContainerExecCreate(m.ctx, m.containerSHA, container.ExecOptions{
|
||||||
|
Cmd: append([]string{"/bin/bash", "-c"}, args...),
|
||||||
|
AttachStdout: true,
|
||||||
|
AttachStderr: true,
|
||||||
|
Tty: true,
|
||||||
|
User: user,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create exec instance: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
attachResp, err := m.dockerClient.ContainerExecAttach(
|
||||||
|
m.ctx, execResp.ID,
|
||||||
|
container.ExecAttachOptions{Tty: true})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to attach to exec instance: %v", err)
|
||||||
|
}
|
||||||
|
defer attachResp.Close()
|
||||||
|
if _, err = io.Copy(os.Stdout, attachResp.Reader); err != nil {
|
||||||
|
return fmt.Errorf("failed to read exec output: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) sshSetUp() error {
|
||||||
|
// we generate a ssh key pair and add the public key to the container's authorized_keys
|
||||||
|
|
||||||
|
sshTempDir, err := os.MkdirTemp("", "minitest-ssh-")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create temp dir for ssh keys: %v", err)
|
||||||
|
}
|
||||||
|
m.sshTempDir = sshTempDir
|
||||||
|
klog.Info("Created temp dir for ssh keys: ", sshTempDir)
|
||||||
|
|
||||||
|
// create private key file
|
||||||
|
sshPrivateKeyFile, err := os.CreateTemp(sshTempDir, "id_rsa")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create temp file for private key: %v", err)
|
||||||
|
}
|
||||||
|
if sshPrivateKeyFile.Chmod(0600) != nil {
|
||||||
|
return fmt.Errorf("failed to chmod private key file: %v", err)
|
||||||
|
}
|
||||||
|
m.sshPrivateKeyFile = sshPrivateKeyFile.Name()
|
||||||
|
klog.Info("Created temp file for private key: ", m.sshPrivateKeyFile)
|
||||||
|
|
||||||
|
// create public key file
|
||||||
|
sshPublicKeyFile, err := os.CreateTemp(sshTempDir, "id_rsa.pub")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create temp file for public key: %v", err)
|
||||||
|
}
|
||||||
|
if sshPublicKeyFile.Chmod(0644) != nil {
|
||||||
|
return fmt.Errorf("failed to chmod public key file: %v", err)
|
||||||
|
}
|
||||||
|
m.sshPublicKeyFile = sshPublicKeyFile.Name()
|
||||||
|
klog.Info("Created temp file for public key: ", m.sshPublicKeyFile)
|
||||||
|
|
||||||
|
// generate private key and convert to PEM format
|
||||||
|
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to generate private key: %v", err)
|
||||||
|
}
|
||||||
|
privDER := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||||
|
privBlock := &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: privDER,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := pem.Encode(sshPrivateKeyFile, privBlock); err != nil {
|
||||||
|
sshPrivateKeyFile.Close()
|
||||||
|
return fmt.Errorf("failed to write private key to file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := gossh.NewPublicKey(&privateKey.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to generate public key: %v", err)
|
||||||
|
}
|
||||||
|
pubBytes := gossh.MarshalAuthorizedKey(pub)
|
||||||
|
|
||||||
|
if _, err := sshPublicKeyFile.Write(pubBytes); err != nil {
|
||||||
|
return fmt.Errorf("failed to write public key to file: %v", err)
|
||||||
|
}
|
||||||
|
sshPublicKeyFile.Close()
|
||||||
|
m.sshPublicKeyContent = string(pubBytes)
|
||||||
|
klog.Infof("Generated ssh public key:%s ", m.sshPublicKeyContent)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) sshAdditionalArgs() []string {
|
||||||
|
return []string{"-i", m.sshPrivateKeyFile, "-p", m.sshPort}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MiniTestDockerDeployer) scpAdditionalArgs() []string {
|
||||||
|
return []string{"-i", m.sshPrivateKeyFile, "-P", m.sshPort}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deployer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ssh = "ssh"
|
||||||
|
const rsync = "rsync"
|
||||||
|
|
||||||
|
func executeLocalCommand(ctx context.Context, name string, args ...string) error {
|
||||||
|
cmd := exec.CommandContext(ctx, name, args...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
klog.Infof("Executing: %v", cmd.Args)
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeSSHCommand(ctx context.Context, user string, addr string, sshArguments []string, args ...string) error {
|
||||||
|
allArgs := []string{addr, "-o", "StrictHostKeyChecking=no",
|
||||||
|
"-o", "User=" + user, "-o", "UserKnownHostsFile=/dev/null"}
|
||||||
|
allArgs = append(allArgs, sshArguments...)
|
||||||
|
allArgs = append(allArgs, "--")
|
||||||
|
allArgs = append(allArgs, args...)
|
||||||
|
cmd := exec.CommandContext(ctx, "ssh", allArgs...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
klog.Infof("Executing: %v", cmd.Args)
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sshConnectionCheck(ctx context.Context, user string, addr string, sshArguments []string) error {
|
||||||
|
var err error
|
||||||
|
for i := range 10 {
|
||||||
|
// cmd cannot be reused after its failure
|
||||||
|
err = executeSSHCommand(ctx, user, addr, sshArguments, "uname", "-a")
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
klog.Infof("[%d/10]ssh command failed with error: %v", i, err)
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to connect to vm: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeRsyncSSHCommand(ctx context.Context, sshArguments []string, src string, dst string, rsyncArgs []string) error {
|
||||||
|
sshArgs := []string{ssh, "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null"}
|
||||||
|
sshArgs = append(sshArgs, sshArguments...)
|
||||||
|
|
||||||
|
allArgs := []string{"-e", strings.Join(sshArgs, " "), "-avz"}
|
||||||
|
allArgs = append(allArgs, rsyncArgs...)
|
||||||
|
allArgs = append(allArgs, src, dst)
|
||||||
|
cmd := exec.CommandContext(ctx, rsync, allArgs...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
klog.Infof("Executing: %v", cmd.Args)
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeScpCommand(ctx context.Context, user string, addr string, sshArguments []string, src string, dst string) error {
|
||||||
|
allArgs := []string{"-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null"}
|
||||||
|
allArgs = append(allArgs, sshArguments...)
|
||||||
|
|
||||||
|
allArgs = append(allArgs, fmt.Sprintf("%s@%s:%s", user, addr, src), dst)
|
||||||
|
cmd := exec.CommandContext(ctx, "scp", allArgs...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
klog.Infof("Executing: %v", cmd.Args)
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
module minitest
|
||||||
|
|
||||||
|
go 1.25.0
|
||||||
|
|
||||||
|
replace github.com/spf13/cobra => github.com/spf13/cobra v1.9.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/docker/go-connections v0.6.0
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
|
github.com/moby/moby/api v1.52.0-beta.1
|
||||||
|
github.com/moby/moby/client v0.1.0-beta.0
|
||||||
|
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
|
||||||
|
golang.org/x/crypto v0.41.0
|
||||||
|
k8s.io/klog/v2 v2.130.1
|
||||||
|
sigs.k8s.io/boskos v0.0.0-20250918103144-9ad89b7dd38e
|
||||||
|
sigs.k8s.io/kubetest2 v0.0.0-20250905115125-63caf6a17555
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/bombsimon/logrusr/v4 v4.1.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/containerd/errdefs v1.0.0 // indirect
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
||||||
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
|
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||||
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
|
github.com/spf13/cast v1.7.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.9 // indirect
|
||||||
|
github.com/spf13/viper v1.19.0 // indirect
|
||||||
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||||
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||||
|
golang.org/x/sys v0.35.0 // indirect
|
||||||
|
golang.org/x/text v0.28.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.4 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
k8s.io/apimachinery v0.32.2 // indirect
|
||||||
|
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
||||||
|
sigs.k8s.io/controller-runtime v0.16.5 // indirect
|
||||||
|
sigs.k8s.io/prow v0.0.0-20240619181241-cfb8754e0459 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,416 @@
|
||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/bombsimon/logrusr/v4 v4.1.0 h1:uZNPbwusB0eUXlO8hIUwStE6Lr5bLN6IgYgG+75kuh4=
|
||||||
|
github.com/bombsimon/logrusr/v4 v4.1.0/go.mod h1:pjfHC5e59CvjTBIU3V3sGhFWFAnsnhOR03TRc6im0l8=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
|
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||||
|
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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
|
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||||
|
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||||
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
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-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
|
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/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||||
|
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
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/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
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/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
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/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
|
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
|
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/moby/api v1.52.0-beta.1 h1:r5U4U72E7xSHh4zX72ndY1mA/FOGiAPiGiz2a8rBW+w=
|
||||||
|
github.com/moby/moby/api v1.52.0-beta.1/go.mod h1:8sBV0soUREiudtow4vqJGOxa4GyHI5vLQmvgKdHq5Ok=
|
||||||
|
github.com/moby/moby/client v0.1.0-beta.0 h1:eXzrwi0YkzLvezOBKHafvAWNmH1B9HFh4n13yb2QgFE=
|
||||||
|
github.com/moby/moby/client v0.1.0-beta.0/go.mod h1:irAv8jRi4yKKBeND96Y+3AM9ers+KaJYk9Vmcm7loxs=
|
||||||
|
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/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||||
|
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||||
|
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
|
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
|
||||||
|
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||||
|
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/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
|
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||||
|
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||||
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
|
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
|
||||||
|
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||||
|
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||||
|
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||||
|
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||||
|
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||||
|
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||||
|
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||||
|
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||||
|
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||||
|
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||||
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||||
|
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||||
|
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||||
|
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||||
|
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||||
|
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||||
|
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||||
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
|
||||||
|
go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||||
|
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
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.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||||
|
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||||
|
golang.org/x/sys v0.35.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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||||
|
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||||
|
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||||
|
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=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
||||||
|
google.golang.org/protobuf v1.36.4/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-20180628173108-788fd7840127/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
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.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.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||||
|
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
|
||||||
|
k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||||
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
|
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
|
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
||||||
|
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
|
pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
|
||||||
|
pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
sigs.k8s.io/boskos v0.0.0-20250918103144-9ad89b7dd38e h1:OthwV3adPAnbNmaz/vkTHdeF27shWyY+wfd1ItyWLag=
|
||||||
|
sigs.k8s.io/boskos v0.0.0-20250918103144-9ad89b7dd38e/go.mod h1:v2jnRiOFvt2Ank4LbddEAFjwfj/+bv7uvrOfcNENTM8=
|
||||||
|
sigs.k8s.io/controller-runtime v0.16.5 h1:yr1cEJbX08xsTW6XEIzT13KHHmIyX8Umvme2cULvFZw=
|
||||||
|
sigs.k8s.io/controller-runtime v0.16.5/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0=
|
||||||
|
sigs.k8s.io/kubetest2 v0.0.0-20250905115125-63caf6a17555 h1:WL7/VL7GfsYTe2FUrhB5FE+B3c0rHzhFCUD2l98MHNU=
|
||||||
|
sigs.k8s.io/kubetest2 v0.0.0-20250905115125-63caf6a17555/go.mod h1:pBd0cFaT0hDqmwQg+TIhyLgPMYaH66QMLcKd09XnKTI=
|
||||||
|
sigs.k8s.io/prow v0.0.0-20240619181241-cfb8754e0459 h1:t8nFAgqf4A53NMuaML7xbBkaKcQtN3aqPPHDsVLfWWs=
|
||||||
|
sigs.k8s.io/prow v0.0.0-20240619181241-cfb8754e0459/go.mod h1:B6hUZArrw0kjY/Q4I5qBJd6lQoZP0nloG0ot1cTMhaA=
|
||||||
|
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||||
|
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"minitest/deployer"
|
||||||
|
"minitest/tester"
|
||||||
|
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var deployers = map[string]func(string) deployer.MiniTestDeployer{
|
||||||
|
// boskos deployer will require a gcp project and start instances in it to run the test
|
||||||
|
// the whole gcp project will be cleaned up after tests are done
|
||||||
|
"boskos": deployer.NewMiniTestBosKosDeployerFromConfigFile,
|
||||||
|
//docker deployer is for testing minitest. This should never be used for testing minikube
|
||||||
|
"docker": deployer.NewMiniTestDockerDeployerFromConfigFile,
|
||||||
|
}
|
||||||
|
var testers = map[string]tester.MiniTestTester{
|
||||||
|
"kvm-docker-linux-amd64-integration": &tester.KVMDockerLinuxAmd64IntegrationTester{},
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
flagSet := flag.CommandLine
|
||||||
|
deployerName := flagSet.String("deployer", "boskos", "deployer to use. Options: [boskos, docker]")
|
||||||
|
config := flagSet.String("config", "", "path to deployer config file")
|
||||||
|
testerName := flagSet.String("tester", "kvm-docker-linux-amd64-integration", "tester to use. Options: [kvm-docker-linux-amd64-integration]")
|
||||||
|
klog.InitFlags(flagSet)
|
||||||
|
flagSet.Parse(os.Args[1:])
|
||||||
|
|
||||||
|
dep := getDeployer(*deployerName)(*config)
|
||||||
|
tester := getTester(*testerName)
|
||||||
|
|
||||||
|
if err := dep.Up(); err != nil {
|
||||||
|
klog.Fatalf("failed to start deployer: %v", err)
|
||||||
|
}
|
||||||
|
var testErr error
|
||||||
|
if testErr = tester.Run(dep); testErr != nil {
|
||||||
|
klog.Errorf("failed to run tests: %v", testErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dep.Down(); err != nil {
|
||||||
|
klog.Fatalf("failed to stop deployer: %v", err)
|
||||||
|
}
|
||||||
|
if testErr != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDeployer(name string) func(string) deployer.MiniTestDeployer {
|
||||||
|
d, ok := deployers[name]
|
||||||
|
if !ok {
|
||||||
|
klog.Fatalf("deployer %s not found. Available deployers: %v", name, deployers)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTester(name string) tester.MiniTestTester {
|
||||||
|
t, ok := testers[name]
|
||||||
|
if !ok {
|
||||||
|
klog.Fatalf("tester %s not found. Available testers: %v", name, testers)
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package tester
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ MiniTestTester = &KVMDockerLinuxAmd64IntegrationTester{}
|
||||||
|
|
||||||
|
// this runs the integration tests with kvm2 driver and a docker container runtime.
|
||||||
|
type KVMDockerLinuxAmd64IntegrationTester struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run implements MiniTestTester.
|
||||||
|
func (k *KVMDockerLinuxAmd64IntegrationTester) Run(runner MiniTestRunner) error {
|
||||||
|
|
||||||
|
if up, err := runner.IsUp(); err != nil || !up {
|
||||||
|
klog.Errorf("tester: deployed environment is not up: %v", err)
|
||||||
|
}
|
||||||
|
if err := runner.SyncToRemote(".", "~/minikube", []string{".cache"}); err != nil {
|
||||||
|
klog.Errorf("failed to sync file in docker deployer: %v", err)
|
||||||
|
}
|
||||||
|
pr := os.Getenv("PULL_NUMBER")
|
||||||
|
|
||||||
|
var testErr error
|
||||||
|
// install docker and libvirtd first then run the test in a new shell
|
||||||
|
if err := runner.Execute("cd minikube && ./hack/prow/integration_kvm_docker_linux_x86-64_pre.sh"); err != nil {
|
||||||
|
klog.Errorf("failed to install docker in env: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if testErr = runner.Execute(fmt.Sprintf("cd minikube && PULL_NUMBER=\"%s\" ./hack/prow/integration_kvm_docker_linux_x86-64.sh", pr)); testErr != nil {
|
||||||
|
klog.Errorf("failed to execute command in env: %v", testErr)
|
||||||
|
// don't return here, we still want to collect the test reports
|
||||||
|
}
|
||||||
|
|
||||||
|
// prow requires result file to be copied to $ARTIFACTS. All other files will not be persisted.
|
||||||
|
if err := copyFileToArtifact(runner); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return testErr
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package tester
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MiniTestRunner interface {
|
||||||
|
// IsUp should return true if a test cluster is successfully provisioned
|
||||||
|
IsUp() (bool, error)
|
||||||
|
// Execute execute a command in the deployed environment
|
||||||
|
Execute(args ...string) error
|
||||||
|
// SyncToRemote copy files from src on host to dst on deployed environment
|
||||||
|
SyncToRemote(src string, dst string, excludedPattern []string) error
|
||||||
|
// SyncToRemote copy files from src on remote to host
|
||||||
|
SyncToHost(src string, dst string, excludedPattern []string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type MiniTestTester interface {
|
||||||
|
// Run should run the actual tests
|
||||||
|
Run(MiniTestRunner) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFileToArtifact(runner MiniTestRunner) error {
|
||||||
|
artifactLocation := os.Getenv("ARTIFACTS")
|
||||||
|
klog.Infof("copying to %s", artifactLocation)
|
||||||
|
|
||||||
|
if err := runner.SyncToHost("~/minikube/testout.txt", artifactLocation, nil); err != nil {
|
||||||
|
klog.Errorf("failed to sync testout.txt from deployer: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := runner.SyncToHost("~/minikube/test.json", artifactLocation, nil); err != nil {
|
||||||
|
klog.Errorf("failed to sync test.json in from deployer: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := runner.SyncToHost("~/minikube/junit-unit.xml", artifactLocation, nil); err != nil {
|
||||||
|
klog.Errorf("failed to sync junit-unit.xml in from deployer: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := runner.SyncToHost("~/minikube/test.html", artifactLocation, nil); err != nil {
|
||||||
|
klog.Errorf("failed to sync test.html in from deployer: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := runner.SyncToHost("~/minikube/test_summary.json", artifactLocation, nil); err != nil {
|
||||||
|
klog.Errorf("failed to sync test_summary.json in from deployer: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
.PHONY: integration-prow-kvm-docker-linux-x86-64
|
||||||
|
|
||||||
|
integration-prow-kvm-docker-linux-x86-64:
|
||||||
|
# build first
|
||||||
|
# container-runtime=docker driver=kvm on linux/amd64
|
||||||
|
./hack/prow/minikube_cross_build.sh $(GO_VERSION) linux amd64
|
||||||
|
# set up ssh keys for gcloud cli. These env vars are set by test/infra
|
||||||
|
mkdir -p -m 0700 ~/.ssh
|
||||||
|
cp -f "${GCE_SSH_PRIVATE_KEY_FILE}" ~/.ssh/google_compute_engine
|
||||||
|
cp -f "${GCE_SSH_PUBLIC_KEY_FILE}" ~/.ssh/google_compute_engine.pub
|
||||||
|
GOTOOLCHAIN=auto go build -C ./hack/prow/minitest -o $(PWD)/out/minitest .
|
||||||
|
./out/minitest --deployer boskos --tester kvm-docker-linux-amd64-integration --config hack/prow/kvm.json
|
||||||
|
|
@ -57,6 +57,11 @@ var (
|
||||||
`github.com/medyagh/gopogh/cmd/gopogh@.*`: `github.com/medyagh/gopogh/cmd/gopogh@{{.StableVersion}}`,
|
`github.com/medyagh/gopogh/cmd/gopogh@.*`: `github.com/medyagh/gopogh/cmd/gopogh@{{.StableVersion}}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"hack/prow/installer/check_install_gopogh.sh": {
|
||||||
|
Replace: map[string]string{
|
||||||
|
`github.com/medyagh/gopogh/cmd/gopogh@.*`: `github.com/medyagh/gopogh/cmd/gopogh@{{.StableVersion}}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,11 @@ var (
|
||||||
`gotest.tools/gotestsum@.*`: `gotest.tools/gotestsum@{{.StableVersion}}`,
|
`gotest.tools/gotestsum@.*`: `gotest.tools/gotestsum@{{.StableVersion}}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"hack/prow/installer/check_install_gotestsum.sh": {
|
||||||
|
Replace: map[string]string{
|
||||||
|
`gotest.tools/gotestsum@.*`: `gotest.tools/gotestsum@{{.StableVersion}}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ publish = "site/public/"
|
||||||
command = "pwd && cd themes/docsy && npm install && git submodule update -f --init && cd ../.. && hugo"
|
command = "pwd && cd themes/docsy && npm install && git submodule update -f --init && cd ../.. && hugo"
|
||||||
|
|
||||||
[build.environment]
|
[build.environment]
|
||||||
NODE_VERSION = "20.19.5"
|
# node Active LTS
|
||||||
HUGO_VERSION = "v0.148.2"
|
NODE_VERSION = "24.11.0"
|
||||||
|
# https://github.com/gohugoio/hugo/releases
|
||||||
|
HUGO_VERSION = "0.152.2"
|
||||||
|
|
||||||
[context.production.environment]
|
[context.production.environment]
|
||||||
HUGO_ENV = "production"
|
HUGO_ENV = "production"
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,6 @@ var Addons = map[string]*Addon{
|
||||||
"0640"),
|
"0640"),
|
||||||
}, false, "istio", "3rd party (Istio)", "", "https://istio.io/latest/docs/setup/platform-setup/minikube/", nil, nil),
|
}, false, "istio", "3rd party (Istio)", "", "https://istio.io/latest/docs/setup/platform-setup/minikube/", nil, nil),
|
||||||
"inspektor-gadget": NewAddon([]*BinAsset{
|
"inspektor-gadget": NewAddon([]*BinAsset{
|
||||||
MustBinAsset(addons.InspektorGadgetAssets, "inspektor-gadget/ig-crd.yaml", vmpath.GuestAddonsDir, "ig-crd.yaml", "0640"),
|
|
||||||
MustBinAsset(addons.InspektorGadgetAssets, "inspektor-gadget/ig-deployment.yaml.tmpl", vmpath.GuestAddonsDir, "ig-deployment.yaml", "0640"),
|
MustBinAsset(addons.InspektorGadgetAssets, "inspektor-gadget/ig-deployment.yaml.tmpl", vmpath.GuestAddonsDir, "ig-deployment.yaml", "0640"),
|
||||||
}, false, "inspektor-gadget", "3rd party (inspektor-gadget.io)", "https://github.com/orgs/inspektor-gadget/people", "https://minikube.sigs.k8s.io/docs/handbook/addons/inspektor-gadget/",
|
}, false, "inspektor-gadget", "3rd party (inspektor-gadget.io)", "https://github.com/orgs/inspektor-gadget/people", "https://minikube.sigs.k8s.io/docs/handbook/addons/inspektor-gadget/",
|
||||||
map[string]string{
|
map[string]string{
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
@ -101,6 +102,23 @@ func TestISOImage(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("VersionJSON", func(t *testing.T) {
|
||||||
|
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "ssh", "cat /version.json"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to read /version.json. args %q: %v", rr.Command(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var data map[string]string
|
||||||
|
if err := json.Unmarshal(rr.Stdout.Bytes(), &data); err != nil {
|
||||||
|
t.Fatalf("failed to parse /version.json as JSON: %v. \nContent: %s", err, rr.Stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Successfully parsed /version.json:")
|
||||||
|
for k, v := range data {
|
||||||
|
t.Logf(" %s: %s", k, v)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("eBPFSupport", func(t *testing.T) {
|
t.Run("eBPFSupport", func(t *testing.T) {
|
||||||
// Ensure that BTF type information is available (https://github.com/kubernetes/minikube/issues/21788)
|
// Ensure that BTF type information is available (https://github.com/kubernetes/minikube/issues/21788)
|
||||||
btfFile := "/sys/kernel/btf/vmlinux"
|
btfFile := "/sys/kernel/btf/vmlinux"
|
||||||
|
|
|
||||||
|
|
@ -545,12 +545,12 @@
|
||||||
"Please re-eval your podman-env, To ensure your environment variables have updated ports:\n\n\t'minikube -p {{.profile_name}} podman-env'\n\n\t": "Veuillez réévaluer votre podman-env, pour vous assurer que vos variables d'environnement ont des ports mis à jour :\n\n\t'minikube -p {{.profile_name}} podman-env'\n\n\t",
|
"Please re-eval your podman-env, To ensure your environment variables have updated ports:\n\n\t'minikube -p {{.profile_name}} podman-env'\n\n\t": "Veuillez réévaluer votre podman-env, pour vous assurer que vos variables d'environnement ont des ports mis à jour :\n\n\t'minikube -p {{.profile_name}} podman-env'\n\n\t",
|
||||||
"Please run `minikube logs --file=logs.txt` and attach logs.txt to the GitHub issue.": "Veuillez exécuter `minikube logs --file=logs.txt` et attachez logs.txt au problème GitHub.",
|
"Please run `minikube logs --file=logs.txt` and attach logs.txt to the GitHub issue.": "Veuillez exécuter `minikube logs --file=logs.txt` et attachez logs.txt au problème GitHub.",
|
||||||
"Please see {{.documentation_url}} for more details": "Veuillez consulter {{.documentation_url}} pour plus de détails",
|
"Please see {{.documentation_url}} for more details": "Veuillez consulter {{.documentation_url}} pour plus de détails",
|
||||||
"Please specify the directory to be mounted:\n\tminikube mount \u003csource directory\u003e:\u003ctarget directory\u003e (example: \"/host-home:/vm-home\")": "",
|
"Please specify the directory to be mounted:\n\tminikube mount \u003csource directory\u003e:\u003ctarget directory\u003e (example: \"/host-home:/vm-home\")": "Veuillez spécifier le répertoire à monter :\n\tminikube mount \u003crépertoire source\u003e:\u003crépertoire cible\u003e (exemple : \"/host-home:/vm-home\")",
|
||||||
"Please specify the directory to be mounted: \n\tminikube mount \u003csource directory\u003e:\u003ctarget directory\u003e (example: \"/host-home:/vm-home\")": "Veuillez spécifier le répertoire à monter : \n\tminikube mount \u003csource directory\u003e:\u003ctarget directory\u003e (exemple : \"/host-home:/vm-home\")",
|
"Please specify the directory to be mounted: \n\tminikube mount \u003csource directory\u003e:\u003ctarget directory\u003e (example: \"/host-home:/vm-home\")": "Veuillez spécifier le répertoire à monter : \n\tminikube mount \u003csource directory\u003e:\u003ctarget directory\u003e (exemple : \"/host-home:/vm-home\")",
|
||||||
"Please specify the path to copy:\n\tminikube cp \u003csource file path\u003e \u003ctarget file absolute path\u003e (example: \"minikube cp a/b.txt /copied.txt\")": "",
|
"Please specify the path to copy:\n\tminikube cp \u003csource file path\u003e \u003ctarget file absolute path\u003e (example: \"minikube cp a/b.txt /copied.txt\")": "Veuillez spécifier le chemin à copier :\n\tminikube cp \u003cchemin du fichier source\u003e \u003cchemin absolu du fichier cible\u003e (exemple : \"minikube cp a/b.txt /copied.txt\")",
|
||||||
"Please specify the path to copy: \n\tminikube cp \u003csource file path\u003e \u003ctarget file absolute path\u003e (example: \"minikube cp a/b.txt /copied.txt\")": "Veuillez spécifier le chemin à copier : \n\tminikube cp \u003cchemin du fichier source\u003e \u003cchemin absolu du fichier cible\u003e (exemple : \"minikube cp a/b.txt /copied.txt\")",
|
"Please specify the path to copy: \n\tminikube cp \u003csource file path\u003e \u003ctarget file absolute path\u003e (example: \"minikube cp a/b.txt /copied.txt\")": "Veuillez spécifier le chemin à copier : \n\tminikube cp \u003cchemin du fichier source\u003e \u003cchemin absolu du fichier cible\u003e (exemple : \"minikube cp a/b.txt /copied.txt\")",
|
||||||
"Please try purging minikube using `minikube delete --all --purge`": "Veuillez essayer de purger minikube en utilisant `minikube delete --all --purge`",
|
"Please try purging minikube using `minikube delete --all --purge`": "Veuillez essayer de purger minikube en utilisant `minikube delete --all --purge`",
|
||||||
"Please visit the following link for documentation around this:\n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages\n": "",
|
"Please visit the following link for documentation around this:\n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages\n": "Veuillez consulter le lien suivant pour obtenir de la documentation à ce sujet :\n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages\n",
|
||||||
"Please visit the following link for documentation around this: \n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages\n": "Veuillez visiter le lien suivant pour la documentation à ce sujet : \n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with -github-packages#authentiating-to-github-packages\n",
|
"Please visit the following link for documentation around this: \n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages\n": "Veuillez visiter le lien suivant pour la documentation à ce sujet : \n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with -github-packages#authentiating-to-github-packages\n",
|
||||||
"Populates the specified folder with documentation in markdown about minikube": "Remplit le dossier spécifié avec la documentation en markdown sur minikube",
|
"Populates the specified folder with documentation in markdown about minikube": "Remplit le dossier spécifié avec la documentation en markdown sur minikube",
|
||||||
"PowerShell is running in constrained mode, which is incompatible with Hyper-V scripting.": "PowerShell s'exécute en mode contraint, ce qui est incompatible avec les scripts Hyper-V.",
|
"PowerShell is running in constrained mode, which is incompatible with Hyper-V scripting.": "PowerShell s'exécute en mode contraint, ce qui est incompatible avec les scripts Hyper-V.",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue