1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#!/bin/bash
#
# make-v2sN - create a v2sN image, possibly with dups
#
# This is a helper script used for creating custom images for buildah testing.
# The images are used in the digest.bats test.
#
ME=$(basename $0)
die() {
echo "$ME: $*" >&2
exit 1
}
###############################################################################
#
# From the script name, determine the desired schema version (1 or 2) and
# whether or not we want duplicate layers.
schemaversion=$(expr "$ME" : ".*-v2s\([12]\)")
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
dup="_with_dups"
fi
IMGNAME=testdigest_v2s${schemaversion}${dup}
###############################################################################
# Create the image.
set -e
# First layer
cid=$(buildah from scratch)
buildah commit -q $cid interim1
# Create a second layer containing this script and a README
cid2=$(buildah from interim1)
mp=$(buildah mount $cid2)
cp $0 $mp/
cat <<EOF >$mp/README
This is a test image used for buildah testing.
EOF
# In the README include creation timestamp, user, script name, git tree state
function add_to_readme() {
printf " %-12s : %s\n" "$1" "$2" >>$mp/README
}
add_to_readme "Created" "$(date --iso-8601=seconds)"
# FIXME: do we really need to know? Will it ever, in practice, be non-root?
user=$(id -un)
if [ -n "$user" -a "$user" != "root" ]; then
add_to_readme "By (user)" "$user"
fi
create_script=$(cd $(dirname $0) && git ls-files --full-name $ME)
if [ -z "$create_script" ]; then
create_script=$0
fi
add_to_readme "By (script)" "$create_script"
git_state=$(cd $(dirname $0) && git describe --dirty)
if [ -n "$git_state" ]; then
add_to_readme "git state" "$git_state"
fi
echo "-----------------------------------------------------------------"
cat $mp/README
echo "-----------------------------------------------------------------"
buildah umount $cid2
buildah commit -q $cid2 interim2
layers="interim2 interim1"
buildah tag interim2 my_image
###############################################################################
#
# Push/pull the image to/from a tempdir. This is a kludge allowing us to
# clean up interim layers. It's also necessary for dealing with v2s1 layers.
TMPDIR=$(mktemp --tmpdir -d $(basename $0).XXXXXXX)
push_flags=
if [[ $schemaversion -eq 1 ]]; then
# buildah can't actually create a v2s1 image; only v2s2. To create v2s1,
# dir-push it to a tmpdir using '--format v2s1'; that will be inherited
# when we reload it
push_flags="--format v2s1"
fi
buildah push $push_flags my_image dir:${TMPDIR}/${IMGNAME}
# Clean up containers and images
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})
# Leave the tmpdir behind for the -dup image!
if [ -z "$dup" ]; then
rm -rf ${TMPDIR}
fi
###############################################################################
#
# We should now have a 'localhost/IMGNAME' image with desired SchemaVersion
# and other features as requested.
#
# Now verify what we have what we intended.
echo
if type -p jq >&/dev/null; then
# Manifest is embedded in the image but as a string, not actual JSON;
# the eval-echo converts it to usable JSON
manifest=$(eval echo $(buildah inspect ${IMGNAME} | jq .Manifest))
# Check desired schema version:
actual_schemaversion=$(jq .schemaVersion <<<"$manifest")
if [[ $actual_schemaversion -ne $schemaversion ]]; then
die "Expected .schemaVersion $schemaversion, got '$actual_schemaversion'"
fi
echo "Image localhost/${IMGNAME} looks OK; feel free to:"
echo
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"
echo "in test/digest.bats."
echo
echo "Note that the Digest SHA on quay.io != the SHA on the locally"
echo "created image. You can get the real SHA on quay.io by clicking"
echo "on the image name, then the luggage-tag icon on the left,"
echo "then the gray box with the text 'SHA256' (not the actual"
echo "hash shown in blue to its right), and copy-pasting the SHA"
echo "from the popup window."
echo
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
|