image with dup layers: we now have one on quay

...and a process to create future ones. Thanks to Nalin for
a short patch to skopeo that allows pushing images with dups.

This commit updates make-v2sN to add "with-dups" functionality;
it simply creates a v2s1 image, then uses jq (JSON tool) to
duplicate the first .fsLayers and .history elements. Updated
instructions so others can (we hope) do this in the future
should it ever be necessary (we hope not).

Update the checks that confirm that the image we pull has
dup layers - this is a guarantee that we're testing what
we think we're testing.

Signed-off-by: Ed Santiago <santiago@redhat.com>
This commit is contained in:
Ed Santiago 2020-03-12 14:11:30 -06:00
parent bb561e01b2
commit 91c08ff7fc
2 changed files with 56 additions and 33 deletions

View File

@ -3,21 +3,23 @@
load helpers
fromreftest() {
run_buildah from --quiet --pull --signature-policy ${TESTSDIR}/policy.json $1
local img=$1
run_buildah from --quiet --pull --signature-policy ${TESTSDIR}/policy.json $img
cid=$output
# If image includes '_v2sN', verify that image is schema version N
expected_schemaversion=$(expr "$1" : '.*_v2s\([0-9]\)')
local expected_schemaversion=$(expr "$img" : '.*_v2s\([0-9]\)')
if [ -n "$expected_schemaversion" ]; then
actual_schemaversion=$(imgtype -expected-manifest-type '*' -show-manifest $1 | jq .schemaVersion)
actual_schemaversion=$(imgtype -expected-manifest-type '*' -show-manifest $img | jq .schemaVersion)
expect_output --from="$actual_schemaversion" "$expected_schemaversion" \
".schemaversion of $1"
".schemaversion of $img"
fi
# This is all we test: basically, that buildah doesn't crash when pushing
pushdir=${TESTDIR}/fromreftest
mkdir -p ${pushdir}/{1,2,3}
run_buildah push --signature-policy ${TESTSDIR}/policy.json $1 dir:${pushdir}/1
run_buildah push --signature-policy ${TESTSDIR}/policy.json $img dir:${pushdir}/1
run_buildah commit --signature-policy ${TESTSDIR}/policy.json $cid new-image
run_buildah push --signature-policy ${TESTSDIR}/policy.json new-image dir:${pushdir}/2
run_buildah rmi new-image
@ -32,17 +34,21 @@ fromreftest() {
}
@test "from-by-digest-s1-a-discarded-layer" {
IMG=quay.io/libpod/testdigest_v2s1_with_dups@sha256:70d6c767101c907aa251c21fded459c0f1a481685eb764ca2f7a6162e24dd81a
IMG=quay.io/libpod/testdigest_v2s1_with_dups@sha256:2c619fffbed29d8677e246798333e7d1b288333cb61c020575f6372c76fdbb52
fromreftest ${IMG}
# Verify that image meets our expectations (duplicate layers)
# Surprisingly, we do this after fromreftest, not before, because fromreftest
# has to pull the image for us.
dups=$(imgtype -expected-manifest-type '*' -show-manifest ${IMG} | jq .fsLayers|grep blobSum|sort|uniq -cd)
if [[ -z "$dups" ]]; then
die "Image ${IMG} does not have any duplicate layers (expected: one dup)"
fi
#
# Check that the first and second .fsLayers and .history elements are dups
local manifest=$(imgtype -expected-manifest-type '*' -show-manifest ${IMG})
for element in fsLayers history; do
local first=$(jq ".${element}[0]" <<<"$manifest")
local second=$(jq ".${element}[1]" <<<"$manifest")
expect_output --from="$second" "$first" "${IMG}: .${element}[1] == [0]"
done
}
@test "from-by-tag-s1" {

View File

@ -22,7 +22,7 @@ test -n "$schemaversion" || die "Could not find 'v2s[12]' in basename"
test "$schemaversion" = "N" && die "Script must be invoked via symlink"
dup=
if expr "$ME" : ".*-dup" >&/dev/null; then
if expr "$ME" : ".*-dup" &>/dev/null; then
dup="_with_dups"
fi
@ -78,17 +78,7 @@ buildah umount $cid2
buildah commit -q $cid2 interim2
layers="interim2 interim1"
# If a dup layer is requested, create it now
if [ -n "$dup" ]; then
cid3=$(buildah from interim2)
buildah commit -q $cid3 interim3
layers="interim3 $layers"
buildah tag interim3 my_image
else
buildah tag interim2 my_image
fi
buildah tag interim2 my_image
###############################################################################
#
@ -109,9 +99,26 @@ buildah push $push_flags my_image dir:${TMPDIR}/${IMGNAME}
buildah rm -a
buildah rmi -f my_image $layers
if [ -n "$dup" ]; then
manifest=${TMPDIR}/${IMGNAME}/manifest.json
cat $manifest |
jq -c '.fsLayers |= [.[0]] + .' |
jq -c '.history |= [.[0]] + .' |
tr -d '\012' >$manifest.tmp
mv $manifest $manifest.BAK
mv $manifest.tmp $manifest
fi
# Delete possibly-existing image, because 'buildah pull' will not overwrite it
buildah rmi -f localhost/${IMGNAME}:latest &>/dev/null || true
# Reload the image
(cd $TMPDIR && buildah pull dir:${IMGNAME})
rm -rf ${TMPDIR}
# Leave the tmpdir behind for the -dup image!
if [ -z "$dup" ]; then
rm -rf ${TMPDIR}
fi
###############################################################################
#
@ -131,18 +138,17 @@ if type -p jq >&/dev/null; then
die "Expected .schemaVersion $schemaversion, got '$actual_schemaversion'"
fi
if [ -n "$dup" ]; then
# Check that there's one layer listed twice
dup_layers=$(jq .fsLayers <<<"$manifest" | grep blobSum | sort | uniq -cd)
if [ -z "$dup_layers" ]; then
die "Did not find any duplicate layers in image"
fi
fi
echo "Image localhost/${IMGNAME} looks OK; feel free to:"
echo
echo " buildah push localhost/${IMGNAME} quay.io/libpod/${IMGNAME}:$(date +%Y%m%d)"
echo " buildah push localhost/${IMGNAME} quay.io/libpod/${IMGNAME}:latest"
if [ -n "$dup" ]; then
echo " \$SKOPEO copy dir:${TMPDIR}/${IMGNAME} docker://quay.io/libpod/${IMGNAME}:\$(date +%Y%m%d)"
echo " ^^^^^^^--- must be specially-crafted skopeo(*), see below"
else
echo " buildah push localhost/${IMGNAME} quay.io/libpod/${IMGNAME}:$(date +%Y%m%d)"
echo " buildah push localhost/${IMGNAME} quay.io/libpod/${IMGNAME}:latest"
fi
echo
echo "You may then need to log in to the https://quay.io/ web UI"
echo "make those images public, then update tags and/or SHAs"
@ -158,6 +164,17 @@ if type -p jq >&/dev/null; then
echo "NOTE: the first push to quay.io sometimes fails with some sort of"
echo "500 error, trying to reuse blob, blah blah. Just ignore it and"
echo "retry. IME it works the second time."
if [ -n "$dup" ]; then
echo
echo "(*) skopeo WILL NOT push an image with dup layers. To get it to"
echo " do that, build a custom skopeo using the patch here:"
echo " https://gist.github.com/nalind/b491204ff05c3c3f3b6ef014b333a60c"
echo " ...then use that skopeo in the above 'copy' command."
# And, for posterity should the gist ever disappear:
# vendor/github.com/containers/image/v5/manifest/docker_schema1.go
# - remove lines 66-68 ('if ... s1.fixManifestLayers()...')
fi
else
echo "WARNING: 'jq' not found; unable to verify built image" >&2
fi