mirror of
https://github.com/containers/skopeo.git
synced 2025-04-27 11:01:18 +00:00
systemtest - new set of BATS tests for RHEL8 gating
Signed-off-by: Ed Santiago <santiago@redhat.com>
This commit is contained in:
parent
b137741385
commit
12f0e24519
19
systemtest/001-basic.bats
Normal file
19
systemtest/001-basic.bats
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
#
|
||||||
|
# Simplest set of skopeo tests. If any of these fail, we have serious problems.
|
||||||
|
#
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
# Override standard setup! We don't yet trust anything
|
||||||
|
function setup() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "skopeo version emits reasonable output" {
|
||||||
|
run_skopeo --version
|
||||||
|
|
||||||
|
expect_output --substring "skopeo version [0-9.]+"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
67
systemtest/010-inspect.bats
Normal file
67
systemtest/010-inspect.bats
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
#
|
||||||
|
# Simplest test for skopeo inspect
|
||||||
|
#
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
@test "inspect: basic" {
|
||||||
|
workdir=$TESTDIR/inspect
|
||||||
|
|
||||||
|
remote_image=docker://quay.io/libpod/alpine_labels:latest
|
||||||
|
# Inspect remote source, then pull it. There's a small race condition
|
||||||
|
# in which the remote image can get updated between the inspect and
|
||||||
|
# the copy; let's just not worry about it.
|
||||||
|
run_skopeo inspect $remote_image
|
||||||
|
inspect_remote=$output
|
||||||
|
|
||||||
|
# Now pull it into a directory
|
||||||
|
run_skopeo copy $remote_image dir:$workdir
|
||||||
|
expect_output --substring "Getting image source signatures"
|
||||||
|
expect_output --substring "Writing manifest to image destination"
|
||||||
|
|
||||||
|
# Unpacked contents must include a manifest and version
|
||||||
|
[ -e $workdir/manifest.json ]
|
||||||
|
[ -e $workdir/version ]
|
||||||
|
|
||||||
|
# Now run inspect locally
|
||||||
|
run_skopeo inspect dir:$workdir
|
||||||
|
inspect_local=$output
|
||||||
|
|
||||||
|
# Each SHA-named file must be listed in the output of 'inspect'
|
||||||
|
for sha in $(find $workdir -type f | xargs -l1 basename | egrep '^[0-9a-f]{64}$'); do
|
||||||
|
expect_output --from="$inspect_local" --substring "sha256:$sha" \
|
||||||
|
"Locally-extracted SHA file is present in 'inspect'"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Simple sanity check on 'inspect' output.
|
||||||
|
# For each of the given keys (LHS of the table below):
|
||||||
|
# 1) Get local and remote values
|
||||||
|
# 2) Sanity-check local value using simple expression
|
||||||
|
# 3) Confirm that local and remote values match.
|
||||||
|
#
|
||||||
|
# The reason for (2) is to make sure that we don't compare bad results
|
||||||
|
#
|
||||||
|
# The reason for a hardcoded list, instead of 'jq keys', is that RepoTags
|
||||||
|
# is always empty locally, but a list remotely.
|
||||||
|
while read key expect; do
|
||||||
|
local=$(echo "$inspect_local" | jq -r ".$key")
|
||||||
|
remote=$(echo "$inspect_remote" | jq -r ".$key")
|
||||||
|
|
||||||
|
expect_output --from="$local" --substring "$expect" \
|
||||||
|
"local $key is sane"
|
||||||
|
|
||||||
|
expect_output --from="$remote" "$local" \
|
||||||
|
"local $key matches remote"
|
||||||
|
done <<END_EXPECT
|
||||||
|
Architecture amd64
|
||||||
|
Created [0-9-]+T[0-9:]+\.[0-9]+Z
|
||||||
|
Digest sha256:[0-9a-f]{64}
|
||||||
|
DockerVersion [0-9]+\.[0-9][0-9.-]+
|
||||||
|
Labels \\\{.*PODMAN.*podman.*\\\}
|
||||||
|
Layers \\\[.*sha256:.*\\\]
|
||||||
|
Os linux
|
||||||
|
END_EXPECT
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
79
systemtest/020-copy.bats
Normal file
79
systemtest/020-copy.bats
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
#
|
||||||
|
# Copy tests
|
||||||
|
#
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
standard_setup
|
||||||
|
|
||||||
|
start_registry reg
|
||||||
|
}
|
||||||
|
|
||||||
|
# From remote, to dir1, to local, to dir2;
|
||||||
|
# compare dir1 and dir2, expect no changes
|
||||||
|
@test "copy: dir, round trip" {
|
||||||
|
local remote_image=docker://busybox:latest
|
||||||
|
local localimg=docker://localhost:5000/busybox:unsigned
|
||||||
|
|
||||||
|
local dir1=$TESTDIR/dir1
|
||||||
|
local dir2=$TESTDIR/dir2
|
||||||
|
|
||||||
|
run_skopeo copy $remote_image dir:$dir1
|
||||||
|
run_skopeo copy --dest-tls-verify=false dir:$dir1 $localimg
|
||||||
|
run_skopeo copy --src-tls-verify=false $localimg dir:$dir2
|
||||||
|
|
||||||
|
# Both extracted copies must be identical
|
||||||
|
diff -urN $dir1 $dir2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Same as above, but using 'oci:' instead of 'dir:' and with a :latest tag
|
||||||
|
@test "copy: oci, round trip" {
|
||||||
|
local remote_image=docker://busybox:latest
|
||||||
|
local localimg=docker://localhost:5000/busybox:unsigned
|
||||||
|
|
||||||
|
local dir1=$TESTDIR/oci1
|
||||||
|
local dir2=$TESTDIR/oci2
|
||||||
|
|
||||||
|
run_skopeo copy $remote_image oci:$dir1:latest
|
||||||
|
run_skopeo copy --dest-tls-verify=false oci:$dir1:latest $localimg
|
||||||
|
run_skopeo copy --src-tls-verify=false $localimg oci:$dir2:latest
|
||||||
|
|
||||||
|
# Both extracted copies must be identical
|
||||||
|
diff -urN $dir1 $dir2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Same image, extracted once with :tag and once without
|
||||||
|
@test "copy: oci w/ and w/o tags" {
|
||||||
|
local remote_image=docker://busybox:latest
|
||||||
|
|
||||||
|
local dir1=$TESTDIR/dir1
|
||||||
|
local dir2=$TESTDIR/dir2
|
||||||
|
|
||||||
|
run_skopeo copy $remote_image oci:$dir1
|
||||||
|
run_skopeo copy $remote_image oci:$dir2:withtag
|
||||||
|
|
||||||
|
# Both extracted copies must be identical, except for index.json
|
||||||
|
diff -urN --exclude=index.json $dir1 $dir2
|
||||||
|
|
||||||
|
# ...which should differ only in the tag. (But that's too hard to check)
|
||||||
|
grep '"org.opencontainers.image.ref.name":"withtag"' $dir2/index.json
|
||||||
|
}
|
||||||
|
|
||||||
|
# This one seems unlikely to get fixed
|
||||||
|
@test "copy: bug 651" {
|
||||||
|
skip "Enable this once skopeo issue #651 has been fixed"
|
||||||
|
|
||||||
|
run_skopeo copy --dest-tls-verify=false \
|
||||||
|
docker://quay.io/libpod/alpine_labels:latest \
|
||||||
|
docker://localhost:5000/foo
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
podman rm -f reg
|
||||||
|
|
||||||
|
standard_teardown
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
41
systemtest/030-local-registry-tls.bats
Normal file
41
systemtest/030-local-registry-tls.bats
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
#
|
||||||
|
# This is probably a never-mind.
|
||||||
|
#
|
||||||
|
# The idea is to set up a local registry with locally generated certs,
|
||||||
|
# using --dest-cert-dir to tell skopeo how to check. But no, it fails with
|
||||||
|
#
|
||||||
|
# x509: certificate signed by unknown authority
|
||||||
|
#
|
||||||
|
# Perhaps I'm missing something? Maybe I need to add something into
|
||||||
|
# /etc/pki/somewhere? If this is truly not possible to test without
|
||||||
|
# a real signature, then let's just delete this test.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
standard_setup
|
||||||
|
|
||||||
|
start_registry --with-cert reg
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "local registry, with cert" {
|
||||||
|
skip "doesn't work as expected"
|
||||||
|
|
||||||
|
local remote_image=docker://busybox:latest
|
||||||
|
local localimg=docker://localhost:5000/busybox:unsigned
|
||||||
|
|
||||||
|
# Fails with: x509: certificate signed by unknown authority
|
||||||
|
run_skopeo --debug copy --dest-cert-dir=$TESTDIR/auth \
|
||||||
|
docker://busybox:latest \
|
||||||
|
docker://localhost:5000/busybox:unsigned
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
podman rm -f reg
|
||||||
|
|
||||||
|
standard_teardown
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
76
systemtest/040-local-registry-auth.bats
Normal file
76
systemtest/040-local-registry-auth.bats
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
#
|
||||||
|
# Tests with a local registry with auth
|
||||||
|
#
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
standard_setup
|
||||||
|
|
||||||
|
# Remove old/stale cred file
|
||||||
|
_cred_file=${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/containers/auth.json
|
||||||
|
rm -f $_cred_file
|
||||||
|
|
||||||
|
# Start authenticated registry with random password
|
||||||
|
testuser=testuser
|
||||||
|
testpassword=$(random_string 15)
|
||||||
|
|
||||||
|
start_registry --testuser=testuser --testpassword=$testpassword reg
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "auth: credentials on command line" {
|
||||||
|
# No creds
|
||||||
|
run_skopeo 1 inspect --tls-verify=false docker://localhost:5000/nonesuch
|
||||||
|
expect_output --substring "unauthorized: authentication required"
|
||||||
|
|
||||||
|
# Wrong user
|
||||||
|
run_skopeo 1 inspect --tls-verify=false --creds=baduser:badpassword \
|
||||||
|
docker://localhost:5000/nonesuch
|
||||||
|
expect_output --substring "unauthorized: authentication required"
|
||||||
|
|
||||||
|
# Wrong password
|
||||||
|
run_skopeo 1 inspect --tls-verify=false --creds=$testuser:badpassword \
|
||||||
|
docker://localhost:5000/nonesuch
|
||||||
|
expect_output --substring "unauthorized: authentication required"
|
||||||
|
|
||||||
|
# Correct creds, but no such image
|
||||||
|
run_skopeo 1 inspect --tls-verify=false --creds=$testuser:$testpassword \
|
||||||
|
docker://localhost:5000/nonesuch
|
||||||
|
expect_output --substring "manifest unknown: manifest unknown"
|
||||||
|
|
||||||
|
# These should pass
|
||||||
|
run_skopeo copy --dest-tls-verify=false --dcreds=$testuser:$testpassword \
|
||||||
|
docker://busybox:latest docker://localhost:5000/busybox:mine
|
||||||
|
run_skopeo inspect --tls-verify=false --creds=$testuser:$testpassword \
|
||||||
|
docker://localhost:5000/busybox:mine
|
||||||
|
expect_output --substring "localhost:5000/busybox"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "auth: credentials via podman login" {
|
||||||
|
# Logged in: skopeo should work
|
||||||
|
podman login --tls-verify=false -u $testuser -p $testpassword localhost:5000
|
||||||
|
|
||||||
|
run_skopeo copy --dest-tls-verify=false \
|
||||||
|
docker://busybox:latest docker://localhost:5000/busybox:mine
|
||||||
|
run_skopeo inspect --tls-verify=false docker://localhost:5000/busybox:mine
|
||||||
|
expect_output --substring "localhost:5000/busybox"
|
||||||
|
|
||||||
|
# Logged out: should fail
|
||||||
|
podman logout localhost:5000
|
||||||
|
|
||||||
|
run_skopeo 1 inspect --tls-verify=false docker://localhost:5000/busybox:mine
|
||||||
|
expect_output --substring "unauthorized: authentication required"
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
podman rm -f reg
|
||||||
|
|
||||||
|
if [[ -n $_cred_file ]]; then
|
||||||
|
rm -f $_cred_file
|
||||||
|
fi
|
||||||
|
|
||||||
|
standard_teardown
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
137
systemtest/050-signing.bats
Normal file
137
systemtest/050-signing.bats
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
#
|
||||||
|
# Tests with gpg signing
|
||||||
|
#
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
standard_setup
|
||||||
|
|
||||||
|
# Create dummy gpg keys
|
||||||
|
export GNUPGHOME=$TESTDIR/skopeo-gpg
|
||||||
|
mkdir --mode=0700 $GNUPGHOME
|
||||||
|
for k in alice bob;do
|
||||||
|
gpg --batch --pinentry-mode loopback --gen-key --passphrase '' <<END_GPG
|
||||||
|
Key-Type: RSA
|
||||||
|
Name-Real: Test key - $k
|
||||||
|
Name-email: $k@test.redhat.com
|
||||||
|
%commit
|
||||||
|
END_GPG
|
||||||
|
|
||||||
|
gpg --armor --export $k@test.redhat.com >$GNUPGHOME/pubkey-$k.gpg
|
||||||
|
done
|
||||||
|
|
||||||
|
# Registries. The important part here seems to be sigstore,
|
||||||
|
# because (I guess?) the registry itself has no mechanism
|
||||||
|
# for storing or validating signatures.
|
||||||
|
REGISTRIES_D=$TESTDIR/registries.d
|
||||||
|
mkdir $REGISTRIES_D $TESTDIR/sigstore
|
||||||
|
cat >$REGISTRIES_D/registries.yaml <<EOF
|
||||||
|
docker:
|
||||||
|
localhost:5000:
|
||||||
|
sigstore: file://$TESTDIR/sigstore
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Policy file. Basically, require /myns/alice and /myns/bob
|
||||||
|
# to be signed; allow /open; and reject anything else.
|
||||||
|
POLICY_JSON=$TESTDIR/policy.json
|
||||||
|
cat >$POLICY_JSON <<END_POLICY_JSON
|
||||||
|
{
|
||||||
|
"default": [
|
||||||
|
{
|
||||||
|
"type": "reject"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transports": {
|
||||||
|
"docker": {
|
||||||
|
"localhost:5000/myns/alice": [
|
||||||
|
{
|
||||||
|
"type": "signedBy",
|
||||||
|
"keyType": "GPGKeys",
|
||||||
|
"keyPath": "$GNUPGHOME/pubkey-alice.gpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"localhost:5000/myns/bob": [
|
||||||
|
{
|
||||||
|
"type": "signedBy",
|
||||||
|
"keyType": "GPGKeys",
|
||||||
|
"keyPath": "$GNUPGHOME/pubkey-bob.gpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"localhost:5000/open": [
|
||||||
|
{
|
||||||
|
"type": "insecureAcceptAnything"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_POLICY_JSON
|
||||||
|
|
||||||
|
start_registry reg
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "signing" {
|
||||||
|
# Cache local copy
|
||||||
|
run_skopeo copy docker://busybox:latest dir:$TESTDIR/busybox
|
||||||
|
|
||||||
|
# Push a bunch of images. Do so *without* --policy flag; this lets us
|
||||||
|
# sign or not, creating images that will or won't conform to policy.
|
||||||
|
while read path sig comments; do
|
||||||
|
local sign_opt=
|
||||||
|
if [[ $sig != '-' ]]; then
|
||||||
|
sign_opt="--sign-by=${sig}@test.redhat.com"
|
||||||
|
fi
|
||||||
|
run_skopeo --registries.d $REGISTRIES_D \
|
||||||
|
copy --dest-tls-verify=false \
|
||||||
|
$sign_opt \
|
||||||
|
dir:$TESTDIR/busybox \
|
||||||
|
docker://localhost:5000$path
|
||||||
|
done <<END_PUSH
|
||||||
|
/myns/alice:signed alice # Properly-signed image
|
||||||
|
/myns/alice:unsigned - # Unsigned image to path that requires signature
|
||||||
|
/myns/bob:signedbyalice alice # Bad signature: image under /bob
|
||||||
|
/myns/carol:latest - # No signature
|
||||||
|
/open/forall:latest - # No signature, but none needed
|
||||||
|
END_PUSH
|
||||||
|
# FIXME: there doesn't seem to be a way to push an image
|
||||||
|
# such as '/bob:signed', signed by bob, at the same time
|
||||||
|
# that we have :signedbyalice
|
||||||
|
|
||||||
|
# Done pushing. Now try to fetch. From here on we use the --policy option.
|
||||||
|
# The table below lists the paths to fetch, and the expected errors (or
|
||||||
|
# none, if we expect them to pass).
|
||||||
|
while read path expected_error; do
|
||||||
|
expected_rc=
|
||||||
|
if [[ -n $expected_error ]]; then
|
||||||
|
expected_rc=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf $TESTDIR/d
|
||||||
|
run_skopeo $expected_rc \
|
||||||
|
--registries.d $REGISTRIES_D \
|
||||||
|
--policy $POLICY_JSON \
|
||||||
|
copy --src-tls-verify=false \
|
||||||
|
docker://localhost:5000$path \
|
||||||
|
dir:$TESTDIR/d
|
||||||
|
if [[ -n $expected_error ]]; then
|
||||||
|
expect_output --substring "Source image rejected: $expected_error"
|
||||||
|
fi
|
||||||
|
done <<END_TESTS
|
||||||
|
/myns/alice:signed
|
||||||
|
/myns/bob:signedbyalice Invalid GPG signature
|
||||||
|
/myns/alice:unsigned Signature for identity localhost:5000/myns/alice:signed is not accepted
|
||||||
|
/myns/carol:latest Running image docker://localhost:5000/myns/carol:latest is rejected by policy.
|
||||||
|
/open/forall:latest
|
||||||
|
END_TESTS
|
||||||
|
# FIXME: why does the message for alice:unsigned say ':signed' ?
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
podman rm -f reg
|
||||||
|
|
||||||
|
standard_teardown
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
318
systemtest/helpers.bash
Normal file
318
systemtest/helpers.bash
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SKOPEO_BINARY=${SKOPEO_BINARY:-$(dirname ${BASH_SOURCE})/../skopeo}
|
||||||
|
|
||||||
|
# Default timeout for a skopeo command.
|
||||||
|
SKOPEO_TIMEOUT=${SKOPEO_TIMEOUT:-300}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# BEGIN setup/teardown
|
||||||
|
|
||||||
|
# Provide common setup and teardown functions, but do not name them such!
|
||||||
|
# That way individual tests can override with their own setup/teardown,
|
||||||
|
# while retaining the ability to include these if they so desire.
|
||||||
|
|
||||||
|
function standard_setup() {
|
||||||
|
# Argh. Although BATS provides $BATS_TMPDIR, it's just /tmp!
|
||||||
|
# That's bloody worthless. Let's make our own, in which subtests
|
||||||
|
# can write whatever they like and trust that it'll be deleted
|
||||||
|
# on cleanup.
|
||||||
|
TESTDIR=$(mktemp -d --tmpdir=${BATS_TMPDIR:-/tmp} skopeo_bats.XXXXXX)
|
||||||
|
}
|
||||||
|
|
||||||
|
function standard_teardown() {
|
||||||
|
if [[ -n $TESTDIR ]]; then
|
||||||
|
rm -rf $TESTDIR
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Individual .bats files may override or extend these
|
||||||
|
function setup() {
|
||||||
|
standard_setup
|
||||||
|
}
|
||||||
|
|
||||||
|
function teardown() {
|
||||||
|
standard_teardown
|
||||||
|
}
|
||||||
|
|
||||||
|
# END setup/teardown
|
||||||
|
###############################################################################
|
||||||
|
# BEGIN standard helpers for running skopeo and testing results
|
||||||
|
|
||||||
|
#################
|
||||||
|
# run_skopeo # Invoke skopeo, with timeout, using BATS 'run'
|
||||||
|
#################
|
||||||
|
#
|
||||||
|
# This is the preferred mechanism for invoking skopeo:
|
||||||
|
#
|
||||||
|
# * we use 'timeout' to abort (with a diagnostic) if something
|
||||||
|
# takes too long; this is preferable to a CI hang.
|
||||||
|
# * we log the command run and its output. This doesn't normally
|
||||||
|
# appear in BATS output, but it will if there's an error.
|
||||||
|
# * we check exit status. Since the normal desired code is 0,
|
||||||
|
# that's the default; but the first argument can override:
|
||||||
|
#
|
||||||
|
# run_skopeo 125 nonexistent-subcommand
|
||||||
|
# run_skopeo '?' some-other-command # let our caller check status
|
||||||
|
#
|
||||||
|
# Since we use the BATS 'run' mechanism, $output and $status will be
|
||||||
|
# defined for our caller.
|
||||||
|
#
|
||||||
|
function run_skopeo() {
|
||||||
|
# Number as first argument = expected exit code; default 0
|
||||||
|
expected_rc=0
|
||||||
|
case "$1" in
|
||||||
|
[0-9]) expected_rc=$1; shift;;
|
||||||
|
[1-9][0-9]) expected_rc=$1; shift;;
|
||||||
|
[12][0-9][0-9]) expected_rc=$1; shift;;
|
||||||
|
'?') expected_rc= ; shift;; # ignore exit code
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Remember command args, for possible use in later diagnostic messages
|
||||||
|
MOST_RECENT_SKOPEO_COMMAND="skopeo $*"
|
||||||
|
|
||||||
|
# stdout is only emitted upon error; this echo is to help a debugger
|
||||||
|
echo "\$ $SKOPEO_BINARY $*"
|
||||||
|
run timeout --foreground --kill=10 $SKOPEO_TIMEOUT ${SKOPEO_BINARY} "$@"
|
||||||
|
# without "quotes", multiple lines are glommed together into one
|
||||||
|
if [ -n "$output" ]; then
|
||||||
|
echo "$output"
|
||||||
|
fi
|
||||||
|
if [ "$status" -ne 0 ]; then
|
||||||
|
echo -n "[ rc=$status ";
|
||||||
|
if [ -n "$expected_rc" ]; then
|
||||||
|
if [ "$status" -eq "$expected_rc" ]; then
|
||||||
|
echo -n "(expected) ";
|
||||||
|
else
|
||||||
|
echo -n "(** EXPECTED $expected_rc **) ";
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$status" -eq 124 -o "$status" -eq 137 ]; then
|
||||||
|
# FIXME: 'timeout -v' requires coreutils-8.29; travis seems to have
|
||||||
|
# an older version. If/when travis updates, please add -v
|
||||||
|
# to the 'timeout' command above, and un-comment this out:
|
||||||
|
# if expr "$output" : ".*timeout: sending" >/dev/null; then
|
||||||
|
echo "*** TIMED OUT ***"
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$expected_rc" ]; then
|
||||||
|
if [ "$status" -ne "$expected_rc" ]; then
|
||||||
|
die "exit code is $status; expected $expected_rc"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#########
|
||||||
|
# die # Abort with helpful message
|
||||||
|
#########
|
||||||
|
function die() {
|
||||||
|
echo "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" >&2
|
||||||
|
echo "#| FAIL: $*" >&2
|
||||||
|
echo "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >&2
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
###################
|
||||||
|
# expect_output # Compare actual vs expected string; fail if mismatch
|
||||||
|
###################
|
||||||
|
#
|
||||||
|
# Compares $output against the given string argument. Optional second
|
||||||
|
# argument is descriptive text to show as the error message (default:
|
||||||
|
# the command most recently run by 'run_skopeo'). This text can be
|
||||||
|
# useful to isolate a failure when there are multiple identical
|
||||||
|
# run_skopeo invocations, and the difference is solely in the
|
||||||
|
# config or setup; see, e.g., run.bats:run-cmd().
|
||||||
|
#
|
||||||
|
# By default we run an exact string comparison; use --substring to
|
||||||
|
# look for the given string anywhere in $output.
|
||||||
|
#
|
||||||
|
# By default we look in "$output", which is set in run_skopeo().
|
||||||
|
# To override, use --from="some-other-string" (e.g. "${lines[0]}")
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# expect_output "this is exactly what we expect"
|
||||||
|
# expect_output "foo=bar" "description of this particular test"
|
||||||
|
# expect_output --from="${lines[0]}" "expected first line"
|
||||||
|
#
|
||||||
|
function expect_output() {
|
||||||
|
# By default we examine $output, the result of run_skopeo
|
||||||
|
local actual="$output"
|
||||||
|
local check_substring=
|
||||||
|
|
||||||
|
# option processing: recognize --from="...", --substring
|
||||||
|
local opt
|
||||||
|
for opt; do
|
||||||
|
local value=$(expr "$opt" : '[^=]*=\(.*\)')
|
||||||
|
case "$opt" in
|
||||||
|
--from=*) actual="$value"; shift;;
|
||||||
|
--substring) check_substring=1; shift;;
|
||||||
|
--) shift; break;;
|
||||||
|
-*) die "Invalid option '$opt'" ;;
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local expect="$1"
|
||||||
|
local testname="${2:-${MOST_RECENT_SKOPEO_COMMAND:-[no test name given]}}"
|
||||||
|
|
||||||
|
if [ -z "$expect" ]; then
|
||||||
|
if [ -z "$actual" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
expect='[no output]'
|
||||||
|
elif [ "$actual" = "$expect" ]; then
|
||||||
|
return
|
||||||
|
elif [ -n "$check_substring" ]; then
|
||||||
|
if [[ "$actual" =~ $expect ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is a multi-line message, which may in turn contain multi-line
|
||||||
|
# output, so let's format it ourself, readably
|
||||||
|
local -a actual_split
|
||||||
|
readarray -t actual_split <<<"$actual"
|
||||||
|
printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2
|
||||||
|
printf "#| FAIL: $testname\n" >&2
|
||||||
|
printf "#| expected: '%s'\n" "$expect" >&2
|
||||||
|
printf "#| actual: '%s'\n" "${actual_split[0]}" >&2
|
||||||
|
local line
|
||||||
|
for line in "${actual_split[@]:1}"; do
|
||||||
|
printf "#| > '%s'\n" "$line" >&2
|
||||||
|
done
|
||||||
|
printf "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" >&2
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# expect_line_count # Check the expected number of output lines
|
||||||
|
#######################
|
||||||
|
#
|
||||||
|
# ...from the most recent run_skopeo command
|
||||||
|
#
|
||||||
|
function expect_line_count() {
|
||||||
|
local expect="$1"
|
||||||
|
local testname="${2:-${MOST_RECENT_SKOPEO_COMMAND:-[no test name given]}}"
|
||||||
|
|
||||||
|
local actual="${#lines[@]}"
|
||||||
|
if [ "$actual" -eq "$expect" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2
|
||||||
|
printf "#| FAIL: $testname\n" >&2
|
||||||
|
printf "#| Expected %d lines of output, got %d\n" $expect $actual >&2
|
||||||
|
printf "#| Output was:\n" >&2
|
||||||
|
local line
|
||||||
|
for line in "${lines[@]}"; do
|
||||||
|
printf "#| >%s\n" "$line" >&2
|
||||||
|
done
|
||||||
|
printf "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" >&2
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
# END standard helpers for running skopeo and testing results
|
||||||
|
###############################################################################
|
||||||
|
# BEGIN helpers for starting/stopping registries
|
||||||
|
|
||||||
|
start_registry() {
|
||||||
|
local port=5000
|
||||||
|
local testuser=
|
||||||
|
local testpassword=
|
||||||
|
local create_cert=
|
||||||
|
|
||||||
|
# option processing: recognize --auth
|
||||||
|
local opt
|
||||||
|
for opt; do
|
||||||
|
local value=$(expr "$opt" : '[^=]*=\(.*\)')
|
||||||
|
case "$opt" in
|
||||||
|
--port=*) port="$value"; shift;;
|
||||||
|
--testuser=*) testuser="$value"; shift;;
|
||||||
|
--testpassword=*) testpassword="$value"; shift;;
|
||||||
|
--with-cert) create_cert=1; shift;;
|
||||||
|
-*) die "Invalid option '$opt'" ;;
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local name=${1?start_registry() invoked without a NAME}
|
||||||
|
|
||||||
|
# Temp directory must be defined and must exist
|
||||||
|
[[ -n $TESTDIR && -d $TESTDIR ]]
|
||||||
|
|
||||||
|
AUTHDIR=$TESTDIR/auth
|
||||||
|
mkdir -p $AUTHDIR
|
||||||
|
|
||||||
|
local -a reg_args=(-v $AUTHDIR:/auth:Z -p $port:5000)
|
||||||
|
|
||||||
|
# Called with --testuser? Create an htpasswd file
|
||||||
|
if [[ -n $testuser ]]; then
|
||||||
|
if [[ -z $testpassword ]]; then
|
||||||
|
die "start_registry() invoked with testuser but no testpassword"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! egrep -q "^$testuser:" $AUTHDIR/htpasswd; then
|
||||||
|
podman run --rm --entrypoint htpasswd registry:2 \
|
||||||
|
-Bbn $testuser $testpassword >> $AUTHDIR/htpasswd
|
||||||
|
fi
|
||||||
|
|
||||||
|
reg_args+=(
|
||||||
|
-e REGISTRY_AUTH=htpasswd
|
||||||
|
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
|
||||||
|
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Called with --with-cert? Create certificates.
|
||||||
|
if [[ -n $create_cert ]]; then
|
||||||
|
CERT=$AUTHDIR/domain.cert
|
||||||
|
if [ ! -e $CERT ]; then
|
||||||
|
openssl req -newkey rsa:4096 -nodes -sha256 \
|
||||||
|
-keyout $AUTHDIR/domain.key -x509 -days 2 \
|
||||||
|
-out $CERT \
|
||||||
|
-subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
|
||||||
|
fi
|
||||||
|
|
||||||
|
reg_args+=(
|
||||||
|
-e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.cert
|
||||||
|
-e REGISTRY_HTTP_TLS_KEY=/auth/domain.key
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
podman run -d --name $name "${reg_args[@]}" registry:2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
stop_registries() {
|
||||||
|
if [[ -z $SKOPEO_DEBUG_REGISTRIES ]]; then
|
||||||
|
podman rm -a -f
|
||||||
|
|
||||||
|
if [[ -n $AUTHDIR ]]; then
|
||||||
|
rm -rf $AUTHDIR
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# END helpers for starting/stopping registries
|
||||||
|
###############################################################################
|
||||||
|
# BEGIN miscellaneous tools
|
||||||
|
|
||||||
|
###################
|
||||||
|
# random_string # Returns a pseudorandom human-readable string
|
||||||
|
###################
|
||||||
|
#
|
||||||
|
# Numeric argument, if present, is desired length of string
|
||||||
|
#
|
||||||
|
function random_string() {
|
||||||
|
local length=${1:-10}
|
||||||
|
|
||||||
|
head /dev/urandom | tr -dc a-zA-Z0-9 | head -c$length
|
||||||
|
}
|
||||||
|
|
||||||
|
# END miscellaneous tools
|
||||||
|
###############################################################################
|
19
systemtest/run-tests
Executable file
19
systemtest/run-tests
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# run-tests - simple wrapper allowing shortcuts on invocation
|
||||||
|
#
|
||||||
|
|
||||||
|
# FIXME
|
||||||
|
export SKOPEO_BINARY=${SKOPEO_BINARY:-/usr/bin/skopeo}
|
||||||
|
|
||||||
|
TEST_DIR=$(dirname $0)
|
||||||
|
TESTS=$TEST_DIR
|
||||||
|
|
||||||
|
for i; do
|
||||||
|
case "$i" in
|
||||||
|
*.bats) TESTS=$i ;;
|
||||||
|
*) TESTS=$(echo $TEST_DIR/*$i*.bats) ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
bats $TESTS
|
Loading…
Reference in New Issue
Block a user