Merge pull request #22726 from edsantiago/pull-from-local-registry
CI: Use local cache registry
This commit is contained in:
commit
58c8803a1e
|
@ -33,7 +33,7 @@ env:
|
|||
DEBIAN_NAME: "debian-13"
|
||||
|
||||
# Image identifiers
|
||||
IMAGE_SUFFIX: "c20240702t180702z-f40f39d13"
|
||||
IMAGE_SUFFIX: "c20240708t152000z-f40f39d13"
|
||||
|
||||
# EC2 images
|
||||
FEDORA_AMI: "fedora-aws-${IMAGE_SUFFIX}"
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# get-local-registry-script - fetches local-registry script from automation_images repo
|
||||
#
|
||||
ME=$(basename $0)
|
||||
|
||||
###############################################################################
|
||||
# BEGIN global settings
|
||||
|
||||
SCRIPTNAME=cache_images/local-cache-registry
|
||||
|
||||
REPO=containers/automation_images
|
||||
|
||||
GITHUB_GRAPHQL=https://api.github.com/graphql
|
||||
|
||||
# END global settings
|
||||
###############################################################################
|
||||
|
||||
usage="Usage: $ME [--help] [-v|--verbose] [IMG_SFX]
|
||||
|
||||
--help display usage message
|
||||
-v, --verbose verbose output
|
||||
|
||||
$ME fetches the $SCRIPTNAME tool
|
||||
from the github $REPO repo.
|
||||
If successful, the script will be left in cwd.
|
||||
|
||||
It is up to you to invoke it:
|
||||
|
||||
\$ sudo ./$(basename $SCRIPTNAME) initialize
|
||||
|
||||
This will set up a local registry and prepopulate it with
|
||||
images used in tests. Initialization may take tens of minutes
|
||||
on a slow connection.
|
||||
|
||||
To use this registry in e2e or apiv2 tests:
|
||||
|
||||
export CI_USE_REGISTRY_CACHE=1
|
||||
|
||||
To use in system tests, you need to overwrite /etc/containers/registries.conf
|
||||
because system tests, by definition, use system settings. This is left as
|
||||
an exercise for the reader.
|
||||
|
||||
Reasons for doing this:
|
||||
1) Consistency with CI environment
|
||||
2) Speedier (and less flaky) tests
|
||||
"
|
||||
|
||||
verbose=
|
||||
for i; do
|
||||
value=`expr "$i" : '[^=]*=\(.*\)'`
|
||||
case "$i" in
|
||||
-h*|--help) echo "$usage"; exit 0;;
|
||||
-v|--verbose) verbose=$i; shift;;
|
||||
-*) echo "$ME: unrecognized option $i" >&2
|
||||
echo "$usage" >&2
|
||||
exit 1;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
###############################################################################
|
||||
# BEGIN helper functions
|
||||
|
||||
function die() {
|
||||
echo "$ME: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
function get_imgsfx() {
|
||||
test -e .cirrus.yml || die ".cirrus.yml does not exist; please run me from top of repo"
|
||||
|
||||
imgsfx=$(sed -ne 's/^ *IMAGE_SUFFIX:.*"c\(202.*\)"/\1/p' <.cirrus.yml)
|
||||
if [[ -z "$imgsfx" ]]; then
|
||||
die "Did not find 'IMAGE_SUFFIX:.*c202.*' in .cirrus.yml"
|
||||
fi
|
||||
|
||||
expr "$imgsfx" : "^20[0-9]\{6\}t[0-9]\{6\}z-" &> /dev/null || die "IMAGE_SUFFIX '$imgsfx' (from .cirrus.yml) does not match expected YYYYMMDDtHHMMSS-* form"
|
||||
|
||||
echo $imgsfx
|
||||
}
|
||||
|
||||
function get_script() {
|
||||
local tag=$1
|
||||
|
||||
local tmpfile=$(mktemp --tmpdir --suffix=.sh $ME.fetched-script.XXXXXXX)
|
||||
|
||||
local url="https://raw.githubusercontent.com/${REPO}/$tag/$SCRIPTNAME"
|
||||
test -n "$verbose" && echo "[ $url ]" >&2
|
||||
|
||||
curl -s -f -o $tmpfile $url
|
||||
if [[ $? -eq 0 ]]; then
|
||||
chmod 755 $tmpfile
|
||||
mv -f $tmpfile $SCRIPTNAME
|
||||
echo $SCRIPTNAME
|
||||
return
|
||||
fi
|
||||
rm -f $tmpfile
|
||||
}
|
||||
|
||||
# END helper functions
|
||||
###############################################################################
|
||||
# BEGIN code
|
||||
|
||||
if [[ -n "$1" ]]; then
|
||||
imgsfx=$1
|
||||
shift
|
||||
if [[ -n "$*" ]]; then
|
||||
die "Too many arguments; run $ME --help for help"
|
||||
fi
|
||||
else
|
||||
imgsfx=$(get_imgsfx)
|
||||
fi
|
||||
test -n "$verbose" && echo "[ imgsfx=$imgsfx ]" >&2
|
||||
|
||||
# Easy case: this is a tagged automation_images build
|
||||
fetched_script=$(get_script $imgsfx)
|
||||
if [[ -n "$fetched_script" ]]; then
|
||||
echo $fetched_script
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Nope, not a tagged build. Look for imgsfx in PR
|
||||
query="
|
||||
{
|
||||
\"query\": \"{
|
||||
search(query: \\\"repo:$REPO is:pr c$imgsfx\\\", type:ISSUE, first:10) {
|
||||
edges {
|
||||
node { ... on PullRequest {
|
||||
number
|
||||
title
|
||||
commits(last:30) { nodes { commit { committedDate, oid } } }
|
||||
comments(last:30) { nodes { createdAt author { login } body } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}\"
|
||||
}
|
||||
"
|
||||
|
||||
query_clean=$(tr -d \\012 <<<"$query")
|
||||
|
||||
jsontmp=$(mktemp --tmpdir --suffix=.json $ME.graphql.XXXXXXX)
|
||||
|
||||
curl -s -S -H "Authorization: bearer $GITHUB_TOKEN" -X POST --data "$query_clean" $GITHUB_GRAPHQL > $jsontmp
|
||||
|
||||
# There should be one and exactly one comment from github-actions
|
||||
# that mentions the given imgsfx. Find its timestamp
|
||||
img_timestamp=$(jq -C -r '.data.search.edges.[].node.comments.nodes.[] | select(.author.login="github-actions") | select(.body | contains("c'${imgsfx}'")).createdAt' < $jsontmp)
|
||||
if [[ -z "$img_timestamp" ]]; then
|
||||
die "Did not find a github-actions comment mentioning '$imgsfx'"
|
||||
fi
|
||||
|
||||
# Some time prior to that comment, there was a commit pushed to github
|
||||
# that resulted in that build. Find that commit's SHA (OID).
|
||||
push_sha=$(jq -C -r '.data.search.edges.[].node.commits.nodes.[].commit | select(.committedDate < "'${img_timestamp}'").oid' < $jsontmp)
|
||||
|
||||
# Got all the info we need. Clean up tmpfile
|
||||
rm -f $jsontmp
|
||||
|
||||
# This must succeed.
|
||||
get_script $push_sha
|
|
@ -72,6 +72,9 @@ CIRRUS_CI="${CIRRUS_CI:-false}"
|
|||
CONTINUOUS_INTEGRATION="${CONTINUOUS_INTEGRATION:-false}"
|
||||
CIRRUS_REPO_NAME=${CIRRUS_REPO_NAME:-podman}
|
||||
|
||||
# All CI jobs use a local registry
|
||||
export CI_USE_REGISTRY_CACHE=true
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
if [[ -n "$CIRRUS_PR" ]] && [[ -z "$PR_BASE_SHA" ]]; then
|
||||
# shellcheck disable=SC2154
|
||||
|
@ -193,7 +196,8 @@ setup_rootless() {
|
|||
|
||||
install_test_configs() {
|
||||
msg "Installing ./test/registries.conf system-wide."
|
||||
install -v -D -m 644 ./test/registries.conf /etc/containers/
|
||||
# All CI VMs run with a local registry
|
||||
install -v -D -m 644 ./test/registries-cached.conf /etc/containers/registries.conf
|
||||
}
|
||||
|
||||
# Remove all files provided by the distro version of podman.
|
||||
|
|
|
@ -124,6 +124,7 @@ exec_container() {
|
|||
|
||||
# VM Images and Container images are built using (nearly) identical operations.
|
||||
set -x
|
||||
env CONTAINERS_REGISTRIES_CONF=/dev/null bin/podman pull -q $CTR_FQIN
|
||||
# shellcheck disable=SC2154
|
||||
exec bin/podman run --rm --privileged --net=host --cgroupns=host \
|
||||
-v `mktemp -d -p /var/tmp`:/var/tmp:Z \
|
||||
|
|
|
@ -335,6 +335,18 @@ case "$PODBIN_NAME" in
|
|||
*) die_unknown PODBIN_NAME
|
||||
esac
|
||||
|
||||
# As of July 2024, CI VMs come built-in with a registry.
|
||||
LCR=/var/cache/local-registry/local-cache-registry
|
||||
if [[ -x $LCR ]]; then
|
||||
# Images in cache registry are prepopulated at the time
|
||||
# VMs are built. If any PR adds a dependency on new images,
|
||||
# those must be fetched now, at VM start time. This should
|
||||
# be rare, and must be fixed in next automation_images build.
|
||||
while read new_image; do
|
||||
$LCR cache $new_image
|
||||
done < <(grep '^[^#]' test/NEW-IMAGES || true)
|
||||
fi
|
||||
|
||||
# Required to be defined by caller: The primary type of testing that will be performed
|
||||
# shellcheck disable=SC2154
|
||||
showrun echo "about to set up for TEST_FLAVOR [=$TEST_FLAVOR]"
|
||||
|
@ -426,6 +438,10 @@ case "$TEST_FLAVOR" in
|
|||
fi
|
||||
remove_packaged_podman_files
|
||||
showrun make install PREFIX=/usr ETCDIR=/etc
|
||||
# machine-os image changes too frequently, can't be precached
|
||||
# FIXME: I don't think we can use version.go, because of chicken-egg
|
||||
# problem when that gets bumped. Ideas welcome.
|
||||
$LCR cache podman/machine-os:5.2
|
||||
install_test_configs
|
||||
;;
|
||||
swagger)
|
||||
|
|
|
@ -7,7 +7,7 @@ ME=$(basename $0)
|
|||
###############################################################################
|
||||
# BEGIN defaults
|
||||
|
||||
PODMAN_REGISTRY_IMAGE=quay.io/libpod/registry:2.8
|
||||
PODMAN_REGISTRY_IMAGE=quay.io/libpod/registry:2.8.2
|
||||
|
||||
PODMAN_REGISTRY_USER=
|
||||
PODMAN_REGISTRY_PASS=
|
||||
|
|
|
@ -177,7 +177,7 @@ var _ = Describe("Podman images", func() {
|
|||
|
||||
// Adding one more image. There Should be no errors in the response.
|
||||
// And the count should be three now.
|
||||
bt.Pull("testimage:20200929")
|
||||
bt.Pull("testimage:20221018")
|
||||
imageSummary, err = images.List(bt.conn, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(imageSummary)).To(BeNumerically(">=", 2))
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# As of July 2024, all CI VMs include a local registry prepopulated
|
||||
# with all container images used in tests:
|
||||
#
|
||||
# https://github.com/containers/automation_images/pull/357
|
||||
# https://github.com/containers/podman/pull/22726
|
||||
#
|
||||
# From time to time -- infrequently, we hope! -- existing images are
|
||||
# updated, or tests are added that require new images. Those must be
|
||||
# prefetched on each CI job, at least until new VMs are built. This
|
||||
# file contains those images.
|
||||
#
|
||||
# Format is one FQIN per line. Enumerate them below:
|
||||
#
|
|
@ -7,7 +7,9 @@
|
|||
podman pull -q $IMAGE
|
||||
|
||||
t GET libpod/images/json 200 \
|
||||
.[0].Id~[0-9a-f]\\{64\\}
|
||||
length=1 \
|
||||
.[0].Id~[0-9a-f]\\{64\\} \
|
||||
.[0].Names[0]="$IMAGE"
|
||||
iid=$(jq -r '.[0].Id' <<<"$output")
|
||||
|
||||
# Create an empty manifest and make sure it is not listed
|
||||
|
@ -18,7 +20,7 @@ t GET images/json 200 length=1
|
|||
t GET libpod/images/json 200 length=2
|
||||
|
||||
t GET libpod/images/$iid/exists 204
|
||||
t GET libpod/images/$PODMAN_TEST_IMAGE_NAME/exists 204
|
||||
t GET libpod/images/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG/exists 204
|
||||
t GET libpod/images/${iid}abcdef/exists 404 \
|
||||
.cause="failed to find image ${iid}abcdef"
|
||||
|
||||
|
@ -51,11 +53,13 @@ t GET images/$iid/json 200 \
|
|||
t POST "images/create?fromImage=alpine" 200 .error~null .status~".*Download complete.*"
|
||||
t POST "libpod/images/pull?reference=alpine&compatMode=true" 200 .error~null .status~".*Download complete.*"
|
||||
|
||||
t POST "images/create?fromImage=alpine&tag=latest" 200
|
||||
t POST "images/create?fromImage=alpine&tag=latest" 200 \
|
||||
.status~"Already exists"
|
||||
|
||||
# 10977 - handle platform parameter correctly
|
||||
t POST "images/create?fromImage=quay.io/libpod/testimage:20240123&platform=linux/arm64" 200
|
||||
t GET "images/testimage:20240123/json" 200 \
|
||||
# THIS IMAGE MUST NOT BE THE SAME AS $IMAGE
|
||||
t POST "images/create?fromImage=quay.io/libpod/testimage:20221018&platform=linux/arm64" 200
|
||||
t GET "images/testimage:20221018/json" 200 \
|
||||
.Architecture=arm64
|
||||
|
||||
# Make sure that new images are pulled
|
||||
|
@ -78,34 +82,42 @@ t POST /images/create?fromImage=busybox:invalidtag123 404
|
|||
# Display the image history
|
||||
t GET libpod/images/nonesuch/history 404
|
||||
|
||||
for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME; do
|
||||
for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG; do
|
||||
t GET libpod/images/$i/history 200 \
|
||||
.[0].Id=$iid \
|
||||
.[0].Created~[0-9]\\{10\\} \
|
||||
.[0].Tags[0]="$IMAGE" \
|
||||
.[0].Size=0 \
|
||||
.[0].Comment=
|
||||
.[0].Size=1024 \
|
||||
.[0].Comment="FROM localhost/interim-image:latest"
|
||||
done
|
||||
|
||||
for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME; do
|
||||
for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG; do
|
||||
t GET images/$i/history 200 \
|
||||
.[0].Id="sha256:"$iid \
|
||||
.[0].Created~[0-9]\\{10\\} \
|
||||
.[0].Tags[0]="$IMAGE" \
|
||||
.[0].Size=0 \
|
||||
.[0].Comment=
|
||||
.[0].Size=1024 \
|
||||
.[0].Comment="FROM localhost/interim-image:latest"
|
||||
done
|
||||
|
||||
# compat api pull image unauthorized message error
|
||||
t POST "/images/create?fromImage=quay.io/idonotexist/idonotexist:dummy" 401 \
|
||||
.message="unauthorized: access to the requested resource is not authorized"
|
||||
# This depends on whether we're using local cache registry or real quay
|
||||
expect_code=401
|
||||
expect_msg="unauthorized: access to the requested resource is not authorized"
|
||||
if [[ -n "$CI_USE_REGISTRY_CACHE" ]]; then
|
||||
# local registry has no auth, so it can return 404
|
||||
expect_code=404
|
||||
expect_msg="manifest unknown: manifest unknown"
|
||||
fi
|
||||
t POST "/images/create?fromImage=quay.io/idonotexist/idonotexist:dummy" $expect_code \
|
||||
.message="$expect_msg"
|
||||
|
||||
# Export an image on the local
|
||||
t GET libpod/images/nonesuch/get 404
|
||||
t GET libpod/images/$iid/get?format=foo 500
|
||||
t GET libpod/images/$PODMAN_TEST_IMAGE_NAME/get?compress=bar 400
|
||||
|
||||
for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME; do
|
||||
for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG; do
|
||||
t GET "libpod/images/$i/get" 200 '[POSIX tar archive]'
|
||||
t GET "libpod/images/$i/get?compress=true" 200 '[POSIX tar archive]'
|
||||
t GET "libpod/images/$i/get?compress=false" 200 '[POSIX tar archive]'
|
||||
|
@ -296,10 +308,12 @@ t DELETE libpod/images/test:test 200
|
|||
# This sleep seems to avoid the race.
|
||||
# If it fails and begins to flake, investigate a retry loop.
|
||||
sleep 1
|
||||
# FIXME 2024-05-30 #22726: when running with a local cache registry, DELETE
|
||||
# sometimes produces 5-6 events instead of the desired only-one.
|
||||
t GET "libpod/events?stream=false&since=$START" 200 \
|
||||
'select(.status | contains("remove")).Action=remove'
|
||||
'select(.status | contains("remove")).Actor.Attributes.name~.*localhost/test:test'
|
||||
t GET "events?stream=false&since=$START" 200 \
|
||||
'select(.status | contains("delete")).Action=delete'
|
||||
'select(.status | contains("delete")).Actor.Attributes.name~.*localhost/test:test'
|
||||
|
||||
# Test image removal with `noprune={true,false}`
|
||||
podman create --name c_test1 $IMAGE true
|
||||
|
|
|
@ -4,12 +4,10 @@
|
|||
#
|
||||
|
||||
# WORKDIR=/data
|
||||
ENV_WORKDIR_IMG=quay.io/libpod/testimage:20240123
|
||||
MultiTagName=localhost/test/testformultitag:tag
|
||||
|
||||
podman pull $IMAGE &>/dev/null
|
||||
podman tag $IMAGE $MultiTagName
|
||||
podman pull $ENV_WORKDIR_IMG &>/dev/null
|
||||
# Unimplemented
|
||||
#t POST libpod/containers/create '' 201 'sdf'
|
||||
|
||||
|
@ -281,7 +279,7 @@ t DELETE libpod/containers/bogus 404
|
|||
|
||||
|
||||
# test apiv2 create container with correct entrypoint and cmd
|
||||
# --data '{"Image":"quay.io/libpod/alpine_labels:latest","Entrypoint":["echo"],"Cmd":["param1","param2"]}'
|
||||
# --data '{"Image":"quay.io/libpod/some:thing","Entrypoint":["echo"],"Cmd":["param1","param2"]}'
|
||||
t POST containers/create \
|
||||
Image=$IMAGE \
|
||||
Entrypoint='["echo"]' \
|
||||
|
@ -352,7 +350,7 @@ t DELETE containers/$cid_top 204
|
|||
|
||||
# test the WORKDIR and StopSignal
|
||||
t POST containers/create \
|
||||
Image=$ENV_WORKDIR_IMG \
|
||||
Image=$IMAGE \
|
||||
WorkingDir=/dataDir \
|
||||
StopSignal=\"9\" \
|
||||
201 \
|
||||
|
@ -406,7 +404,7 @@ t GET containers/json 200 \
|
|||
podman stop bar
|
||||
|
||||
#compat api list containers sanity checks
|
||||
podman run -d --rm --name labelcontainer_with $ENV_WORKDIR_IMG top
|
||||
podman run -d --rm --name labelcontainer_with --label slartibart=fast $IMAGE top
|
||||
podman run -d --rm --name labelcontainer_without $IMAGE top
|
||||
|
||||
t GET containers/json?filters='garb1age}' 500 \
|
||||
|
@ -436,10 +434,10 @@ t POST containers/prune?filters='{"label":["tes' 500 \
|
|||
t POST libpod/containers/prune?filters='{"label":["tes' 500 \
|
||||
.cause="unexpected end of JSON input"
|
||||
|
||||
t GET libpod/containers/json?filters='{"label":["created_by"]}' 200 \
|
||||
t GET libpod/containers/json?filters='{"label":["slartibart"]}' 200 \
|
||||
length=1 \
|
||||
.[0].Names[0]="labelcontainer_with"
|
||||
t GET libpod/containers/json?filters='{"label!":["created_by"]}' 200 \
|
||||
t GET libpod/containers/json?filters='{"label!":["slartibart"]}' 200 \
|
||||
length=1 \
|
||||
.[0].Names[0]="labelcontainer_without"
|
||||
t GET libpod/containers/json?filters='{"label!":["testlabel"]}' 200 length=2
|
||||
|
|
|
@ -11,13 +11,13 @@ ME=$(basename $0)
|
|||
|
||||
PODMAN_TEST_IMAGE_REGISTRY=${PODMAN_TEST_IMAGE_REGISTRY:-"quay.io"}
|
||||
PODMAN_TEST_IMAGE_USER=${PODMAN_TEST_IMAGE_USER:-"libpod"}
|
||||
PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"alpine_labels"}
|
||||
PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"latest"}
|
||||
PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"testimage"}
|
||||
PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"20240123"}
|
||||
PODMAN_TEST_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG"
|
||||
|
||||
IMAGE=$PODMAN_TEST_IMAGE_FQN
|
||||
|
||||
REGISTRY_IMAGE="${PODMAN_TEST_IMAGE_REGISTRY}/${PODMAN_TEST_IMAGE_USER}/registry:2.7"
|
||||
REGISTRY_IMAGE="${PODMAN_TEST_IMAGE_REGISTRY}/${PODMAN_TEST_IMAGE_USER}/registry:2.8.2"
|
||||
|
||||
# END stuff you can but probably shouldn't customize
|
||||
###############################################################################
|
||||
|
@ -54,6 +54,14 @@ fi
|
|||
# Path to podman binary
|
||||
PODMAN_BIN=${PODMAN:-${CONTAINERS_HELPER_BINARY_DIR}/podman}
|
||||
|
||||
# Path to registries.conf file. CI uses a locally-running cache registry,
|
||||
# but we can't expect developers to have that in their local environment.
|
||||
registries_conf_file=registries.conf
|
||||
if [[ -n "$CI_USE_REGISTRY_CACHE" ]]; then
|
||||
registries_conf_file=registries-cached.conf
|
||||
fi
|
||||
registries_conf_path=$TESTS_DIR/../$registries_conf_file
|
||||
|
||||
# Cleanup handlers
|
||||
clean_up_server() {
|
||||
if [ -n "$service_pid" ]; then
|
||||
|
@ -474,7 +482,7 @@ function start_service() {
|
|||
$PODMAN_BIN unshare true
|
||||
fi
|
||||
|
||||
CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf \
|
||||
CONTAINERS_REGISTRIES_CONF=$registries_conf_path \
|
||||
$PODMAN_BIN \
|
||||
--root $WORKDIR/server_root --syslog=true \
|
||||
system service \
|
||||
|
@ -526,7 +534,7 @@ function start_registry() {
|
|||
mkdir -p $AUTHDIR
|
||||
|
||||
mkdir -p ${REGDIR}/{root,runroot}
|
||||
local PODMAN_REGISTRY_ARGS="--root ${REGDIR}/root --runroot ${REGDIR}/runroot"
|
||||
local PODMAN_REGISTRY_ARGS="--root ${REGDIR}/root --runroot ${REGDIR}/runroot --tmpdir ${REGDIR}/tmp"
|
||||
|
||||
# Give it three tries, to compensate for network flakes
|
||||
podman ${PODMAN_REGISTRY_ARGS} pull $REGISTRY_IMAGE ||
|
||||
|
@ -644,7 +652,7 @@ function wait_for_port() {
|
|||
############
|
||||
function podman() {
|
||||
echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log
|
||||
# env CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf \
|
||||
env CONTAINERS_REGISTRIES_CONF=$registries_conf_path \
|
||||
$PODMAN_BIN --root $WORKDIR/server_root "$@" >>$WORKDIR/output.log 2>&1
|
||||
}
|
||||
|
||||
|
|
|
@ -1493,3 +1493,7 @@ func CopySymLink(source, dest string) error {
|
|||
}
|
||||
return os.Symlink(link, dest)
|
||||
}
|
||||
|
||||
func UsingCacheRegistry() bool {
|
||||
return os.Getenv("CI_USE_REGISTRY_CACHE") != ""
|
||||
}
|
||||
|
|
|
@ -15,15 +15,6 @@ var (
|
|||
HEALTHCHECK_IMAGE = "quay.io/libpod/alpine_healthcheck:latest" //nolint:revive,stylecheck
|
||||
volumeTest = "quay.io/libpod/volume-plugin-test-img:20220623"
|
||||
|
||||
// This image has seccomp profiles that blocks all syscalls.
|
||||
// The intention behind blocking all syscalls is to prevent
|
||||
// regressions in the future. The required syscalls can vary
|
||||
// depending on which runtime we're using.
|
||||
alpineSeccomp = "quay.io/libpod/alpine-with-seccomp:label"
|
||||
// This image has a bogus/invalid seccomp profile which should
|
||||
// yield a json error when being read.
|
||||
alpineBogusSeccomp = "quay.io/libpod/alpine-with-bogus-seccomp:label"
|
||||
|
||||
// ImageCacheDir is initialized at runtime.
|
||||
// e.g., filepath.Join(os.TempDir(), "imagecachedir")
|
||||
// This directory should be used by per-user.
|
||||
|
|
|
@ -117,13 +117,11 @@ var _ = Describe("Podman Info", func() {
|
|||
Expect(session.OutputToString()).To(Equal("false"))
|
||||
}
|
||||
|
||||
session = podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Exists}}"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
if IsRemote() {
|
||||
Expect(session.OutputToString()).To(ContainSubstring("true"))
|
||||
} else {
|
||||
Expect(session.OutputToString()).To(ContainSubstring("false"))
|
||||
session = podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Exists}}"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.OutputToString()).To(Equal("true"))
|
||||
}
|
||||
|
||||
})
|
||||
|
|
|
@ -49,8 +49,12 @@ func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os
|
|||
}
|
||||
|
||||
func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() {
|
||||
defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf")
|
||||
os.Setenv("CONTAINERS_REGISTRIES_CONF", defaultFile)
|
||||
defaultFile := "registries.conf"
|
||||
if UsingCacheRegistry() {
|
||||
defaultFile = "registries-cached.conf"
|
||||
}
|
||||
defaultPath := filepath.Join(INTEGRATION_ROOT, "test", defaultFile)
|
||||
os.Setenv("CONTAINERS_REGISTRIES_CONF", defaultPath)
|
||||
}
|
||||
|
||||
func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) {
|
||||
|
|
|
@ -37,8 +37,12 @@ func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os
|
|||
}
|
||||
|
||||
func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() {
|
||||
defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf")
|
||||
err := os.Setenv("CONTAINERS_REGISTRIES_CONF", defaultFile)
|
||||
defaultFile := "registries.conf"
|
||||
if UsingCacheRegistry() {
|
||||
defaultFile = "registries-cached.conf"
|
||||
}
|
||||
defaultPath := filepath.Join(INTEGRATION_ROOT, "test", defaultFile)
|
||||
err := os.Setenv("CONTAINERS_REGISTRIES_CONF", defaultPath)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ var _ = Describe("Podman load", func() {
|
|||
Skip("skip on ppc64le")
|
||||
}
|
||||
outfile := filepath.Join(podmanTest.TempDir, "alpine.tar")
|
||||
alpVersion := "quay.io/libpod/alpine:3.2"
|
||||
alpVersion := "quay.io/libpod/alpine:3.10.2"
|
||||
|
||||
pull := podmanTest.Podman([]string{"pull", "-q", alpVersion})
|
||||
pull.WaitWithDefaultTimeout()
|
||||
|
@ -169,9 +169,12 @@ var _ = Describe("Podman load", func() {
|
|||
inspect := podmanTest.Podman([]string{"inspect", ALPINE})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(result).Should(ExitCleanly())
|
||||
Expect(result.OutputToString()).To(ContainSubstring(alpVersion))
|
||||
|
||||
inspect = podmanTest.Podman([]string{"inspect", alpVersion})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(result).Should(ExitCleanly())
|
||||
Expect(result.OutputToString()).To(ContainSubstring(alpVersion))
|
||||
})
|
||||
|
||||
It("podman load localhost registry from scratch", func() {
|
||||
|
|
|
@ -21,26 +21,21 @@ var _ = Describe("Podman pull", func() {
|
|||
|
||||
session = podmanTest.Podman([]string{"pull", "busybox:latest", "docker.io/library/ibetthisdoesnotexistfr:random", "alpine"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitWithError(125, "initializing source docker://ibetthisdoesnotexistfr:random: reading manifest random in quay.io/libpod/ibetthisdoesnotexistfr:"))
|
||||
|
||||
// As of 2024-06 all Cirrus tests run using a local registry where
|
||||
// we get 404. When running in dev environment, though, we still
|
||||
// test against real registry, which returns 401
|
||||
expect := "quay.io/libpod/ibetthisdoesnotexistfr: unauthorized: access to the requested resource is not authorized"
|
||||
if UsingCacheRegistry() {
|
||||
expect = "127.0.0.1:60333/libpod/ibetthisdoesnotexistfr: manifest unknown"
|
||||
}
|
||||
Expect(session).Should(ExitWithError(125, "initializing source docker://ibetthisdoesnotexistfr:random: reading manifest random in "+expect))
|
||||
|
||||
session = podmanTest.Podman([]string{"rmi", "busybox:musl", "alpine", "quay.io/libpod/cirros", "testdigest_v2s2@sha256:755f4d90b3716e2bf57060d249e2cd61c9ac089b1233465c5c2cb2d7ee550fdb"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
})
|
||||
|
||||
It("podman pull bogus image", func() {
|
||||
// This is a NOP in CI; but in a developer environment, if user
|
||||
// has a valid login to quay.io, pull fails with "repository not found"
|
||||
defer func() {
|
||||
os.Unsetenv("REGISTRY_AUTH_FILE")
|
||||
}()
|
||||
os.Setenv("REGISTRY_AUTH_FILE", "/tmp/this/does/not/exist")
|
||||
|
||||
session := podmanTest.Podman([]string{"pull", "quay.io/libpod/ibetthisdoesntexist:there"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(ExitWithError(125, "nitializing source docker://quay.io/libpod/ibetthisdoesntexist:there: reading manifest there in quay.io/libpod/ibetthisdoesntexist: unauthorized: access to the requested resource is not authorized"))
|
||||
})
|
||||
|
||||
It("podman pull with tag --quiet", func() {
|
||||
session := podmanTest.Podman([]string{"pull", "-q", "quay.io/libpod/testdigest_v2s2:20200210"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
|
|
|
@ -2,59 +2,69 @@ package integration
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/containers/podman/v5/test/utils"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
// Create an image with the given seccomp label
|
||||
func makeLabeledImage(seccompLabel string) string {
|
||||
ctrName := "temp-working-container"
|
||||
imgName := "workingimage"
|
||||
session := podmanTest.Podman([]string{"run", "--name", ctrName, CITEST_IMAGE, "true"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(ExitCleanly())
|
||||
|
||||
session = podmanTest.Podman([]string{"commit", "-q", "--change", "LABEL io.containers.seccomp.profile=" + seccompLabel, ctrName, imgName})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(ExitCleanly())
|
||||
|
||||
return imgName
|
||||
}
|
||||
|
||||
var _ = Describe("Podman run", func() {
|
||||
|
||||
It("podman run --seccomp-policy default", func() {
|
||||
session := podmanTest.Podman([]string{"run", "-q", "--seccomp-policy", "default", alpineSeccomp, "ls"})
|
||||
session := podmanTest.Podman([]string{"run", "-q", "--seccomp-policy", "default", CITEST_IMAGE, "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
})
|
||||
|
||||
It("podman run --seccomp-policy ''", func() {
|
||||
// Empty string is interpreted as "default".
|
||||
session := podmanTest.Podman([]string{"run", "-q", "--seccomp-policy", "", alpineSeccomp, "ls"})
|
||||
session := podmanTest.Podman([]string{"run", "-q", "--seccomp-policy", "", CITEST_IMAGE, "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
})
|
||||
|
||||
It("podman run --seccomp-policy invalid", func() {
|
||||
session := podmanTest.Podman([]string{"run", "--seccomp-policy", "invalid", alpineSeccomp, "ls"})
|
||||
session := podmanTest.Podman([]string{"run", "--seccomp-policy", "invalid", CITEST_IMAGE, "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(ExitWithError(125, `invalid seccomp policy "invalid": valid policies are ["default" "image"]`))
|
||||
})
|
||||
|
||||
It("podman run --seccomp-policy image (block all syscalls)", func() {
|
||||
session := podmanTest.Podman([]string{"run", "--seccomp-policy", "image", alpineSeccomp, "ls"})
|
||||
// This image has seccomp profiles that blocks all syscalls.
|
||||
// The intention behind blocking all syscalls is to prevent
|
||||
// regressions in the future. The required syscalls can vary
|
||||
// depending on which runtime we're using.
|
||||
img := makeLabeledImage(`'{"defaultAction":"SCMP_ACT_ERRNO"}'`)
|
||||
session := podmanTest.Podman([]string{"run", "--seccomp-policy", "image", img, "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
// TODO: we're getting a "cannot start a container that has
|
||||
// stopped" error which seems surprising. Investigate
|
||||
// why that is so.
|
||||
base := filepath.Base(podmanTest.OCIRuntime)
|
||||
if base == "runc" {
|
||||
// TODO: worse than that. With runc, we get two alternating failures:
|
||||
// 126 + cannot start a container that has stopped
|
||||
// 127 + failed to connect to container's attach socket ... ENOENT
|
||||
Expect(session.ExitCode()).To(BeNumerically(">=", 126), "Exit status using runc")
|
||||
} else if base == "crun" {
|
||||
expect := fmt.Sprintf("OCI runtime error: %s: read from the init process", podmanTest.OCIRuntime)
|
||||
if IsRemote() {
|
||||
expect = fmt.Sprintf("for attach: %s: read from the init process: OCI runtime error", podmanTest.OCIRuntime)
|
||||
}
|
||||
Expect(session).To(ExitWithError(126, expect))
|
||||
} else {
|
||||
Skip("Not valid with the current OCI runtime")
|
||||
|
||||
expect := fmt.Sprintf("OCI runtime error: %s: read from the init process", podmanTest.OCIRuntime)
|
||||
if IsRemote() {
|
||||
expect = fmt.Sprintf("for attach: %s: read from the init process: OCI runtime error", podmanTest.OCIRuntime)
|
||||
}
|
||||
Expect(session).To(ExitWithError(126, expect))
|
||||
})
|
||||
|
||||
It("podman run --seccomp-policy image (bogus profile)", func() {
|
||||
session := podmanTest.Podman([]string{"run", "--seccomp-policy", "image", alpineBogusSeccomp, "ls"})
|
||||
// This image has a bogus/invalid seccomp profile which should
|
||||
// yield a json error when being read.
|
||||
img := makeLabeledImage(`'BOGUS - this should yield an error'`)
|
||||
session := podmanTest.Podman([]string{"run", "--seccomp-policy", "image", img, "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitWithError(125, "loading seccomp profile failed: decoding seccomp profile failed: invalid character 'B' looking for beginning of value"))
|
||||
})
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#####
|
||||
##### CAUTION! All changes to this file must also be
|
||||
##### CAUTION! mirrored to registries.conf !
|
||||
#####
|
||||
##### This is the registries.conf file used IN DEVELOPER ENVIRONMENT.
|
||||
##### For the one used in CI, see registries-cached.conf
|
||||
#####
|
||||
# Note that changing the order here may break tests.
|
||||
unqualified-search-registries = ['docker.io', 'quay.io', 'registry.fedoraproject.org']
|
||||
|
||||
[[registry]]
|
||||
# In Nov. 2020, Docker rate-limits image pulling. To avoid hitting these
|
||||
# limits while testing, always use the google mirror for qualified and
|
||||
# unqualified `docker.io` images.
|
||||
# Ref: https://cloud.google.com/container-registry/docs/pulling-cached-images
|
||||
prefix="docker.io"
|
||||
location="127.0.0.1:60333"
|
||||
insecure=true
|
||||
|
||||
[[registry]]
|
||||
prefix="quay.io"
|
||||
location="127.0.0.1:60333"
|
||||
insecure=true
|
||||
|
||||
# 2020-10-27 a number of images are not present in gcr.io, and podman
|
||||
# barfs spectacularly when trying to fetch them. We've hand-copied
|
||||
# those to quay, using skopeo copy --all ...
|
||||
[[registry]]
|
||||
prefix="docker.io/library"
|
||||
location="127.0.0.1:60333/libpod"
|
||||
insecure=true
|
||||
|
||||
# For testing #11933 to make sure that registries.conf is consulted unless
|
||||
# --tls-verify is used during container creation.
|
||||
[[registry]]
|
||||
location="localhost:5000"
|
||||
insecure=true
|
||||
|
||||
# Alias used in tests.
|
||||
[aliases]
|
||||
"podman-desktop-test123"="florent.fr/will/like"
|
|
@ -1,3 +1,10 @@
|
|||
#####
|
||||
##### CAUTION! All changes to this file must also be
|
||||
##### CAUTION! mirrored to registries-cached.conf !
|
||||
#####
|
||||
##### This is the registries.conf file used IN DEVELOPER ENVIRONMENT.
|
||||
##### For the one used in CI, see registries-cached.conf
|
||||
#####
|
||||
# Note that changing the order here may break tests.
|
||||
unqualified-search-registries = ['docker.io', 'quay.io', 'registry.fedoraproject.org']
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ function start_registry() {
|
|||
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"
|
||||
local REGISTRY_IMAGE="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/registry:2.8.2"
|
||||
|
||||
# Pull registry image, but into a separate container storage and DB and everything
|
||||
PODMAN_LOGIN_ARGS="--storage-driver vfs $(podman_isolation_opts ${PODMAN_LOGIN_WORKDIR})"
|
||||
|
|
Loading…
Reference in New Issue