From 7d3dd2b80e072e5b2956dcc861c3c37e23554860 Mon Sep 17 00:00:00 2001 From: Vishwas Rajashekar Date: Wed, 20 May 2026 22:00:32 +0530 Subject: [PATCH] feat(sync): add kind BATS test for streaming Signed-off-by: Vishwas Rajashekar --- test/blackbox/ci.sh | 2 +- test/blackbox/sync_streaming_kind.bats | 209 +++++++++++++++++++++++++ test/ports.json | 6 + 3 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 test/blackbox/sync_streaming_kind.bats diff --git a/test/blackbox/ci.sh b/test/blackbox/ci.sh index 2ad502d3..6efa4bdb 100755 --- a/test/blackbox/ci.sh +++ b/test/blackbox/ci.sh @@ -19,7 +19,7 @@ tests=("pushpull" "pushpull_authn" "delete_images" "referrers" "metadata" "anony "annotations" "detect_manifest_collision" "cve" "sync" "sync_docker" "sync_replica_cluster" "scrub" "garbage_collect" "metrics" "metrics_minimal" "multiarch_index" "docker_compat" "redis_local" "redis_session_store" "events_nats" "events_http" "events_nats_lint_failure" "events_http_lint_failure" "events_sink_failure" "events_config_decoding" - "fips140" "fips140_authn" "openid_claim_mapping" "upgrade" "upgrade_minimal" "dynamic_tls" "quota" "sync_streaming") + "fips140" "fips140_authn" "openid_claim_mapping" "upgrade" "upgrade_minimal" "dynamic_tls" "quota" "sync_streaming" "sync_streaming_kind") for test in ${tests[*]}; do ${BATS} ${BATS_FLAGS} ${SCRIPTPATH}/${test}.bats > ${test}.log & pids+=($!) diff --git a/test/blackbox/sync_streaming_kind.bats b/test/blackbox/sync_streaming_kind.bats new file mode 100644 index 00000000..6e3ddb82 --- /dev/null +++ b/test/blackbox/sync_streaming_kind.bats @@ -0,0 +1,209 @@ +# Note: Intended to be run as "make run-blackbox-tests" or "make run-blackbox-ci" + +# This test suite verifies that zot's streaming on-demand sync works correctly +# when kubelet pulls images through zot. + +load helpers_zot +load helpers_wait +load ../port_helper + +KIND="${ROOT_DIR}/hack/tools/bin/kind" +CLUSTER_NAME="zotstream" + +function verify_prerequisites() { + local ok=0 + for cmd in curl jq skopeo docker kubectl; do + if ! command -v "${cmd}" &>/dev/null; then + echo "you need to install ${cmd} as a prerequisite to running the tests" >&3 + ok=1 + fi + done + + if [ ! -f "${KIND}" ]; then + echo "kind not found at ${KIND}; run 'make check-blackbox-prerequisites' first" >&3 + ok=1 + fi + + return "${ok}" +} + +function setup_file() { + if ! verify_prerequisites; then + exit 1 + fi + + local test_root="${BATS_FILE_TMPDIR}/zot-test" + mkdir -p "${test_root}" + + echo "${test_root}" > "${BATS_FILE_TMPDIR}/test_root" + + local test_port + test_port=$(get_free_port_for_service "zot_test") + echo "${test_port}" > "${BATS_FILE_TMPDIR}/zot.test.port" + + # Create docker network + docker network create kind 2>/dev/null || true + local host_ip + host_ip=$(docker network inspect kind \ + --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' \ + | grep -Eo '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -1) + + if [ -z "${host_ip}" ]; then + echo "ERROR: could not determine host IP from kind Docker network" >&2 + exit 1 + fi + + echo "${host_ip}" > "${BATS_FILE_TMPDIR}/host_ip" + echo "kind network gateway (host IP from nodes): ${host_ip}" >&3 + + local test_config="${BATS_FILE_TMPDIR}/zot_test_config.json" + cat > "${test_config}" <&3 + wait_zot_reachable "${test_port}" + echo "zot-test is reachable" >&3 + + local kubeconfig="${BATS_FILE_TMPDIR}/kubeconfig" + echo "${kubeconfig}" > "${BATS_FILE_TMPDIR}/kubeconfig.path" + + # Remove any leftover cluster from a previous run + if "${KIND}" get clusters 2>/dev/null | grep -qx "${CLUSTER_NAME}"; then + "${KIND}" delete cluster --name "${CLUSTER_NAME}" + fi + + # Configure containerd so that ${host_ip}:${test_port} is treated as a + # plain-HTTP registry. + local kind_config="${BATS_FILE_TMPDIR}/kind_config.yaml" + cat > "${kind_config}" <&3 + "${KIND}" create cluster \ + --config "${kind_config}" \ + --kubeconfig "${kubeconfig}" \ + --wait 240s + echo "kind cluster '${CLUSTER_NAME}' is ready" >&3 + + # https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry + # + # document the local registry + cat </dev/null || echo "") + local kubeconfig + kubeconfig=$(cat "${BATS_FILE_TMPDIR}/kubeconfig.path" 2>/dev/null || echo "") + + echo "=== zot-test log ===" >&3 + [ -n "${test_root}" ] && cat "${test_root}/zot.log" >&3 || true + + if [ -n "${kubeconfig}" ] && [ -f "${kubeconfig}" ]; then + echo "=== kubernetes pod state ===" >&3 + kubectl --kubeconfig="${kubeconfig}" get pods -A >&3 || true + echo "=== kubernetes events ===" >&3 + kubectl --kubeconfig="${kubeconfig}" get events \ + --sort-by='.lastTimestamp' >&3 || true + fi + + zot_stop_all + + if "${KIND}" get clusters 2>/dev/null | grep -qx "${CLUSTER_NAME}"; then + "${KIND}" delete cluster --name "${CLUSTER_NAME}" + fi +} + +@test "kubelet pulls image through streaming sync successfully" { + local test_port + test_port=$(cat "${BATS_FILE_TMPDIR}/zot.test.port") + local host_ip + host_ip=$(cat "${BATS_FILE_TMPDIR}/host_ip") + local kubeconfig + kubeconfig=$(cat "${BATS_FILE_TMPDIR}/kubeconfig.path") + + local pod_manifest="${BATS_FILE_TMPDIR}/debian-pod.yaml" + cat > "${pod_manifest}" <