Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

system tests: refactor registry code #19106

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion hack/podman-registry
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,12 @@ function do_stop() {
podman rm -f registry

# Use straight podman, not our alias function, to avoid 'overlay: EBUSY'
${PODMAN} unshare rm -rf ${PODMAN_REGISTRY_WORKDIR}
cmd="rm -rf ${PODMAN_REGISTRY_WORKDIR}"
if [[ $(id -u) -eq 0 ]]; then
$cmd
else
${PODMAN} unshare $cmd
fi
}


Expand Down
117 changes: 2 additions & 115 deletions test/system/150-login.bats
Original file line number Diff line number Diff line change
Expand Up @@ -5,105 +5,20 @@

load helpers
load helpers.network
load helpers.registry

###############################################################################
# BEGIN one-time envariable setup

# Create a scratch directory; our podman registry will run from here. We
# also use it for other temporary files like authfiles.
if [ -z "${PODMAN_LOGIN_WORKDIR}" ]; then
export PODMAN_LOGIN_WORKDIR=$(mktemp -d --tmpdir=${BATS_TMPDIR:-${TMPDIR:-/tmp}} podman_bats_login.XXXXXX)
fi

# Randomly-generated username and password
if [ -z "${PODMAN_LOGIN_USER}" ]; then
export PODMAN_LOGIN_USER="user$(random_string 4)"
export PODMAN_LOGIN_PASS=$(random_string 15)
fi

# Randomly-assigned port in the 5xxx range
if [ -z "${PODMAN_LOGIN_REGISTRY_PORT}" ]; then
export PODMAN_LOGIN_REGISTRY_PORT=$(random_free_port)
fi

# Override any user-set path to an auth file
unset REGISTRY_AUTH_FILE

# END one-time envariable setup
###############################################################################
# BEGIN filtering - none of these tests will work with podman-remote

function setup() {
skip_if_remote "none of these tests work with podman-remote"

basic_setup
start_registry
}

# END filtering - none of these tests will work with podman-remote
###############################################################################
# BEGIN first "test" - start a registry for use by other tests
#
# This isn't really a test: it's a helper that starts a local registry.
# Note that we're careful to use a root/runroot separate from our tests,
# so setup/teardown don't clobber our registry image.
#

@test "podman login [start registry]" {
AUTHDIR=${PODMAN_LOGIN_WORKDIR}/auth
mkdir -p $AUTHDIR

# Registry image; copy of docker.io, but on our own registry
local REGISTRY_IMAGE="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/registry:2.8"

# Pull registry image, but into a separate container storage
mkdir -p ${PODMAN_LOGIN_WORKDIR}/root
mkdir -p ${PODMAN_LOGIN_WORKDIR}/runroot
PODMAN_LOGIN_ARGS="--storage-driver=vfs --root ${PODMAN_LOGIN_WORKDIR}/root --runroot ${PODMAN_LOGIN_WORKDIR}/runroot"
# Give it three tries, to compensate for flakes
run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE ||
run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE ||
run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE

# Registry image needs a cert. Self-signed is good enough.
CERT=$AUTHDIR/domain.crt
if [ ! -e $CERT ]; then
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout $AUTHDIR/domain.key -x509 -days 2 \
-out $AUTHDIR/domain.crt \
-subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost" \
-addext "subjectAltName=DNS:localhost"
fi

# Copy a cert to another directory for --cert-dir option tests
mkdir -p ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir
cp $CERT ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir

# Store credentials where container will see them
if [ ! -e $AUTHDIR/htpasswd ]; then
htpasswd -Bbn ${PODMAN_LOGIN_USER} ${PODMAN_LOGIN_PASS} \
> $AUTHDIR/htpasswd

# In case $PODMAN_TEST_KEEP_LOGIN_REGISTRY is set, for testing later
echo "${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}" \
> $AUTHDIR/htpasswd-plaintext
fi

# Run the registry container.
run_podman '?' ${PODMAN_LOGIN_ARGS} rm -t 0 -f registry
run_podman ${PODMAN_LOGIN_ARGS} run -d \
-p ${PODMAN_LOGIN_REGISTRY_PORT}:5000 \
--name registry \
-v $AUTHDIR:/auth:Z \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \
$REGISTRY_IMAGE
}

