File docker-integration.sh of Package docker

#!/bin/bash
# docker-integration: run Docker's integration tests
# Copyright (C) 2024 SUSE LLC
#
# 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 -Eeuo pipefail

TESTDIR=/usr/src/docker-test
TEST_SRCDIR="$TESTDIR/src"
TEST_BINDIR="$TESTDIR/bin"

TMPROOT="$(mktemp --tmpdir -d docker-integration-tmpdir.XXXXXX)"
TMPDIR="$TMPROOT/tmp"
DEST="$TMPROOT/dest"

mkdir -p "$TMPDIR" "$TEST_BINDIR" "$DEST"
chmod 1777 "$TMPDIR"
chmod 777 "$TMPROOT"

function usage() {
	cat >&2 <<-EOF
	docker-integration.sh [-Av] [-r TestName] [-t timeout] [<test-suites>...]

	Arguments:
	  -A
	         Run all tests (do not fail on first suite failure).
	  -v
	         Run tests in verbose mode (go test -v).
	  -r
	         Only run tests that match the given regular expression (go test -run).
	  -t <timeout=$timeout>
	         Set the per-suite timeout to <timeout> (go test -timeout).
	  <test-suites>...
	         Only run the given test suites in /usr/src/docker-test. The
	         default is to run all test suites

	Examples:

	  Run the build and network integration tests with a 60 minute timeout:

	    ./docker-integration.sh -t 60m integration/build integration/network

	  Run all of the tests in verbose mode with a 6 hour timeout:

	    ./docker-integration.sh -Av -t 360m

	This script is maintained by openSUSE in the Virtualization:containers
	project, and is only intended to be used by openSUSE developers.
	EOF
	exit "${1:-1}"
}

fail_fast=1
verbose=
filter=
timeout=20m
while getopts "Ahr:t:v" opt; do
	case "$opt" in
	A)
		fail_fast=
		;;
	v)
		verbose=1
		;;
	r)
		filter="$OPTARG"
		;;
	t)
		timeout="$OPTARG"
		;;
	h)
		usage 0
		;;
	:)
		echo "Missing argument: -$OPTARG" >&2
		usage 1
		;;
	\?)
		echo "Invalid option: -$OPTARG" >&2
		usage 1
		;;
	esac
done

pushd "$TEST_SRCDIR"

if [ "$OPTIND" -le "$#" ]; then
	SUITES=("${@:$OPTIND:$(($#+1))}")
else
	readarray -t SUITES <<<"$(find . -type f -name test.main -printf "%h\n")"
fi
echo "Planning to run suites {${SUITES[@]}}."

# Download the frozen images.
if ! [ -d /docker-frozen-images ]; then
	# TODO: Get the hashes from /usr/src/docker-test/Dockerfile...
	contrib/download-frozen-image-v2.sh "$TMPDIR/docker-frozen-images" \
		busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 \
		busybox:glibc@sha256:1f81263701cddf6402afe9f33fca0266d9fff379e59b1748f33d3072da71ee85 \
		debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 \
		hello-world:latest@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 \
		arm32v7/hello-world:latest@sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1
	sudo cp -r "$TMPDIR/docker-frozen-images" /
fi

# Create binaries in $TEST_BINDIR.
if ! [ -e "$TEST_BINDIR/docker-basic-plugin" ]; then
	(
		pushd "$TEST_SRCDIR/testutil/fixtures/plugin/basic"

		go mod init docker-basic-plugin
		go build -o "$TEST_BINDIR/docker-basic-plugin" .
	)
fi
if ! [ -e "$TEST_BINDIR/registry-v2" ]; then
	# The v2.x tags of Docker registry don't use go.mod, and pre-date the move
	# to github.com/distribution, so we need to create a fake GOPATH with the
	# old github.com/docker/distribution import path.
	(
		export GOPATH="$(mktemp -d -p "$TMPROOT" distribution-build-gopath.XXXXXX)"
		pushd "$GOPATH"

		git clone \
			--depth=1 --branch=v2.8.3 \
			https://github.com/distribution/distribution.git \
			src/github.com/docker/distribution

		pushd src/github.com/docker/distribution

		GO111MODULE=off go build -o "$TEST_BINDIR/registry-v2" ./cmd/registry
	)
fi
if ! [ -e "$TEST_BINDIR/ctr" ]; then
	containerd-ctr --help >/dev/null
	ln -sf "$(which containerd-ctr)" "$TEST_BINDIR/ctr"
fi
if ! [ -e "$TEST_BINDIR/docker" ]; then
	# The integration-cli tests require a Docker 17.06.2 client (from 2017).
	# This is mainly because the tests are all based on the specific output the
	# client gives, and some tests fail on modern client versions.
	(
		export GOPATH="$(mktemp -d -p "$TMPROOT" distribution-build-gopath.XXXXXX)"
		pushd "$GOPATH"

		# This tag also comes from the time when this was called
		# github.com/docker/docker-ce-packaging, so we need to work around this
		# by moving the cli component into the right path...
		git clone \
			--depth=1 --branch=v17.06.2-ce \
			https://github.com/docker/cli.git \
			src/github.com/docker/docker-ce-packaging
		mv \
			src/github.com/docker/docker-ce-packaging/components/cli \
			src/github.com/docker/cli

		pushd src/github.com/docker/cli
		GO111MODULE=off go build -o "$TEST_BINDIR/docker" ./cmd/docker
	)
