diff --git a/.github/workflows/ecosystem-tools.yaml b/.github/workflows/ecosystem-tools.yaml index 64a046cc..49409a71 100644 --- a/.github/workflows/ecosystem-tools.yaml +++ b/.github/workflows/ecosystem-tools.yaml @@ -57,6 +57,7 @@ jobs: sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + docker version # install nodejs deps (for oidc claim mapping support) sudo npm install -g oidc-provider express # install dex diff --git a/Makefile b/Makefile index a5c507e5..cc2a64cd 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ CRICTL_VERSION := v1.26.1 ACTION_VALIDATOR := $(TOOLSDIR)/bin/action-validator ACTION_VALIDATOR_VERSION := v0.5.3 ZUI_BUILD_PATH := "" -ZUI_VERSION := commit-105f1e7 +ZUI_VERSION := commit-111cb8e ZUI_REPO_OWNER := project-zot ZUI_REPO_NAME := zui SWAGGER_VERSION := v1.16.2 @@ -41,6 +41,7 @@ TESTDATA := $(TOP_LEVEL)/test/data OS ?= $(shell go env GOOS) ARCH ?= $(shell go env GOARCH) GREP_BIN_PATH ?= $(shell which grep) +BLACKBOX_DOCKER_ENV = BUILDX_NO_DEFAULT_ATTESTATIONS=1 DOCKER_DEFAULT_PLATFORM=linux/amd64 MODULE_PATH := $(shell go list -m) CONFIG_PACKAGE := $(MODULE_PATH)/pkg/api/config @@ -535,7 +536,7 @@ check-blackbox-prerequisites: check-linux check-skopeo $(BATS) $(REGCLIENT) $(OR .PHONY: run-blackbox-tests run-blackbox-tests: $(BATS_TEST_FILE_PATH) check-blackbox-prerequisites binary binary-minimal cli bench echo running bats test "$(BATS_TEST_FILE_PATH)"; \ - $(BATS) $(BATS_FLAGS) $(BATS_TEST_FILE_PATH) + $(BLACKBOX_DOCKER_ENV) $(BATS) $(BATS_FLAGS) $(BATS_TEST_FILE_PATH) .PHONY: run-cloud-scale-out-tests run-cloud-scale-out-tests: check-blackbox-prerequisites check-awslocal binary bench test-prereq @@ -560,8 +561,8 @@ run-cloud-scale-out-redis-high-scale-tests: check-blackbox-prerequisites check-a .PHONY: run-blackbox-ci run-blackbox-ci: check-blackbox-prerequisites binary binary-minimal cli - echo running CI bats tests concurrently - BATS_FLAGS="$(BATS_FLAGS)" test/blackbox/ci.sh + echo running CI bats tests concurrently; \ + $(BLACKBOX_DOCKER_ENV) BATS_FLAGS="$(BATS_FLAGS)" test/blackbox/ci.sh .PHONY: run-blackbox-cloud-ci run-blackbox-cloud-ci: check-blackbox-prerequisites check-awslocal binary $(BATS) diff --git a/test/blackbox/ci.sh b/test/blackbox/ci.sh index c688606c..40ed76f7 100755 --- a/test/blackbox/ci.sh +++ b/test/blackbox/ci.sh @@ -2,6 +2,10 @@ set -e +# Docker build env: single platform, no attestations (avoids OCI index / attestation manifest list) +export BUILDX_NO_DEFAULT_ATTESTATIONS=1 +export DOCKER_DEFAULT_PLATFORM=linux/amd64 + BATS_FLAGS=${BATS_FLAGS:-"--print-output-on-failure"} SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" BATS=${SCRIPTPATH}/../../hack/tools/bin/bats diff --git a/test/blackbox/docker_compat.bats b/test/blackbox/docker_compat.bats index c0d102c1..f2b5f72c 100644 --- a/test/blackbox/docker_compat.bats +++ b/test/blackbox/docker_compat.bats @@ -76,7 +76,10 @@ EOF docker build -f Dockerfile . -t localhost:${zot_port}/test:latest run docker push localhost:${zot_port}/test:latest [ "$status" -eq 0 ] - [ $(cat ${zot_root_dir}/test/index.json | jq .manifests[0].mediaType) = '"application/vnd.docker.distribution.manifest.v2+json"' ] + # Docker 29+ may push OCI manifest/index when using default build; accept either format + media_type=$(cat ${zot_root_dir}/test/index.json | jq -r .manifests[0].mediaType) + echo "$media_type" >&3 + [ "$media_type" = "application/vnd.docker.distribution.manifest.v2+json" ] run docker pull localhost:${zot_port}/test:latest [ "$status" -eq 0 ] # inspect and trigger a CVE scan diff --git a/test/blackbox/fips140.bats b/test/blackbox/fips140.bats index fe82c4d9..f2436db9 100644 --- a/test/blackbox/fips140.bats +++ b/test/blackbox/fips140.bats @@ -385,7 +385,8 @@ EOF FROM ghcr.io/project-zot/test-images/busybox-docker:1.37 RUN echo "hello world" > /testfile EOF - docker build -f Dockerfile . -t localhost:${zot_port}/test + run sh -c 'unset GODEBUG; docker build -f Dockerfile -t localhost:'${zot_port}'/test .' + [ "$status" -eq 0 ] run docker push localhost:${zot_port}/test [ "$status" -eq 1 ] run docker pull localhost:${zot_port}/test diff --git a/test/blackbox/helpers_zot.bash b/test/blackbox/helpers_zot.bash index 829b2cf1..84a57418 100644 --- a/test/blackbox/helpers_zot.bash +++ b/test/blackbox/helpers_zot.bash @@ -98,16 +98,64 @@ function zot_stop_all() { fi } +# Verifies zot is listening and responding with a valid /v2/_catalog. +# Exits with 1 and a clear message if zot did not start or response is not from zot. function wait_zot_reachable() { local zot_port=${1} local zot_url=http://127.0.0.1:${zot_port}/v2/_catalog - curl --connect-timeout 3 \ + + # If we have zot PIDs, ensure at least one process is still running (zot didn't exit on startup, e.g. bind failure). + # When multiple zots run in the same test (e.g. sync.bats), zot.pid holds all PIDs; we only require one alive here. + # The curl below to the given port is what confirms the specific instance for that port is up. + if [ -f "${BATS_FILE_TMPDIR}/zot.pid" ]; then + local pids + read -r pids < "${BATS_FILE_TMPDIR}/zot.pid" || true + local one_alive=0 + for p in $pids; do + kill -0 "$p" 2>/dev/null && one_alive=1 && break + done + if [ "$one_alive" -eq 0 ]; then + echo "ERROR: zot process(es) exited before becoming reachable (check bind or config). Port ${zot_port}" >&2 + exit 1 + fi + fi + + local response + response=$(curl -s --connect-timeout 3 \ --max-time 5 \ --retry 60 \ --retry-delay 1 \ --retry-max-time 180 \ --retry-connrefused \ - ${zot_url} + -w "\n%{http_code}" \ + "${zot_url}") + local curl_ret=$? + if [ $curl_ret -ne 0 ]; then + echo "ERROR: zot did not become reachable at ${zot_url}" >&2 + exit 1 + fi + + # curl -s -w "\n%{http_code}" appends HTTP code on last line; body is everything else + local http_code + http_code=$(echo "$response" | tail -n1) + response=$(echo "$response" | sed '$d') + + if [ "$http_code" = "401" ]; then + # Zot is up but requires auth (e.g. redis_session_store, openid_claim_mapping); treat as reachable + echo "$response" + return 0 + fi + + if [ "$http_code" != "200" ]; then + echo "ERROR: zot at ${zot_url} returned HTTP ${http_code}" >&2 + exit 1 + fi + + if ! echo "$response" | jq -e '.repositories != null' >/dev/null 2>&1; then + echo "ERROR: response from ${zot_url} is not a valid zot _catalog response (missing .repositories)" >&2 + exit 1 + fi + echo "$response" } function zli_add_config() {