# END first "test" - start a registry for use by other tests
###############################################################################
# BEGIN actual tests
# BEGIN primary podman login/push/pull tests

Expand Down Expand Up @@ -358,33 +273,5 @@ function _test_skopeo_credential_sharing() {
# END cooperation with skopeo
# END actual tests
###############################################################################
# BEGIN teardown (remove the registry container)

@test "podman login [stop registry, clean up]" {
# For manual debugging; user may request keeping the registry running
if [ -n "${PODMAN_TEST_KEEP_LOGIN_REGISTRY}" ]; then
skip "[leaving registry running by request]"
fi

run_podman --storage-driver=vfs --root ${PODMAN_LOGIN_WORKDIR}/root \
--runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
rm -f registry
run_podman --storage-driver=vfs --root ${PODMAN_LOGIN_WORKDIR}/root \
--runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
rmi -a

# By default, clean up
if [ -z "${PODMAN_TEST_KEEP_LOGIN_WORKDIR}" ]; then
rm -rf ${PODMAN_LOGIN_WORKDIR}
fi

# Make sure socket is closed
if tcp_port_probe $PODMAN_LOGIN_REGISTRY_PORT; then
die "Socket still seems open"
fi
}

# END teardown (remove the registry container)
###############################################################################

# vim: filetype=sh
29 changes: 28 additions & 1 deletion test/system/helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,36 @@ function _prefetch() {
fi
fi

# Kludge alert.
# Skopeo has no --storage-driver, --root, or --runroot flags; those
# need to be expressed in the destination string inside [brackets].
# See containers-transports(5). So if we see those options in
# _PODMAN_TEST_OPTS, transmogrify $want into skopeo form.
skopeo_opts=''
driver="$(expr "$_PODMAN_TEST_OPTS" : ".*--storage-driver \([^ ]\+\)" || true)"
if [[ -n "$driver" ]]; then
skopeo_opts+="$driver@"
fi

altroot="$(expr "$_PODMAN_TEST_OPTS" : ".*--root \([^ ]\+\)" || true)"
if [[ -n "$altroot" ]] && [[ -d "$altroot" ]]; then
skopeo_opts+="$altroot"

altrunroot="$(expr "$_PODMAN_TEST_OPTS" : ".*--runroot \([^ ]\+\)" || true)"
if [[ -n "$altrunroot" ]] && [[ -d "$altrunroot" ]]; then
skopeo_opts+="+$altrunroot"
fi
fi

if [[ -n "$skopeo_opts" ]]; then
want="[$skopeo_opts]$want"
fi

# Cached image is now guaranteed to exist. Be sure to load it
# with skopeo, not podman, in order to preserve metadata
skopeo copy --all oci-archive:$cachepath containers-storage:$want
cmd="skopeo copy --all oci-archive:$cachepath containers-storage:$want"
echo "$_LOG_PROMPT $cmd"
$cmd
}

# END tools for fetching & caching test images
Expand Down
116 changes: 116 additions & 0 deletions test/system/helpers.registry.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# -*- bash -*-
#
# helpers for starting/stopping a local registry.
#
# Used primarily in 150-login.bats
#

###############################################################################
# BEGIN one-time envariable setup

# Override any user-set path to an auth file
unset REGISTRY_AUTH_FILE

# END one-time envariable setup
###############################################################################

# Start a local registry. Only needed on demand (e.g. by 150-login.bats)
# and then only once: if we start, leave it running until final teardown.
function start_registry() {
if [[ -d "$PODMAN_LOGIN_WORKDIR/auth" ]]; then
# Already started
return
fi

AUTHDIR=${PODMAN_LOGIN_WORKDIR}/auth
mkdir -p $AUTHDIR

# Registry image; copy of docker.io, but on our own registry
local REGISTRY_IMAGE="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/registry:2.8"

# Pull registry image, but into a separate container storage
mkdir ${PODMAN_LOGIN_WORKDIR}/root
mkdir ${PODMAN_LOGIN_WORKDIR}/runroot
PODMAN_LOGIN_ARGS="--storage-driver vfs --root ${PODMAN_LOGIN_WORKDIR}/root --runroot ${PODMAN_LOGIN_WORKDIR}/runroot"
# _prefetch() will retry twice on network error, and will also use
# a pre-cached image if present (helpful on dev workstation, not in CI).
_PODMAN_TEST_OPTS="${PODMAN_LOGIN_ARGS}" _prefetch $REGISTRY_IMAGE

# Registry image needs a cert. Self-signed is good enough.
CERT=$AUTHDIR/domain.crt
if [ ! -e $CERT ]; then
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout $AUTHDIR/domain.key -x509 -days 2 \
-out $AUTHDIR/domain.crt \
-subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost" \
-addext "subjectAltName=DNS:localhost"
fi

# Copy a cert to another directory for --cert-dir option tests
mkdir -p ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir
cp $CERT ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir

# Store credentials where container will see them
htpasswd -Bbn ${PODMAN_LOGIN_USER} ${PODMAN_LOGIN_PASS} > $AUTHDIR/htpasswd

# In case $PODMAN_TEST_KEEP_LOGIN_REGISTRY is set, for testing later
echo "${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}" > $AUTHDIR/htpasswd-plaintext

# Run the registry container.
run_podman ${PODMAN_LOGIN_ARGS} run -d \
-p 127.0.0.1:${PODMAN_LOGIN_REGISTRY_PORT}:5000 \
--name registry \
-v $AUTHDIR:/auth:Z \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \
$REGISTRY_IMAGE
cid="$output"

# wait_for_port isn't enough: that just checks that podman has mapped the port...
wait_for_port 127.0.0.1 ${PODMAN_LOGIN_REGISTRY_PORT}
# ...so we look in container logs for confirmation that registry is running.
_PODMAN_TEST_OPTS="${PODMAN_LOGIN_ARGS}" wait_for_output "listening on .::.:5000" $cid
}

function stop_registry() {
if [[ ! -d "$PODMAN_LOGIN_WORKDIR/auth" ]]; then
# No registry running
return
fi

# For manual debugging; user may request keeping the registry running
if [ -n "${PODMAN_TEST_KEEP_LOGIN_REGISTRY}" ]; then
skip "[leaving registry running by request]"
fi

run_podman --storage-driver vfs \
--root ${PODMAN_LOGIN_WORKDIR}/root \
--runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
rm -f -t0 registry
run_podman --storage-driver vfs \
--root ${PODMAN_LOGIN_WORKDIR}/root \
--runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
rmi -a -f

# By default, clean up
if [ -z "${PODMAN_TEST_KEEP_LOGIN_WORKDIR}" ]; then
# FIXME: why is this necessary??? If we don't do this, we can't
# rm -rf the workdir, because ..../overlay is mounted
mount | grep ${PODMAN_LOGIN_WORKDIR} | awk '{print $3}' | xargs --no-run-if-empty umount

if [[ $(id -u) -eq 0 ]]; then
rm -rf ${PODMAN_LOGIN_WORKDIR}
else
# rootless image data is owned by a subuid
run_podman unshare rm -rf ${PODMAN_LOGIN_WORKDIR}
fi
fi

# Make sure socket is closed
if tcp_port_probe $PODMAN_LOGIN_REGISTRY_PORT; then
die "Socket still seems open"
fi
}
29 changes: 29 additions & 0 deletions test/system/setup_suite.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# -*- bash -*-
#
# global setup/teardown for the entire system test suite
#
bats_require_minimum_version 1.8.0

load helpers
load helpers.network
load helpers.registry

# Create common environment just in case we end up needing a registry.
# These environment variables will be available to all tests.
function setup_suite() {
# Can't use $BATS_SUITE_TMPDIR because podman barfs:
# Error: the specified runroot is longer than 50 characters
export PODMAN_LOGIN_WORKDIR=$(mktemp -d --tmpdir=${BATS_TMPDIR:-${TMPDIR:-/tmp}} podman-bats-registry.XXXXXX)

export PODMAN_LOGIN_USER="user$(random_string 4)"
export PODMAN_LOGIN_PASS="pw$(random_string 15)"

# FIXME: racy! It could be many minutes between now and when we start it.
# To mitigate, we use a range not used anywhere else in system tests.
export PODMAN_LOGIN_REGISTRY_PORT=$(random_free_port 42000-42999)
}

# Run at the very end of all tests. Useful for cleanup of non-BATS tmpdirs.
function teardown_suite() {
stop_registry
}