-
Notifications
You must be signed in to change notification settings - Fork 760
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests: new tool to build a no-history image
Script crafts a custom image with multiple layers but no history; used in tests/bud.bats:bud-implicit-no-history test. Signed-off-by: Ed Santiago <santiago@redhat.com>
- Loading branch information
1 parent
ee70428
commit d30786a
Showing
3 changed files
with
250 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
#!/bin/bash | ||
# | ||
# build-no-history-image - craft a custom image used in bud-implicit-no-history test. | ||
# | ||
# This script does not run in CI, or automated tests, or gating. In fact | ||
# it is meant to be run once, only once, by a human, and then (with luck) | ||
# never again. The purpose is to create a custom test image with certain | ||
# very specific attributes. This image will be used in one specific test. | ||
# Maybe some day other tests. The image should be static and immutable. | ||
# This creation script is checked into the buildah source tree simply | ||
# as reference for how the image was created, and as a tool should there | ||
# ever be a need to update that test image in some way. | ||
# | ||
# See https://github.com/containers/buildah/pull/5473 | ||
# | ||
set -e | ||
|
||
# Name of the resulting image. (Never pushed automatically). | ||
# If image build is successful, a human can push it to quay. | ||
IMAGE=quay.io/libpod/buildah-testimage-nohistory:$(date +%Y%m%d) | ||
podman rmi -f $IMAGE &> /dev/null | ||
|
||
# Arches for which we want to build images | ||
declare -a arches=(amd64 arm:v7 arm64:v8 ppc64le s390x) | ||
|
||
# Working directory; we'll be filling it up with layer files and | ||
# manifests and whatnot | ||
workdir=$(mktemp --tmpdir --directory $(basename $0).XXXXXXX) | ||
ocidir=oci/blobs/sha256 | ||
mkdir -p $workdir/$ocidir | ||
|
||
# First layer is a copy of this script. Copy it before we cd. | ||
cp $0 $workdir/ | ||
cd $workdir | ||
echo $workdir | ||
|
||
# | ||
# PASS 1: Create some layers (content) | ||
# | ||
declare -a layerid layersize | ||
|
||
# Helper for creating one layer. If called with an argument, use | ||
# that as input file; otherwise create random content | ||
function createlayer() { | ||
local inputfile | ||
if [[ -n "$*" ]]; then | ||
inputfile=$1 | ||
shift | ||
else | ||
inputfile=myfile | ||
dd if=/dev/urandom bs=1 count=$((RANDOM+1024)) of=$inputfile status=none | ||
fi | ||
|
||
# Tar it. Once we tar it, we have no further need for the original | ||
tarfile=mylayer.tar | ||
tar -cf $tarfile $inputfile | ||
rm -f $inputfile | ||
|
||
# Move tarfile into blob dir; name = digest | ||
sha=$(sha256sum $tarfile | awk '{print $1}') | ||
layerid+=($sha) | ||
layersize+=($(stat -c %s $tarfile)) | ||
|
||
mv $tarfile oci/blobs/sha256/$sha | ||
} | ||
|
||
createlayer $(basename $0) | ||
for i in $(seq 3); do | ||
# Content for the layer | ||
createlayer | ||
done | ||
|
||
# | ||
# PASS 2: Create json files for each desired arch | ||
# | ||
cat >mlist.json <<EOF | ||
{ | ||
"schemaVersion": 2, | ||
"mediaType": "application/vnd.oci.image.index.v1+json", | ||
"manifests": [ | ||
EOF | ||
|
||
mlistcomma= | ||
for tuple in "${arches[@]}"; do | ||
arch=$tuple | ||
variant= | ||
if [[ $arch =~ : ]]; then | ||
variant=$(expr "$arch" : ".*:\(.*\)") | ||
arch=${arch%%:*} | ||
fi | ||
|
||
# >>>>> config.json | ||
config=config-$tuple.json | ||
cat >$config <<EOF | ||
{ | ||
"created": "$(date --utc +'%Y-%m-%dT%H:%M:%S.%NZ')", | ||
"architecture": "$arch", | ||
"os": "linux", | ||
"config": { | ||
"Cmd": ["/bin/sh"], | ||
"Env": [ "PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin" ] | ||
}, | ||
"rootfs": { | ||
"type": "layers", | ||
"diff_ids": [ | ||
EOF | ||
comma= | ||
for layer in "${layerid[@]}";do | ||
test -n "$comma" && echo $comma >> $config | ||
echo -n ' "sha256:'${layer}'"' >> $config | ||
comma="," | ||
done | ||
|
||
cat >>$config <<EOF | ||
] | ||
} | ||
} | ||
EOF | ||
|
||
confdigest=$(sha256sum $config | awk '{print $1}') | ||
confsize=$(stat -c %s $config) | ||
ln $config $ocidir/$confdigest | ||
|
||
# >>>>> manifest.json references config.json | ||
manifest=manifest-$tuple.json | ||
cat >$manifest <<EOF | ||
{ | ||
"schemaVersion": 2, | ||
"mediaType": "application/vnd.oci.image.manifest.v1+json", | ||
"config": { | ||
"mediaType": "application/vnd.oci.image.config.v1+json", | ||
"digest": "sha256:$confdigest", | ||
"size": $confsize | ||
}, | ||
"layers": [ | ||
EOF | ||
|
||
comma= | ||
for i in $(seq 0 $((${#layerid[*]} - 1))); do | ||
test -n "$comma" && echo $comma >>$manifest | ||
cat >>$manifest <<EOF | ||
{ | ||
"mediaType": "application/vnd.oci.image.layer.v1.tar", | ||
"digest": "sha256:${layerid[$i]}", | ||
"size": ${layersize[$i]} | ||
EOF | ||
echo -n ' }' >>$manifest | ||
|
||
comma="," | ||
done | ||
echo >>$manifest | ||
echo " ]" >>$manifest | ||
echo "}" >>$manifest | ||
|
||
manifestdigest=$(sha256sum $manifest | awk '{print $1}') | ||
manifestsize=$(stat -c %s $manifest) | ||
ln $manifest $ocidir/$manifestdigest | ||
|
||
# >>>>> top-level manifest list.json references this arch's manifest.json | ||
test -n "$mlistcomma" && echo $comma >>mlist.json | ||
cat >>mlist.json <<EOF | ||
{ | ||
"mediaType": "application/vnd.oci.image.manifest.v1+json", | ||
"digest": "sha256:${manifestdigest}", | ||
"size": ${manifestsize}, | ||
"platform": { | ||
"architecture": "${arch}", | ||
"os": "linux", | ||
"variant": "${variant}" | ||
} | ||
EOF | ||
echo -n ' }' >>mlist.json | ||
mlistcomma="," | ||
done | ||
|
||
cat >>mlist.json <<EOF | ||
] | ||
} | ||
EOF | ||
|
||
# Finally, the starting point is index.json which points | ||
# to the all-arch manifest list. | ||
mlistdigest=$(sha256sum mlist.json | awk '{print $1}') | ||
mlistsize=$(stat -c %s mlist.json) | ||
ln mlist.json $ocidir/$mlistdigest | ||
|
||
cat >oci/index.json <<EOF | ||
{ | ||
"schemaVersion": 2, | ||
"manifests": [ | ||
{ | ||
"mediaType": "application/vnd.oci.image.index.v1+json", | ||
"digest": "sha256:${mlistdigest}", | ||
"size": ${mlistsize} | ||
} | ||
] | ||
} | ||
EOF | ||
|
||
# Write the "this is an OCI layout directory" identifier. | ||
echo '{"imageLayoutVersion":"1.0.0"}' > oci/oci-layout | ||
|
||
#################################################################################### | ||
|
||
# Import the image from the OCI layout into buildah's normal storage. | ||
# Complicated horrible loop because 'skopeo copy --all' barfs: | ||
# containers-storage" does not support copying multiple images as a group | ||
podman manifest create $IMAGE | ||
for tuple in "${arches[@]}"; do | ||
arch=$tuple | ||
override_variant= | ||
if [[ $arch =~ : ]]; then | ||
v=$(expr "$arch" : ".*:\(.*\)") | ||
override_variant="--override-variant=$v" | ||
arch=${arch%%:*} | ||
fi | ||
|
||
tmpimage=localhost/foo$arch$variant:bar | ||
podman rmi -f $tmpimage | ||
skopeo copy --override-arch=$arch $override_variant oci:oci containers-storage:$tmpimage | ||
podman manifest add $IMAGE containers-storage:$tmpimage | ||
done | ||
|
||
# Double-check that the image has no history, which is what we wanted to get | ||
# out of all of this. | ||
inspect_history=$(buildah inspect --format '{{.History}}' $IMAGE) | ||
if [[ "$inspect_history" != '[]' ]]; then | ||
echo "base image generated for test had history field that was not an empty slice:" >&2 | ||
echo "$inspect_history" >&2 | ||
exit 1 | ||
fi | ||
|
||
# Worked. Clean up working directory | ||
cd / | ||
rm -rf $workdir | ||
|
||
echo | ||
echo "You may now run:" | ||
echo " podman manifest push --all $IMAGE docker://$IMAGE" |