fi

# Create an unprivilegeduser account for tests.
if ! ( grep unprivilegeduser /etc/passwd &>/dev/null ); then
	useradd --create-home --gid docker unprivilegeduser
fi

# Disable SUSE secrets for tests, as some tests (TestDiff from
# integration/container) will fail if we have secrets injected.
[ -e /etc/docker/suse-secrets-enable ] && \
	mv -nv /etc/docker/suse-secrets-enable{,-DISABLED}
sudo systemctl restart docker

# Make sure docker-buildx is disabled.
[ -e /usr/lib/docker/cli-plugins/docker-buildx ] && \
	mv -nv /usr/lib/docker/cli-plugins/docker-buildx{,-DISABLED}

# Disable any daemon configurations.
[ -e /etc/docker/daemon.json ] && \
	mv -nv /etc/docker/daemon.json{,.DISABLED}

set -x

# In order for< gotest.tools/v3/assert> to parse the source and give us useful
# error messages, we have to create a fake source directory that points at
# $TEST_SRCDIR. This path is replaced with %{docker_builddir} during the
# docker.spec build.
__DOCKER_BUILDIR="@@docker_builddir@@"
DOCKER_BUILDDIR="${DOCKER_BUILDDIR:-$__DOCKER_BUILDIR}"
sudo rm -rvf "$DOCKER_BUILDDIR"
sudo mkdir -p "$(dirname "$DOCKER_BUILDDIR")"
sudo ln -svf "$TEST_SRCDIR" "$DOCKER_BUILDDIR"

# Clean up any old containers/images/networks/volumes before running the tests.
# We need to do this *BEFORE* we set PATH, as the outdated $TEST_BINDIR/docker
# doesn't support some of these commands.
docker container prune -f
docker image prune -af
#docker buildx prune -af
docker network prune -f
docker volume prune -af
[ -z "$(docker plugin ls -q)" ] || docker plugin ls -q | xargs docker plugin rm -f
docker system prune -af

export DOCKERFILE="$TEST_SRCDIR/Dockerfile"
export TMPDIR="$TMPDIR"
export TEMP="$TMPDIR"
export HOME="$TMPDIR/fake-home"
export DEST="$TEST_SRCDIR/bundles"
export ABS_DEST="$DEST"
export PATH="$TEST_BINDIR:$PATH"

export TZ=UTC
export DOCKER_INTEGRATION_DAEMON_DEST="$ABS_DEST"
export DOCKER_HOST=unix:///run/docker.sock
export DOCKER_GRAPHDRIVER=overlay2
export DOCKER_USERLANDPROXY=true
export DOCKER_REMAP_ROOT="${DOCKER_REMAP_ROOT:-}"
export DOCKER_TMPDIR="$TMPDIR"
export DOCKER_SUSE_SECRETS_ENABLE=0

set +x

# Make sure that we have a dummy "destination" directory for tests.
rm -rf "$DOCKER_INTEGRATION_DAEMON_DEST"
mkdir -p "$DOCKER_INTEGRATION_DAEMON_DEST"

# Install the emptyfs images.
sh ./hack/make/.build-empty-images

ls -la "$TMPROOT"

success=0
failed_suites=()
for suite_name in "${SUITES[@]}"; do
	suite_name="${suite_name#*./}"
	pushd "$TEST_SRCDIR/$suite_name"

	test_flags=()
	[ -n "$verbose" ] && test_flags+=("-test.v")
	[ -n "$filter" ] && test_flags+=("-test.run" "$filter")

	if [[ "$suite_name" == "integration-cli" ]]; then
		# We need to disable docker-buildx for the integration-cli tests
		# because otherwise the "docker build" command will use the wrong
		# builder and the output won't match what the tests expect.
		timeout=360m
	fi
	test_flags+=("-test.timeout" "$timeout")

	echo "Running suite $suite_name (${test_flags[@]}) [success=$success fail=${#failed_suites[@]}]"

	set -x +e
	sudo -E HOME="$HOME" TMPDIR="$TMPDIR" PATH="$PATH" \
		./test.main "${test_flags[@]}"
	err="$?"
	if (( $err != 0 )); then
		[ -z "$fail_fast" ] || exit "$err"
		failed_suites+=("$suite_name")
	else
		(( success++ ))
	fi
	set +x -e

	popd
done

[ -e /usr/lib/docker/cli-plugins/docker-buildx-DISABLED ] && \
	mv -nv /usr/lib/docker/cli-plugins/docker-buildx{-DISABLED,}

[ -e /etc/docker/suse-secrets-enable-DISABLED ] && \
	mv -nv /etc/docker/suse-secrets-enable{-DISABLED,}

[ -e /etc/docker/daemon.json.DISABLED ] && \
	mv -nv /etc/docker/daemon.json{.DISABLED,}

echo "Suite results: $success success(es) ${#failed_suites[@]} failure(s)."
if (( ${#failed_suites[@]} > 0 )); then
	echo "Failed suites:"
	printf " - %s\n" "${failed_suites[@]}"
	exit 1
fi
openSUSE Build Service is sponsored by