diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 16:20:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 16:20:50 +0000 |
commit | 318b0d0e7515e0a97e647906387ecf89455f3878 (patch) | |
tree | 905dcee34012fd33308dbfda2f7114343dd36e8b /tests | |
parent | Initial commit. (diff) | |
download | golang-github-containers-storage-318b0d0e7515e0a97e647906387ecf89455f3878.tar.xz golang-github-containers-storage-318b0d0e7515e0a97e647906387ecf89455f3878.zip |
Adding upstream version 1.51.0+ds1.upstream/1.51.0+ds1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests')
38 files changed, 5386 insertions, 0 deletions
diff --git a/tests/abs.bats b/tests/abs.bats new file mode 100644 index 0000000..1cccf28 --- /dev/null +++ b/tests/abs.bats @@ -0,0 +1,11 @@ +#!/usr/bin/env bats + +load helpers + +@test "absolute-paths" { + cd ${TESTDIR} + storage --graph tmp1a/deep/root --run tmp1b/deep/runroot layers + storage --graph ./tmp2a/deep/root --run ./tmp2b/deep/runroot layers + storage --graph tmp1a/deep/root --run tmp1b/deep/runroot shutdown + storage --graph ./tmp2a/deep/root --run ./tmp2b/deep/runroot shutdown +} diff --git a/tests/apply-diff.bats b/tests/apply-diff.bats new file mode 100644 index 0000000..83807c8 --- /dev/null +++ b/tests/apply-diff.bats @@ -0,0 +1,103 @@ +#!/usr/bin/env bats + +load helpers + +@test "applydiff" { + # The checkdiffs function needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + # Create and populate three interesting layers. + populate + + # Extract the layers. + storage diff -u -f $TESTDIR/lower.tar $lowerlayer + storage diff -c -f $TESTDIR/middle.tar $midlayer + storage diff -u -f $TESTDIR/upper.tar $upperlayer + + # Delete the layers. + storage delete-layer $upperlayer + storage delete-layer $midlayer + storage delete-layer $lowerlayer + + # Create new layers and populate them using the layer diffs. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + storage applydiff -f $TESTDIR/lower.tar "$lowerlayer" + + run storage --debug=false create-layer "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + midlayer="$output" + storage applydiff -f $TESTDIR/middle.tar "$midlayer" + + run storage --debug=false create-layer "$midlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + storage applydiff -f $TESTDIR/upper.tar "$upperlayer" + + # The contents of these new layers should match what the old ones had. + checkchanges + checkdiffs +} + +@test "apply-diff-from-staging-directory" { + case "$STORAGE_DRIVER" in + overlay*) + ;; + *) + skip "driver $STORAGE_DRIVER does not support diff-from-staging-directory" + ;; + esac + + SRC=$TESTDIR/source + mkdir -p $SRC + createrandom $SRC/file1 + createrandom $SRC/file2 + createrandom $SRC/file3 + + local sconf=$TESTDIR/storage.conf + + local root=`storage status 2>&1 | awk '/^Root:/{print $2}'` + local runroot=`storage status 2>&1 | awk '/^Run Root:/{print $3}'` + + cat >$sconf <<EOF +[storage] +driver="overlay" +graphroot="$root" +runroot="$runroot" + +[storage.options] +pull_options = {enable_partial_images = "true" } +EOF + + # Create a layer. + CONTAINERS_STORAGE_CONF=$sconf run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer="$output" + + CONTAINERS_STORAGE_CONF=$sconf run storage --debug=false applydiff-using-staging-dir $layer $SRC + [ "$status" -eq 0 ] + + name=safe-image + CONTAINERS_STORAGE_CONF=$sconf run storage --debug=false create-image --name $name $layer + [ "$status" -eq 0 ] + + ctrname=foo + CONTAINERS_STORAGE_CONF=$sconf run storage --debug=false create-container --name $ctrname $name + [ "$status" -eq 0 ] + + CONTAINERS_STORAGE_CONF=$sconf run storage --debug=false mount $ctrname + [ "$status" -eq 0 ] + mount="$output" + + for i in file1 file2 file3 ; do + run cmp $SRC/$i $mount/$i + [ "$status" -eq 0 ] + done +} diff --git a/tests/apply-junk.bats b/tests/apply-junk.bats new file mode 100644 index 0000000..164fa58 --- /dev/null +++ b/tests/apply-junk.bats @@ -0,0 +1,47 @@ +#!/usr/bin/env bats + +load helpers + +function applyjunk_main() { + # Create and try to populate layers with... garbage. It should be + # rejected cleanly. + compressed="$1" + + storage create-layer --id layer-${compressed} + + echo [[${compressed} /etc/os-release]] + if ! ${compressed} < /etc/os-release > junkfile ; then + skip "error running ${compressed}" + fi + run storage apply-diff --file junkfile layer-${compressed} + echo "$output" + [[ "$status" -ne 0 ]] + [[ "$output" =~ "invalid tar header" ]] || [[ "$output" =~ "unexpected EOF" ]] + + echo [[${compressed}]] + echo "sorry, not even enough info for a tar header here" | ${compressed} > junkfile + run storage apply-diff --file junkfile layer-${compressed} + echo "$output" + [[ "$status" -ne 0 ]] + [[ "$output" =~ "unexpected EOF" ]] +} + +@test "applyjunk-uncompressed" { + applyjunk_main cat +} + +@test "applyjunk-gzip" { + applyjunk_main gzip +} + +@test "applyjunk-bzip2" { + applyjunk_main bzip2 +} + +@test "applyjunk-xz" { + applyjunk_main xz +} + +@test "applyjunk-zstd" { + applyjunk_main zstd +} diff --git a/tests/bigdata.bats b/tests/bigdata.bats new file mode 100644 index 0000000..8d04415 --- /dev/null +++ b/tests/bigdata.bats @@ -0,0 +1,212 @@ +#!/usr/bin/env bats + +load helpers + +@test "image-data" { + # Bail if "sha256sum" isn't available. + if test -z "$(which sha256sum 2> /dev/null)" ; then + skip "need sha256sum" + fi + + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Make sure the image can be located. + storage exists -i $image + + # Make sure the image has no big data items associated with it. + run storage --debug=false list-image-data $image + [ "$status" -eq 0 ] + [ "$output" = "" ] + + # Create two random files. + createrandom $TESTDIR/big-item-1 1234 + createrandom $TESTDIR/big-item-2 5678 + + # Set each of those files as a big data item named after the file. + storage set-image-data -f $TESTDIR/big-item-1 $image big-item-1 + storage set-image-data -f $TESTDIR/big-item-2 $image big-item-2 + + # Get a list of the items. Make sure they're both listed. + run storagewithsorting --debug=false list-image-data $image + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 2 ] + [ "${lines[0]}" = "big-item-1" ] + [ "${lines[1]}" = "big-item-2" ] + + # Check that the recorded sizes of the items match what we decided above. + run storage get-image-data-size $image no-such-item + [ "$status" -ne 0 ] + run storage --debug=false get-image-data-size $image big-item-1 + [ "$status" -eq 0 ] + [ "$output" -eq 1234 ] + run storage --debug=false get-image-data-size $image big-item-2 + [ "$status" -eq 0 ] + [ "$output" -eq 5678 ] + + # Check that we can distinguish between no-such-image and no-such-item. + run storage --debug=false get-image-data nosuchimage big-item + [ "$status" -ne 0 ] + echo "$output" + [[ "$output" =~ "image not known" ]] + run storage --debug=false get-image-data $image no-such-big-item + [ "$status" -ne 0 ] + echo "$output" + [[ "$output" =~ "does not exist" ]] + + # Save the contents of the big data items to disk and compare them with the originals. + run storage --debug=false get-image-data $image no-such-item + [ "$status" -ne 0 ] + storage get-image-data -f $TESTDIR/big-item-1.2 $image big-item-1 + cmp $TESTDIR/big-item-1 $TESTDIR/big-item-1.2 + storage get-image-data -f $TESTDIR/big-item-2.2 $image big-item-2 + cmp $TESTDIR/big-item-2 $TESTDIR/big-item-2.2 + + # Read the recorded digests of the items and compare them with the digests of the originals. + run storage get-image-data-digest $image no-such-item + [ "$status" -ne 0 ] + run storage --debug=false get-image-data-digest $image big-item-1 + [ "$status" -eq 0 ] + sum=$(sha256sum $TESTDIR/big-item-1) + sum=sha256:"${sum%% *}" + echo output:"$output": + echo sum:"$sum": + [ "$output" = "$sum" ] + run storage --debug=false get-image-data-digest $image big-item-2 + [ "$status" -eq 0 ] + sum=$(sha256sum $TESTDIR/big-item-2) + sum=sha256:"${sum%% *}" + echo output:"$output": + echo sum:"$sum": + [ "$output" = "$sum" ] +} + +@test "container-data" { + # Bail if "sha256sum" isn't available. + if test -z "$(which sha256sum 2> /dev/null)" ; then + skip "need sha256sum" + fi + + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container based on that image. + run storage --debug=false create-container $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Make sure the container can be located. + storage exists -c $container + + # Make sure the container has no big data items associated with it. + run storage --debug=false list-container-data $container + [ "$status" -eq 0 ] + [ "$output" = "" ] + + # Create two random files. + createrandom $TESTDIR/big-item-1 1234 + createrandom $TESTDIR/big-item-2 5678 + + # Set each of those files as a big data item named after the file. + storage set-container-data -f $TESTDIR/big-item-1 $container big-item-1 + storage set-container-data -f $TESTDIR/big-item-2 $container big-item-2 + + # Get a list of the items. Make sure they're both listed. + run storage --debug=false list-container-data $container + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 2 ] + [ "${lines[0]}" = "big-item-1" ] + [ "${lines[1]}" = "big-item-2" ] + + # Check that the recorded sizes of the items match what we decided above. + run storage get-container-data-size $container no-such-item + [ "$status" -ne 0 ] + run storage --debug=false get-container-data-size $container big-item-1 + echo "$output" + [ "$status" -eq 0 ] + [ "$output" -eq 1234 ] + run storage --debug=false get-container-data-size $container big-item-2 + [ "$status" -eq 0 ] + [ "$output" -eq 5678 ] + + # Save the contents of the big data items to disk and compare them with the originals. + run storage --debug=false get-container-data $container no-such-item + [ "$status" -ne 0 ] + storage get-container-data -f $TESTDIR/big-item-1.2 $container big-item-1 + cmp $TESTDIR/big-item-1 $TESTDIR/big-item-1.2 + storage get-container-data -f $TESTDIR/big-item-2.2 $container big-item-2 + cmp $TESTDIR/big-item-2 $TESTDIR/big-item-2.2 + + # Read the recorded digests of the items and compare them with the digests of the originals. + run storage get-container-data-digest $container no-such-item + [ "$status" -ne 0 ] + run storage --debug=false get-container-data-digest $container big-item-1 + [ "$status" -eq 0 ] + sum=$(sha256sum $TESTDIR/big-item-1) + sum=sha256:"${sum%% *}" + echo output:"$output": + echo sum:"$sum": + [ "$output" = "$sum" ] + run storage --debug=false get-container-data-digest $container big-item-2 + [ "$status" -eq 0 ] + sum=$(sha256sum $TESTDIR/big-item-2) + sum=sha256:"${sum%% *}" + echo output:"$output": + echo sum:"$sum": + [ "$output" = "$sum" ] +} + +@test "layer-data" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Make sure the layer has no big data items associated with it. + run storage --debug=false list-layer-data $layer + [ "$status" -eq 0 ] + [ "$output" = "" ] + + # Create two random files. + createrandom $TESTDIR/big-item-1 1234 + createrandom $TESTDIR/big-item-2 5678 + + # Set each of those files as a big data item named after the file. + storage set-layer-data -f $TESTDIR/big-item-1 $layer big-item-1 + storage set-layer-data -f $TESTDIR/big-item-2 $layer big-item-2 + + # Get a list of the items. Make sure they're both listed. + run storage --debug=false list-layer-data $layer + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 2 ] + [ "${lines[0]}" = "big-item-1" ] + [ "${lines[1]}" = "big-item-2" ] + + # Save the contents of the big data items to disk and compare them with the originals. + run storage --debug=false get-layer-data $layer no-such-item + [ "$status" -ne 0 ] + storage get-layer-data -f $TESTDIR/big-item-1.2 $layer big-item-1 + cmp $TESTDIR/big-item-1 $TESTDIR/big-item-1.2 + storage get-layer-data -f $TESTDIR/big-item-2.2 $layer big-item-2 + cmp $TESTDIR/big-item-2 $TESTDIR/big-item-2.2 +} diff --git a/tests/changes.bats b/tests/changes.bats new file mode 100644 index 0000000..85643ca --- /dev/null +++ b/tests/changes.bats @@ -0,0 +1,30 @@ +#!/usr/bin/env bats + +load helpers + +@test "changes" { + # Create and populate three interesting layers. + populate + + # Mount the layers. + run storage --debug=false mount "$lowerlayer" + [ "$status" -eq 0 ] + lowermount="$output" + run storage --debug=false mount "$midlayer" + [ "$status" -eq 0 ] + midmount="$output" + run storage --debug=false mount "$upperlayer" + [ "$status" -eq 0 ] + uppermount="$output" + + # Check the "changes" output. + checkchanges + + # Unmount the layers. + storage unmount $lowerlayer + storage unmount $midlayer + storage unmount $upperlayer + + # Now check the "changes" again. + checkchanges +} diff --git a/tests/check.bats b/tests/check.bats new file mode 100644 index 0000000..7f43e34 --- /dev/null +++ b/tests/check.bats @@ -0,0 +1,1064 @@ +#!/usr/bin/env bats + +load helpers + +# Check that the storage driver doesn't have any layers that we don't know +# about, and would therefore never be able to clean up, i.e., that we can +# spot them. +@test "check-unmanaged-layers" { + run storage --debug=false storage-layers + echo storage-layers: "$output" + if [ $status -eq 1 -a "$output" == "driver not supported" ] ; then + skip "driver $STORAGE_DRIVER does not support ListLayers()" + fi + + run storage --debug=false create-storage-layer + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + run storage create-storage-layer "$layer" + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + + run storage create-storage-layer + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + + run storage check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "layer ${layer}: layer in lower level storage driver not accounted for" ]] + + run storage --debug=false storage-layers + echo storage-layers: "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] +} + +# Check that nothing happens when the storage driver had layers that we don't +# know about in a read-only store. It's not as if we can do anything about +# them. +@test "check-unmanaged-ro-layers" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Put a couple of unmanaged layers in the read-only location. + mkdir ${TESTDIR}/{ro-root,ro-runroot} + + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-storage-layer + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-storage-layer "$layer" + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + otherlayer="$output" + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Put an image in the read-write location. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-image "$layer" + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Check that we don't complain about unmanaged layers in the read-only location. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check + echo "check:" "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] +} + +# Check that the storage driver doesn't have any layers that we don't know +# about in a read-write store, and would therefore never be able to clean up, +# i.e., that we can spot them. +@test "check-unmanaged-rw-layers" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Put an image in the read-only location. + mkdir ${TESTDIR}/{ro-root,ro-runroot} + + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rolayer=$output + + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-image "$rolayer" + echo create-image: "$output" + [[ $status -eq 0 ]] + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Put a couple of unmanaged layers in the read-write location. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-storage-layer + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-storage-layer "$layer" + echo create-storage-layer: "$output" + [[ $status -eq 0 ]] + otherlayer=$output + + # Check that we find the unmanaged layers in the read-write location and remove them. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "layer ${layer}: layer in lower level storage driver not accounted for" ]] + [[ $output =~ "layer ${otherlayer}: layer in lower level storage driver not accounted for" ]] + + # So now there shouldn't be any layers at all if we're just looking at the read-write location. + run storage --debug=false storage-layers + echo storage-layers: "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] + + # But there should still be that managed layer we put in the read-only location. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layers -q + echo storage-layers: "$output" + [[ $status -eq 0 ]] + [[ $output == "$rolayer" ]] +} + +# Check that we can detect layers that aren't part of an image or a container. +@test "check-unused-layers" { + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + run storage --debug=false create-layer $output + [[ $status -eq 0 ]] + layer=$output + + # By default, an unreferenced layer must have reached some minimum age + # in order for us to think it's been forgotten. + run storage --debug=false check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] + + # But if we set that minimum age to 0, we should clean it up. + run storage check -r -m 0 + echo "check -r -m 0:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "layer ${layer}: layer not referenced by any images or containers" ]] + + # After the cleanup, there shouldn't be anything left. + run storage --debug=false layers + echo layers: "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] +} + +# Check that we don't complain about layers in read-only storage that aren't +# part of an image or a container, since we can't do anything about them +# anyway. +@test "check-unused-ro-layers" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Put a couple of unreferenced layers in the read-only location. + mkdir ${TESTDIR}/{ro-root,ro-runroot} + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rolayer="$output" + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-layer "$rolayer" + echo create-layer: "$output" + [[ $status -eq 0 ]] + otherlayer="$output" + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Put an image in the read-write location. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-image "$layer" + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Check for errors. We shouldn't be warning about the unreferenced read-only layers. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -m 0 + echo "check -m 0:" "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] +} + +# Check that we can detect layers in read-write storage that aren't part of an +# image or a container. +@test "check-unused-rw-layers" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Put an image in the read-only location. + mkdir ${TESTDIR}/{ro-root,ro-runroot} + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rolayer="$output" + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-image "$rolayer" + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Put some unreferenced layers in the read-write location. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer "$layer" + echo create-layer: "$output" + [[ $status -eq 0 ]] + otherlayer=$output + + # By default, an unreferenced layer must have reached some minimum age + # in order for us to think it's been forgotten. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] + + # Now check for errors and repair them. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r -m 0 + echo "check -r -m 0:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "layer $layer: layer not referenced by any images or containers" ]] + [[ $output =~ "layer $otherlayer: layer not referenced by any images or containers" ]] + + # The read-only layer should be the only one present. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layers -q + echo layers: "$output" + [[ $status -eq 0 ]] + [[ $output == "$rolayer" ]] +} + +# Check that we can detect when the contents of a layer's files, at least the +# ones that we'd need to read in order to reconstruct the diff, have been +# altered. +@test "check-layer-content-digest" { + # This test needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + # Create a layer. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Set contents of the layer. + createrandom ${TESTDIR}/datafile1 + createrandom ${TESTDIR}/datafile2 + (cd ${TESTDIR}; tar cf - datafile1 datafile2) > ${TESTDIR}/diff + storage apply-diff -f ${TESTDIR}/diff $layer + + # Mark that layer as part of an image. + run storage --debug=false create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Put something in the layer that wasn't part of the diff. + createrandom ${TESTDIR}/datafile3 + storage copy ${TESTDIR}/datafile3 ${layer}:/datafile1 + + # Now check if the diff can be reproduced correctly. + run storage check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "layer ${layer}: layer content incorrect digest" ]] || [[ $output =~ "layer ${layer}: file integrity checksum failed" ]] + + # Having removed the layer, there should be no traces left. + run storage --debug=false images + echo images: "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] + + # Should look empty now + run storage --debug=false layers + echo layers: "$output" + [[ $status -eq 0 ]] + [[ $output == "" ]] +} + +# Check that we can detect when the contents of a read-only layer's files, at +# least the ones that we'd need to read in order to reconstruct the diff, have +# been altered. +@test "check-ro-layer-content-digest" { + # This test needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Put a layer record in the read-only location. + mkdir ${TESTDIR}/{ro-root,ro-runroot} + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rolayer="$output" + + # Set up that layer's contents. + createrandom ${TESTDIR}/datafile1 + createrandom ${TESTDIR}/datafile2 + (cd ${TESTDIR}; tar cf - datafile1 datafile2) > ${TESTDIR}/diff + storage apply-diff --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot -f ${TESTDIR}/diff $rolayer + + # Mess with that layer's contents. + createrandom ${TESTDIR}/datafile3 + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot copy ${TESTDIR}/datafile3 ${rolayer}:/datafile1 + + # Create an image record that uses that layer. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-image "$rolayer" + echo create-image: "$output" + [[ $status -eq 0 ]] + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Create a read-write layer. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rwlayer=$output + + # Create a read-write image. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-image $rwlayer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Check that we notice the added file, even if we can't fix it. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] # couldn't fix read-only layers + [[ $output =~ "layer ${rolayer}: layer content incorrect digest" ]] || [[ $output =~ "layer ${rolayer}: file integrity checksum failed" ]] + + # A check of just the read-write storage shouldn't turn up anything. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect when a layer has had content added. Due to the +# way diff reconstructs diffs from layers, items which weren't in the original +# diff won't be noticed if the check consists of only extracting the diff. +@test "check-layer-content-modified" { + # This test needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + # Create the layer record. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Set up the layer's contents. + createrandom ${TESTDIR}/datafile1 + createrandom ${TESTDIR}/datafile2 + (cd ${TESTDIR}; tar cf - datafile1 datafile2) > ${TESTDIR}/diff + storage apply-diff -f ${TESTDIR}/diff $layer + + # Add some contents to the layer. + createrandom ${TESTDIR}/datafile3 + storage copy ${TESTDIR}/datafile3 ${layer}:/datafile3 + + # Create the image record. + run storage --debug=false create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Check if we can detect that file being added. + run storage check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "layer ${layer}: +/datafile3, layer content modified" ]] + + # Should be all clear now. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect when one of an image's layers is gone, or at least +# doesn't correspond to one that we know of. +@test "check-image-layer-missing" { + # Create the layer record. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the image record. + run storage --debug=false create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image="$output" + + # Delete the layer with no safety checking. + run storage --debug=false delete $layer + echo delete layer: "$output" + [[ $status -eq 0 ]] + + # Check that we know to flag the image as damaged, and fix it. + run storage check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "image ${image}: layer ${layer}: image layer is missing" ]] + + # Check that we no longer think there's damage. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect when one of an image's layers is gone, or at least +# doesn't correspond to one that we know of. +@test "check-ro-image-layer-missing" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Create the read-only layer record. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the read-only image record. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image="$output" + + # Delete the layer with no safety checking. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot delete $layer + echo delete layer: "$output" + [[ $status -eq 0 ]] + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Create a read-write layer. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rwlayer=$output + + # Create a read-write image. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-image $rwlayer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Check that we know to flag the image as damaged, even if we can't fix it. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] # we can't fix it + [[ $output =~ "image ${image}: layer ${layer}: image layer is missing" ]] + + # Check that we no longer think there's damage if we just look at read-write content. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect when a container's base image is gone, or at least +# doesn't correspond to one that we know of. +@test "check-container-image-missing" { + # Create the layer. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the image that uses that layer. + run storage --debug=false create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image=$output + + # Create a container based on that image. + run storage --debug=false create-container $image + echo create-container: "$output" + [[ $status -eq 0 ]] + container=$output + + # Delete the image with no safety checks. + run storage --debug=false delete $image + echo delete image: "$output" + [[ $status -eq 0 ]] + + # Check and repair. Repair is okay with deleting images because they + # can be rebuilt or re-pulled. + run storage check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}:" ]] + [[ $output =~ "image ${image}: image missing" ]] + + # didn't get rid of the container, though! + + run storage check + echo check: "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}:" ]] + [[ $output =~ "image ${image}: image missing" ]] + + # Repair, but now we're okay with getting rid of containers. + run storage check -r -f + echo "check -r -f:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "container ${container}:" ]] + [[ $output =~ "image ${image}: image missing" ]] + + # Should be all clear now. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect when a container's base image is deleted in a +# read-only store, or at least doesn't correspond to one that we know of. +@test "check-container-ro-image-missing" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Create the read-only layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the read-only image that uses that layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image=$output + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Create a container based on that image. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-container $image + echo create-container: "$output" + [[ $status -eq 0 ]] + container=$output + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root container ${container} + echo container: "$output" + [[ $status -eq 0 ]] + clayer=$(grep ^Layer: <<< ${output}) + clayer=${clayer##* } + echo clayer: "${clayer}" + + # Delete the layer with no safety checks. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot delete $layer + echo delete layer: "$output" + [[ $status -eq 0 ]] + + # Delete the image while we're at it. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot delete $image + echo delete image: "$output" + [[ $status -eq 0 ]] + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Check and repair. Repair is okay with deleting images because they + # can be rebuilt or re-pulled. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}:" ]] + [[ $output =~ "image ${image}: image missing" ]] + [[ $output =~ "layer ${clayer} used by container ${container}: layer is in use by a container" ]] + + # couldn't get rid of the container, even so + + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check + echo check: "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}:" ]] + [[ $output =~ "image ${image}: image missing" ]] + + # Repair, but now we're okay with getting rid of damaged containers. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r -f + echo "check -r -f:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "container ${container}:" ]] + [[ $output =~ "image ${image}: image missing" ]] + + # Should be all clear now. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect layer data being lost. +@test "check-layer-data-missing" { + # Create the layer. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the image. + run storage --debug=false create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Set a data item associated with the layer. + createrandom ${TESTDIR}/datafile + storage set-layer-data -f ${TESTDIR}/datafile $layer datafile + run storage --debug=false list-layer-data $layer + echo list-layer-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + # Everything should look okay. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] + + # Delete that content and see if we notice. + rm -fv ${TESTDIR}/root/${STORAGE_DRIVER}-layers/$layer/datafile + run storage check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "layer ${layer}: data item \"datafile\": layer data item is missing" ]] + + # Should have repaired by deleting the image and layer, so we should be + # in the clear. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect read-only layer data being lost. +@test "check-ro-layer-data-missing" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Create the read-only layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the image. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Set a data item associated with the layer. + createrandom ${TESTDIR}/datafile + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot set-layer-data -f ${TESTDIR}/datafile $layer datafile + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot list-layer-data $layer + echo list-layer-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Create a read-write layer. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rwlayer=$output + + # Create a read-write image. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-image $rwlayer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Everything should look okay. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check + echo check: "$output" + [[ $status -eq 0 ]] + + # Delete that content and see if we notice. + rm -fv ${TESTDIR}/ro-root/${STORAGE_DRIVER}-layers/$layer/datafile + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] + [[ $output =~ "layer ${layer}: data item \"datafile\": layer data item is missing" ]] + + # Can't repair it by deleting the image and layer, so we should be just + # as broken as last time. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check + echo check: "$output" + [[ $status -ne 0 ]] + [[ $output =~ "layer ${layer}: data item \"datafile\": layer data item is missing" ]] + + # A check of just the read-write storage shouldn't turn up anything. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect image data being lost. +@test "check-image-data-missing" { + # Create the layer. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the image. + run storage --debug=false create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image=$output + + # Create the data associated with the image. + createrandom ${TESTDIR}/datafile + storage set-image-data -f ${TESTDIR}/datafile $image datafile + run storage --debug=false list-image-data $image + echo list-image-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + # Everything should look good so far. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] + + # Now delete the data and check that we notice it's gone. + rm -fv ${TESTDIR}/root/${STORAGE_DRIVER}-images/$image/datafile + run storage check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "image ${image}: data item \"datafile\": image data item is missing" ]] + + # Having repaired it by deleting the offending image, we should be okay again. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect image data in read-only stores being lost. +@test "check-ro-image-data-missing" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Create the read-only layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the image. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image=$output + + # Create the data associated with the image. + createrandom ${TESTDIR}/datafile + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot set-image-data -f ${TESTDIR}/datafile $image datafile + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot list-image-data $image + echo list-image-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + # Everything should look good so far. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot check + echo check: "$output" + [[ $status -eq 0 ]] + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Create a read-write layer. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rwlayer=$output + + # Create a read-write image. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-image $rwlayer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Now delete the data and check that we notice it's gone. + rm -fv ${TESTDIR}/ro-root/${STORAGE_DRIVER}-images/$image/datafile + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] + [[ $output =~ "image ${image}: data item \"datafile\": image data item is missing" ]] + + # Having been unable to repair it by deleting the offending image, we + # should still flag the error. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check + echo check: "$output" + [[ $status -ne 0 ]] + [[ $output =~ "image ${image}: data item \"datafile\": image data item is missing" ]] + + # A check of just the read-write storage shouldn't turn up anything. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect image data being modified. +@test "check-image-data-modified" { + # Create the layer. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the image. + run storage --debug=false create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image=$output + + # Create some data to associate with the image. + createrandom ${TESTDIR}/datafile + storage set-image-data -f ${TESTDIR}/datafile $image datafile + run storage --debug=false list-image-data $image + echo list-image-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + # Everything should look okay so far. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] + + # Corrupt that data and see if we notice. + echo "" >> ${TESTDIR}/root/${STORAGE_DRIVER}-images/$image/datafile + run storage check -r + echo "check -r:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "image ${image}: data item \"datafile\": image data item has incorrect size" ]] + + # We fixed that by removing the image, so everything should be okay now. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect image data being modified in read-only locations. +@test "check-ro-image-data-modified" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "driver $STORAGE_DRIVER does not support additional image stores" + ;; + esac + + # Create the read-only layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + layer=$output + + # Create the read-only image. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image $layer + echo create-image: "$output" + [[ $status -eq 0 ]] + image=$output + + # Create some data to associate with the read-only image. + createrandom ${TESTDIR}/datafile + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot set-image-data -f ${TESTDIR}/datafile $image datafile + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot list-image-data $image + echo list-image-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + # Everything should look okay so far. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot check + echo check: "$output" + [[ $status -eq 0 ]] + + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Create a read-write layer. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rwlayer=$output + + # Create a read-write image. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-image $rwlayer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Corrupt that data and see if we notice. + echo "" >> ${TESTDIR}/ro-root/${STORAGE_DRIVER}-images/$image/datafile + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] + [[ $output =~ "image ${image}: data item \"datafile\": image data item has incorrect size" ]] + + # We couldn't fix that by removing the image, so we should still notice the problem. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root check + echo check: "$output" + [[ $status -ne 0 ]] + [[ $output =~ "image ${image}: data item \"datafile\": image data item has incorrect size" ]] + + # A check of just the read-write storage shouldn't turn up anything. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect container data being lost. +@test "check-container-data-missing" { + # Create a container that isn't using an image as its base. + run storage --debug=false create-container "" + echo create-container: "$output" + [[ $status -eq 0 ]] + container=$output + + # Store some data alongside the container. + createrandom ${TESTDIR}/datafile + storage set-container-data -f ${TESTDIR}/datafile $container datafile + run storage --debug=false list-container-data $container + echo list-container-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + # Everything should look okay so far. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] + + # Now remove the associated data and see if we notice. + rm -fv ${TESTDIR}/root/${STORAGE_DRIVER}-containers/$container/datafile + run storage check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}: data item \"datafile\": container data item is missing" ]] + + # didn't get rid of the container, though + + # Should still look broken. + run storage check + echo check: "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}: data item \"datafile\": container data item is missing" ]] + + # Now let repair remove containers. + run storage check -r -f + echo "check -r -f:" "$output" + [[ $status -eq 0 ]] + + # Should look okay now. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} + +# Check that we can detect container data being modified. +@test "check-container-data-modified" { + # Create a container that isn't using an image as its base. + run storage --debug=false create-container "" + echo create-container: "$output" + [[ $status -eq 0 ]] + container=$output + + # Store some data alongside the container. + createrandom ${TESTDIR}/datafile + storage set-container-data -f ${TESTDIR}/datafile $container datafile + run storage --debug=false list-container-data $container + echo list-container-data: "$output" + [[ $status -eq 0 ]] + [[ $output != "" ]] + + # Everything should look okay so far. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] + + # Create a read-write layer. + run storage --debug=false create-layer + echo create-layer: "$output" + [[ $status -eq 0 ]] + rwlayer=$output + + # Create a read-write image. + run storage --debug=false create-image $rwlayer + echo create-image: "$output" + [[ $status -eq 0 ]] + + # Now remove the associated data and see if we notice. + echo "" >> ${TESTDIR}/root/${STORAGE_DRIVER}-containers/$container/datafile + run storage check -r + echo "check -r:" "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}: data item \"datafile\": container data item has incorrect size" ]] + + # didn't get rid of the container, though + + # Should still look broken. + run storage check + echo check: "$output" + [[ $status -ne 0 ]] + [[ $output =~ "container ${container}: data item \"datafile\": container data item has incorrect size" ]] + + # Now let repair remove containers. + run storage check -r -f + echo "check -r -f:" "$output" + [[ $status -eq 0 ]] + [[ $output =~ "container ${container}: data item \"datafile\": container data item has incorrect size" ]] + + # Should look okay now. + run storage check + echo check: "$output" + [[ $status -eq 0 ]] +} diff --git a/tests/cleanup-layer.bats b/tests/cleanup-layer.bats new file mode 100644 index 0000000..813028f --- /dev/null +++ b/tests/cleanup-layer.bats @@ -0,0 +1,17 @@ +#!/usr/bin/env bats + +load helpers + +@test "cleanup-layer" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + sed -i -e 's/"id":/"flags":{"incomplete":true},"id":/g' ${TESTDIR}/root/${STORAGE_DRIVER}-layers/layers.json + + # Get a list of the layers, which should clean it up. + run storage --debug=false layers + [ "$status" -eq 0 ] + echo "$output" + [ "${#lines[*]}" -eq 0 ] +} diff --git a/tests/container-dirs.bats b/tests/container-dirs.bats new file mode 100644 index 0000000..2cbc237 --- /dev/null +++ b/tests/container-dirs.bats @@ -0,0 +1,48 @@ +#!/usr/bin/env bats + +load helpers + +@test "container-dirs" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Check that the layer can be found. + storage exists -l $layer + + # Create an image using the layer. + run storage --debug=false create-image -m danger $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Check that the image can be found. + storage exists -i $image + + # Create a container based on the layer. + run storage --debug=false create-container $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that the container can be found. + storage exists -c $container + + # Check that the container's user data directory is somewhere under the root. + run storage --debug=false get-container-dir $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + dir=${output%% *} + touch "$dir"/dirfile + echo "$dir"/dirfile | grep -q ^"${TESTDIR}/root/" + + # Check that the container's user run data directory is somewhere under the run root. + run storage --debug=false get-container-run-dir $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + rundir=${output%% *} + touch "$rundir"/rundirfile + echo "$rundir"/rundirfile | grep -q ^"${TESTDIR}/runroot/" +} diff --git a/tests/container.bats b/tests/container.bats new file mode 100644 index 0000000..b123807 --- /dev/null +++ b/tests/container.bats @@ -0,0 +1,36 @@ +#!/usr/bin/env bats + +load helpers + +@test "container" { + # Create and populate three interesting layers. + populate + + # Create an image using to top layer. + run storage --debug=false create-image $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container using the image. + name=wonderful-container + run storage --debug=false create-container --name $name $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${lines[0]} + + # Add a couple of big data items. + createrandom ${TESTDIR}/random1 + createrandom ${TESTDIR}/random2 + storage set-container-data -f ${TESTDIR}/random1 $container random1 + storage set-container-data -f ${TESTDIR}/random2 $container random2 + + # Get information about the container, and make sure the ID, name, and data names were preserved. + run storage container $container + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "ID: $container" ]] + [[ "$output" =~ "Name: $name" ]] + [[ "$output" =~ "Data: random1" ]] + [[ "$output" =~ "Data: random2" ]] +} diff --git a/tests/create-container.bats b/tests/create-container.bats new file mode 100644 index 0000000..76054c2 --- /dev/null +++ b/tests/create-container.bats @@ -0,0 +1,109 @@ +#!/usr/bin/env bats + +load helpers + +@test "create-container" { + # Create a container based on no image. + run storage --debug=false create-container "" + [ "$status" -eq 0 ] + [ "$output" != "" ] + zerothcontainer=${output%% *} + + # Create an image using no layer. + run storage --debug=false create-image "" + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container based on that image. + run storage --debug=false create-container $image + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + thirdcontainer=${output%% *} + + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container based on that image. + run storage --debug=false create-container $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + firstcontainer=${output%% *} + + firstwriter=$(cat ${TESTDIR}/${CONTAINERS_LOCK_ROOT}/${STORAGE_DRIVER}-containers/containers.lock) + [ "$firstwriter" != "" ] + + # Check that the container can be found. + storage exists -c $firstcontainer + + # Create another container based on the same image. + run storage --debug=false create-container $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + secondcontainer=${output%% *} + + secondwriter=$(cat ${TESTDIR}/${CONTAINERS_LOCK_ROOT}/${STORAGE_DRIVER}-containers/containers.lock) + [ "$secondwriter" != "" ] + [ "$firstwriter" != "$secondwriter" ] + + # Check that *that* container can be found. + storage exists -c $secondcontainer + + # Check that a list of containers lists both of them. + run storage --debug=false containers + echo :"$output": + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 4 ] + [ "${lines[0]}" != "${lines[1]}" ] + [ "${lines[0]}" != "${lines[2]}" ] + [ "${lines[0]}" != "${lines[3]}" ] + [ "${lines[1]}" != "${lines[2]}" ] + [ "${lines[1]}" != "${lines[3]}" ] + [ "${lines[2]}" != "${lines[3]}" ] + [ "${lines[0]}" = "$zerothcontainer" ] || [ "${lines[0]}" = "$firstcontainer" ] || [ "${lines[0]}" = "$secondcontainer" ] || [ "${lines[0]}" = "$thirdcontainer" ] + [ "${lines[1]}" = "$zerothcontainer" ] || [ "${lines[1]}" = "$firstcontainer" ] || [ "${lines[1]}" = "$secondcontainer" ] || [ "${lines[1]}" = "$thirdcontainer" ] + [ "${lines[2]}" = "$zerothcontainer" ] || [ "${lines[2]}" = "$firstcontainer" ] || [ "${lines[2]}" = "$secondcontainer" ] || [ "${lines[2]}" = "$thirdcontainer" ] + [ "${lines[3]}" = "$zerothcontainer" ] || [ "${lines[3]}" = "$firstcontainer" ] || [ "${lines[3]}" = "$secondcontainer" ] || [ "${lines[3]}" = "$thirdcontainer" ] +} + +@test "create-and-mount-volatile-container" { + # Create a container based on no image. + run storage --debug=false create-container --volatile "" + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + run storage --debug=false mount $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + path=${output%% *} + + echo test > $path/newfile + + run storage --debug=false unmount $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + + run storage --debug=false mount $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + path=${output%% *} + + run cat $path/newfile + [ "$status" -eq 0 ] + [ "$output" == "test" ] + + run storage --debug=false unmount $container + [ "$status" -eq 0 ] + [ "$output" != "" ] +} diff --git a/tests/create-image.bats b/tests/create-image.bats new file mode 100644 index 0000000..c8addcd --- /dev/null +++ b/tests/create-image.bats @@ -0,0 +1,54 @@ +#!/usr/bin/env bats + +load helpers + +@test "create-image" { + # Create an image using no layer. + run storage --debug=false create-image "" + [ "$status" -eq 0 ] + [ "$output" != "" ] + zerothimage=${output%% *} + + zerothwriter=$(cat ${TESTDIR}/root/${STORAGE_DRIVER}-images/images.lock) + [ "$zerothwriter" != "" ] + + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + firstimage=${output%% *} + + firstwriter=$(cat ${TESTDIR}/root/${STORAGE_DRIVER}-images/images.lock) + [ "$firstwriter" != "" ] + [ "$zerothwriter" != "$firstwriter" ] + + # Check that the image can be accessed. + storage exists -i $firstimage + + # Create another image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + secondimage=${output%% *} + + # Check that *that* image can be accessed. + storage exists -i $secondimage + + # Check that "images" lists the both of the images. + run storage --debug=false images + [ "$status" -eq 0 ] + echo :"$output": + [ "${#lines[*]}" -eq 3 ] + [ "${lines[0]}" != "${lines[1]}" ] + [ "${lines[1]}" != "${lines[2]}" ] + [ "${lines[0]}" != "${lines[2]}" ] + [ "${lines[0]}" = "$zerothimage" ] || [ "${lines[0]}" = "$firstimage" ] || [ "${lines[0]}" = "$secondimage" ] + [ "${lines[1]}" = "$zerothimage" ] || [ "${lines[1]}" = "$firstimage" ] || [ "${lines[1]}" = "$secondimage" ] + [ "${lines[2]}" = "$zerothimage" ] || [ "${lines[2]}" = "$firstimage" ] || [ "${lines[2]}" = "$secondimage" ] +} diff --git a/tests/create-layer.bats b/tests/create-layer.bats new file mode 100644 index 0000000..af023f4 --- /dev/null +++ b/tests/create-layer.bats @@ -0,0 +1,93 @@ +#!/usr/bin/env bats + +load helpers + +@test "create-layer" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + lowerwriter=$(cat ${TESTDIR}/root/${STORAGE_DRIVER}-layers/layers.lock) + [ "$lowerwriter" != "" ] + # Mount the layer. + run storage --debug=false mount $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + lowermwriter=$(cat ${TESTDIR}/runroot/${STORAGE_DRIVER}-layers/mountpoints.lock) + [ "$lowermwriter" != "" ] + # Put a file in the layer. + createrandom "$lowermount"/layer1file1 + + # Create a second layer based on the first one. + run storage --debug=false create-layer "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + midlayer="$output" + midwriter=$(cat ${TESTDIR}/root/${STORAGE_DRIVER}-layers/layers.lock) + [ "$midwriter" != "" ] + # Mount that layer, too. + run storage --debug=false mount $midlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + midmount="$output" + midmwriter=$(cat ${TESTDIR}/runroot/${STORAGE_DRIVER}-layers/mountpoints.lock) + [ "$midmwriter" != "" ] + # Check that the file from the first layer is there. + test -s "$midmount"/layer1file1 + # Check that we can remove it... + rm -f -v "$midmount"/layer1file1 + # ... and that doing so doesn't affect the first layer. + test -s "$lowermount"/layer1file1 + # Create a new file in this layer. + createrandom "$midmount"/layer2file1 + # Unmount this layer. + storage unmount $midlayer + # Unmount the first layer. + storage unmount $lowerlayer + + # Create a third layer based on the second one. + run storage --debug=false create-layer "$midlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + upperwriter=$(cat ${TESTDIR}/root/${STORAGE_DRIVER}-layers/layers.lock) + [ "$upperwriter" != "" ] + # Mount this layer. + run storage --debug=false mount $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppermount="$output" + uppermwriter=$(cat ${TESTDIR}/runroot/${STORAGE_DRIVER}-layers/mountpoints.lock) + [ "$uppermwriter" != "" ] + # Check that the file we removed from the second layer is still gone. + run test -s "$uppermount"/layer1file1 + [ "$status" -ne 0 ] + # Check that the file we added to the second layer is still there. + test -s "$uppermount"/layer2file1 + # Unmount the third layer. + storage unmount $upperlayer + + # Get a list of the layers, and make sure all three, and no others, are listed. + run storage --debug=false layers + [ "$status" -eq 0 ] + echo :"$output": + [ "${#lines[*]}" -eq 3 ] + [ "${lines[0]}" != "${lines[1]}" ] + [ "${lines[1]}" != "${lines[2]}" ] + [ "${lines[2]}" != "${lines[0]}" ] + [ "${lines[0]}" = "$lowerlayer" ] || [ "${lines[0]}" = "$midlayer" ] || [ "${lines[0]}" = "$upperlayer" ] + [ "${lines[1]}" = "$lowerlayer" ] || [ "${lines[1]}" = "$midlayer" ] || [ "${lines[1]}" = "$upperlayer" ] + [ "${lines[2]}" = "$lowerlayer" ] || [ "${lines[2]}" = "$midlayer" ] || [ "${lines[2]}" = "$upperlayer" ] + + # Check that we updated the layers last-writer consistently. + [ "${lowerwriter}" != "${midwriter}" ] + [ "${lowerwriter}" != "${upperwriter}" ] + [ "${midwriter}" != "${upperwriter}" ] + + # Check that we updated the mountpoints last-writer consistently. + [ "${lowermwriter}" != "${midmwriter}" ] + [ "${lowermwriter}" != "${uppermwriter}" ] + [ "${midmwriter}" != "${uppermwriter}" ] +} diff --git a/tests/delete-container.bats b/tests/delete-container.bats new file mode 100644 index 0000000..d0a927b --- /dev/null +++ b/tests/delete-container.bats @@ -0,0 +1,80 @@ +#!/usr/bin/env bats + +load helpers + +@test "delete-container" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create an image using that layer. + run storage --debug=false create-container $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that the container can be found. + storage exists -c $container + + # Use delete-container to delete it. + storage delete-container $container + + # Check that the container is gone. + run storage exists -c $container + [ "$status" -ne 0 ] +} + +@test "delete-container-with-immutable" { + if [ "$OS" != "FreeBSD" ]; then + skip "not supported on $OS" + fi + + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create an image using that layer. + run storage --debug=false create-container $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that the container can be found. + storage exists -c $container + + run storage --debug=false mount $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + containermount="$output" + + # Create a file and make it immutable + createrandom "$containermount"/file1 + chflags schg "$containermount"/file1 + + run storage --debug=false unmount $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + + # Use delete-container to delete it. + storage delete-container $container + + # Check that the container is gone. + run storage exists -c $container + [ "$status" -ne 0 ] +} diff --git a/tests/delete-image.bats b/tests/delete-image.bats new file mode 100644 index 0000000..99f6d10 --- /dev/null +++ b/tests/delete-image.bats @@ -0,0 +1,27 @@ +#!/usr/bin/env bats + +load helpers + +@test "delete-image" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Check that the image can be found. + storage exists -i $image + + # Use delete-image to delete it. + storage delete-image $image + + # Check that the image is gone. + run storage exists -i $image + [ "$status" -ne 0 ] +} diff --git a/tests/delete-layer.bats b/tests/delete-layer.bats new file mode 100644 index 0000000..202bb89 --- /dev/null +++ b/tests/delete-layer.bats @@ -0,0 +1,121 @@ +#!/usr/bin/env bats + +load helpers + +@test "delete-layer" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer. + run storage --debug=false mount $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + # Create a random file in the layer. + createrandom "$lowermount"/layer1file1 + # Unmount the layer. + storage unmount $lowerlayer + + # Create a second layer based on the first one. + run storage --debug=false create-layer "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + midlayer="$output" + # Mount the second layer. + run storage --debug=false mount $midlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + midmount="$output" + # Make sure the file from the first layer is present in this layer, then remove it. + test -s "$midmount"/layer1file1 + rm -f -v "$midmount"/layer1file1 + # Create a new file in this layer. + createrandom "$midmount"/layer2file1 + # Unmount the second layer. + storage unmount $midlayer + + # Create a third layer based on the second one. + run storage --debug=false create-layer "$midlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + # Mount the third layer. + run storage --debug=false mount $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppermount="$output" + # Make sure the file from the second layer is present in this layer, + # and that the one from the first didn't come back somehow.. + test -s "$uppermount"/layer2file1 + run test -s "$uppermount"/layer1file1 + [ "$status" -ne 0 ] + # Unmount the third layer. + storage unmount $upperlayer + + # Try to delete the first layer, which should fail because it has children. + run storage delete-layer $lowerlayer + [ "$status" -ne 0 ] + # Try to delete the second layer, which should fail because it has children. + run storage delete-layer $midlayer + [ "$status" -ne 0 ] + # Try to delete the third layer, which should succeed because it has no children. + storage delete-layer $upperlayer + # Try to delete the second again, and it should succeed because that child is gone. + storage delete-layer $midlayer + # Try to delete the first again, and it should succeed because that child is gone. + storage delete-layer $lowerlayer +} + +@test "delete-layer-with-mappings" { + case "$STORAGE_DRIVER" in + btrfs|devicemapper|overlay*|vfs|zfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + run storage --debug=false create-layer -r + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + + run storage --debug=false create-layer -r --uidmap 0:100:100000 --gidmap 0:100:100000 $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer2="$output" + + run storage --debug=false create-layer -r --uidmap 0:200:100000 --gidmap 0:200:100000 $lowerlayer2 + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + + # Expect an error as both lower layers are referenced + run storage --debug=false delete-layer $lowerlayer2 + [ "$status" -ne 0 ] + run storage --debug=false delete-layer $lowerlayer + [ "$status" -ne 0 ] + + run storage --debug=false delete-layer $upperlayer + [ "$status" -eq 0 ] + run storage --debug=false delete-layer $lowerlayer2 + [ "$status" -eq 0 ] + + run storage --debug=false create-image $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image="$output" + + # The layer is referenced by the image, it cannot be deleted + run storage --debug=false delete-layer $upperlayer + [ "$status" -ne 0 ] + + run storage --debug=false delete-image $image + [ "$status" -eq 0 ] +} diff --git a/tests/delete.bats b/tests/delete.bats new file mode 100644 index 0000000..5dc79c9 --- /dev/null +++ b/tests/delete.bats @@ -0,0 +1,47 @@ +#!/usr/bin/env bats + +load helpers + +@test "delete" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container based on that image. + run storage --debug=false create-container $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that the container can be found, and delete it using the general delete command. + storage exists -c $container + storage delete $container + + # Check that the container is gone. + run storage exists -c $container + [ "$status" -ne 0 ] + + # Check that the image can be found, and delete it using the general delete command. + storage exists -i $image + storage delete $image + + # Check that the image is gone. + run storage exists -i $image + [ "$status" -ne 0 ] + + # Check that the layer can be found, and delete it using the general delete command. + storage exists -l $layer + storage delete $layer + + # Check that the layer is gone. + run storage exists -l $layer + [ "$status" -ne 0 ] +} diff --git a/tests/diff.bats b/tests/diff.bats new file mode 100644 index 0000000..879752e --- /dev/null +++ b/tests/diff.bats @@ -0,0 +1,38 @@ +#!/usr/bin/env bats + +load helpers + +@test "diff" { + # The checkdiffs function needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + # Create and populate three interesting layers. + populate + + # Mount the layers. + run storage --debug=false mount "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + run storage --debug=false mount "$midlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + midmount="$output" + run storage --debug=false mount "$upperlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppermount="$output" + + # Check the "diff" output. + checkdiffs + + # Unmount the layers. + storage unmount $lowerlayer + storage unmount $midlayer + storage unmount $upperlayer + + # Now check the "diff" again. + checkdiffs +} diff --git a/tests/diffsize.bats b/tests/diffsize.bats new file mode 100644 index 0000000..d1b35ff --- /dev/null +++ b/tests/diffsize.bats @@ -0,0 +1,22 @@ +#!/usr/bin/env bats + +load helpers + +@test "diffsize" { + # Create and populate three interesting layers. + populate + + # Mount the layers. + run storage --debug=false diffsize "$lowerlayer" + [ "$status" -eq 0 ] + echo size:"$output": + [ "$output" -ne 0 ] + run storage --debug=false diffsize "$midlayer" + [ "$status" -eq 0 ] + echo size:"$output": + [ "$output" -ne 0 ] + run storage --debug=false diffsize "$upperlayer" + [ "$status" -eq 0 ] + echo size:"$output": + [ "$output" -ne 0 ] +} diff --git a/tests/helpers.bash b/tests/helpers.bash new file mode 100755 index 0000000..7f4b401 --- /dev/null +++ b/tests/helpers.bash @@ -0,0 +1,332 @@ +#!/usr/bin/env bash + +STORAGE_BINARY=${STORAGE_BINARY:-$(dirname ${BASH_SOURCE})/../containers-storage} +TESTSDIR=${TESTSDIR:-$(dirname ${BASH_SOURCE})} +STORAGE_DRIVER=${STORAGE_DRIVER:-vfs} +STORAGE_TRANSIENT=${STORAGE_TRANSIENT:-0} +STORAGE_OPTION=${STORAGE_OPTION:-} +PATH=$(dirname ${BASH_SOURCE})/..:${PATH} +OS=$(uname -s) +if [ "$STORAGE_TRANSIENT" -eq 1 ]; then + CONTAINERS_LOCK_ROOT=runroot + STORAGE_TRANSIENT_OPT=--transient-store +else + CONTAINERS_LOCK_ROOT=root + STORAGE_TRANSIENT_OPT="" +fi + +# Create a unique root directory and a runroot directory. +function setup() { + suffix=$(dd if=/dev/urandom bs=12 count=1 status=none | base64 | tr +/ABCDEFGHIJKLMNOPQRSTUVWXYZ _.abcdefghijklmnopqrstuvwxyz) + TESTDIR=${BATS_TMPDIR}/tmp.${suffix} + rm -fr ${TESTDIR} + mkdir -p ${TESTDIR}/{root,runroot} + # disable idmapped mounts in the overlay driver, since that + # is the expectation in the idmaps.bats tests. + export _CONTAINERS_OVERLAY_DISABLE_IDMAP=yes +} + +# Delete the unique root directory and a runroot directory. +function teardown() { + run storage wipe + if [[ $status -ne 0 ]] ; then + echo "$output" + fi + run storage shutdown + if [[ $status -ne 0 ]] ; then + echo "$output" + fi + rm -fr ${TESTDIR} +} + +# Create a file "$1" with random contents of length $2, or 256. +function createrandom() { + output=${1:-${BATS_TMPDIR}/randomfile} + dd if=/dev/urandom bs=1 count=${2:-256} of=${output} status=none + # Set the mtime to the epoch so it won't be different once it + # is deduplicated with OSTree + # + # Note: The Linux touch utility can express time as an + # explicit offset, allowing '@0' as a clear way of expressing + # epoch. Unfortunately, the touch utility from BSD derived + # platforms including FreeBSD and darwin is more restrictive + # so we use ISO 8601 format as lowest common denominator. + touch -d 1970-01-01T00:00:00Z ${output} +} + +# Run the CLI with the specified options. +function storage() { + ${STORAGE_BINARY} --debug --graph ${TESTDIR}/root --run ${TESTDIR}/runroot ${STORAGE_TRANSIENT_OPT} --storage-driver ${STORAGE_DRIVER} ${STORAGE_OPTION:+--storage-opt=${STORAGE_OPTION}} "$@" +} + +# Run the CLI with the specified options, and sort its output lines. +function storagewithsorting() { + storage "$@" | LC_ALL=C sort +} + +# Run the CLI with the specified options, and sort its output lines using the second field. +function storagewithsorting2() { + storage "$@" | LC_ALL=C sort -k2 +} + +# Create a few layers with files and directories added and removed at each +# layer. Their IDs are set to $lowerlayer, $midlayer, and $upperlayer. +populate() { + # Create a base layer. + run storage --debug=false create-layer + echo $output + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer. + run storage --debug=false mount $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + local lowermount="$output" + # Create three files, and nine directories: three empty, three with subdirectories, three with files. + createrandom "$lowermount"/layer1file1 + createrandom "$lowermount"/layer1file2 + createrandom "$lowermount"/layer1file3 + mkdir "$lowermount"/layerdir1 + mkdir "$lowermount"/layerdir2 + mkdir "$lowermount"/layerdir3 + mkdir "$lowermount"/layerdir4 + mkdir "$lowermount"/layerdir4/layer1subdir + mkdir "$lowermount"/layerdir5 + mkdir "$lowermount"/layerdir5/layer1subdir + mkdir "$lowermount"/layerdir6 + mkdir "$lowermount"/layerdir6/layer1subdir + mkdir "$lowermount"/layerdir7 + createrandom "$lowermount"/layerdir7/layer1file4 + mkdir "$lowermount"/layerdir8 + createrandom "$lowermount"/layerdir8/layer1file5 + mkdir "$lowermount"/layerdir9 + createrandom "$lowermount"/layerdir9/layer1file6 + # Unmount the layer. + storage unmount $lowerlayer + + # Create a second layer based on the first. + run storage --debug=false create-layer "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + midlayer="$output" + # Mount the second layer. + run storage --debug=false mount $midlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + local midmount="$output" + # Check that the files and directories from the first layer are present. + test -s "$midmount"/layer1file1 + test -s "$midmount"/layer1file2 + test -s "$midmount"/layer1file3 + test -d "$midmount"/layerdir1 + test -d "$midmount"/layerdir2 + test -d "$midmount"/layerdir3 + test -d "$midmount"/layerdir4 + test -d "$midmount"/layerdir4/layer1subdir + test -d "$midmount"/layerdir5 + test -d "$midmount"/layerdir5/layer1subdir + test -d "$midmount"/layerdir6 + test -d "$midmount"/layerdir6/layer1subdir + test -d "$midmount"/layerdir7 + test -s "$midmount"/layerdir7/layer1file4 + test -d "$midmount"/layerdir8 + test -s "$midmount"/layerdir8/layer1file5 + test -d "$midmount"/layerdir9 + test -s "$midmount"/layerdir9/layer1file6 + # Now remove some of those files and directories. + rm "$midmount"/layer1file1 + rm "$midmount"/layer1file2 + rmdir "$midmount"/layerdir1 + rmdir "$midmount"/layerdir2 + rmdir "$midmount"/layerdir4/layer1subdir + rmdir "$midmount"/layerdir4 + rmdir "$midmount"/layerdir5/layer1subdir + rmdir "$midmount"/layerdir5 + rm "$midmount"/layerdir7/layer1file4 + rmdir "$midmount"/layerdir7 + rm "$midmount"/layerdir8/layer1file5 + rmdir "$midmount"/layerdir8 + # Add a couple of new files and directories. + createrandom "$midmount"/layer2file1 + mkdir "$midmount"/layerdir10 + mkdir "$midmount"/layerdir11 + mkdir "$midmount"/layerdir11/layer2subdir + mkdir "$midmount"/layerdir12 + createrandom "$midmount"/layerdir12/layer2file2 + # Unmount the layer. + storage unmount $midlayer + + # Create a third layer based on the second. + run storage --debug=false create-layer "$midlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + # Mount the third layer. + run storage --debug=false mount $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + local uppermount="$output" + # Check that contents of the second layer are present. + test -s "$uppermount"/layer1file3 + test -d "$uppermount"/layerdir3 + test -d "$uppermount"/layerdir6 + test -d "$uppermount"/layerdir6/layer1subdir + test -d "$uppermount"/layerdir9 + test -s "$uppermount"/layerdir9/layer1file6 + test -s "$uppermount"/layer2file1 + test -d "$uppermount"/layerdir10 + test -d "$uppermount"/layerdir11 + test -d "$uppermount"/layerdir11/layer2subdir + test -d "$uppermount"/layerdir12 + test -s "$uppermount"/layerdir12/layer2file2 + # Re-add some contents for this layer that were removed earlier. + createrandom "$uppermount"/layerfile1 + mkdir "$uppermount"/layerdir1 + mkdir "$uppermount"/layerdir4 + mkdir "$uppermount"/layerdir4/layer1subdir + mkdir "$uppermount"/layerdir7 + # Add some new contents, too. + mkdir "$uppermount"/layerdir3/layer3subdir + mkdir "$uppermount"/layerdir3/layer3subdir/layer3subsubdir + createrandom "$uppermount"/layerdir7/layer1file4 + # Unmount the layer. + storage unmount $upperlayer +} + +# Check that the changes list for layers created by populate() correspond to +# what naive diff methods would generate. +checkchanges() { + # The first layer should all be additions. + storage changes $lowerlayer + run storagewithsorting2 --debug=false changes $lowerlayer + [ "$status" -eq 0 ] + echo Changes for layer 1: + echo "$output" + [ "${#lines[*]}" -eq 18 ] + [ "${lines[0]}" = 'Add "/layer1file1"' ] + [ "${lines[1]}" = 'Add "/layer1file2"' ] + [ "${lines[2]}" = 'Add "/layer1file3"' ] + [ "${lines[3]}" = 'Add "/layerdir1"' ] + [ "${lines[4]}" = 'Add "/layerdir2"' ] + [ "${lines[5]}" = 'Add "/layerdir3"' ] + [ "${lines[6]}" = 'Add "/layerdir4"' ] + [ "${lines[7]}" = 'Add "/layerdir4/layer1subdir"' ] + [ "${lines[8]}" = 'Add "/layerdir5"' ] + [ "${lines[9]}" = 'Add "/layerdir5/layer1subdir"' ] + [ "${lines[10]}" = 'Add "/layerdir6"' ] + [ "${lines[11]}" = 'Add "/layerdir6/layer1subdir"' ] + [ "${lines[12]}" = 'Add "/layerdir7"' ] + [ "${lines[13]}" = 'Add "/layerdir7/layer1file4"' ] + [ "${lines[14]}" = 'Add "/layerdir8"' ] + [ "${lines[15]}" = 'Add "/layerdir8/layer1file5"' ] + [ "${lines[16]}" = 'Add "/layerdir9"' ] + [ "${lines[17]}" = 'Add "/layerdir9/layer1file6"' ] + # Check the second layer. + storage changes $midlayer + run storagewithsorting2 --debug=false changes $midlayer + [ "$status" -eq 0 ] + echo Changes for layer 2: + echo "$output" + [ "${#lines[*]}" -eq 14 ] + [ "${lines[0]}" = 'Delete "/layer1file1"' ] + [ "${lines[1]}" = 'Delete "/layer1file2"' ] + [ "${lines[2]}" = 'Add "/layer2file1"' ] + [ "${lines[3]}" = 'Delete "/layerdir1"' ] + [ "${lines[4]}" = 'Add "/layerdir10"' ] + [ "${lines[5]}" = 'Add "/layerdir11"' ] + [ "${lines[6]}" = 'Add "/layerdir11/layer2subdir"' ] + [ "${lines[7]}" = 'Add "/layerdir12"' ] + [ "${lines[8]}" = 'Add "/layerdir12/layer2file2"' ] + [ "${lines[9]}" = 'Delete "/layerdir2"' ] + [ "${lines[10]}" = 'Delete "/layerdir4"' ] + [ "${lines[11]}" = 'Delete "/layerdir5"' ] + [ "${lines[12]}" = 'Delete "/layerdir7"' ] + [ "${lines[13]}" = 'Delete "/layerdir8"' ] + # Check the third layer. + storage changes $upperlayer + run storagewithsorting2 --debug=false changes $upperlayer + [ "$status" -eq 0 ] + echo Changes for layer 3: + echo "$output" + [ "${#lines[*]}" -eq 9 ] + [ "${lines[0]}" = 'Add "/layerdir1"' ] + [ "${lines[1]}" = 'Modify "/layerdir3"' ] + [ "${lines[2]}" = 'Add "/layerdir3/layer3subdir"' ] + [ "${lines[3]}" = 'Add "/layerdir3/layer3subdir/layer3subsubdir"' ] + [ "${lines[4]}" = 'Add "/layerdir4"' ] + [ "${lines[5]}" = 'Add "/layerdir4/layer1subdir"' ] + [ "${lines[6]}" = 'Add "/layerdir7"' ] + [ "${lines[7]}" = 'Add "/layerdir7/layer1file4"' ] + [ "${lines[8]}" = 'Add "/layerfile1"' ] +} + +# Check that the diff contents for layers created by populate() correspond to +# what naive diff methods would generate. +checkdiffs() { + # The first layer should all be additions. + storage diff -u -f $TESTDIR/lower.tar $lowerlayer + tar tf $TESTDIR/lower.tar > $TESTDIR/lower.txt + run env LC_ALL=C sort $TESTDIR/lower.txt + [ "$status" -eq 0 ] + echo Diff contents for layer 1: + echo "$output" + [ "${#lines[*]}" -eq 18 ] + [ "${lines[0]}" = 'layer1file1' ] + [ "${lines[1]}" = 'layer1file2' ] + [ "${lines[2]}" = 'layer1file3' ] + [ "${lines[3]}" = 'layerdir1/' ] + [ "${lines[4]}" = 'layerdir2/' ] + [ "${lines[5]}" = 'layerdir3/' ] + [ "${lines[6]}" = 'layerdir4/' ] + [ "${lines[7]}" = 'layerdir4/layer1subdir/' ] + [ "${lines[8]}" = 'layerdir5/' ] + [ "${lines[9]}" = 'layerdir5/layer1subdir/' ] + [ "${lines[10]}" = 'layerdir6/' ] + [ "${lines[11]}" = 'layerdir6/layer1subdir/' ] + [ "${lines[12]}" = 'layerdir7/' ] + [ "${lines[13]}" = 'layerdir7/layer1file4' ] + [ "${lines[14]}" = 'layerdir8/' ] + [ "${lines[15]}" = 'layerdir8/layer1file5' ] + [ "${lines[16]}" = 'layerdir9/' ] + [ "${lines[17]}" = 'layerdir9/layer1file6' ] + # Check the second layer. + storage diff -c -f $TESTDIR/middle.tar $midlayer + tar tzf $TESTDIR/middle.tar > $TESTDIR/middle.txt + run env LC_ALL=C sort $TESTDIR/middle.txt + [ "$status" -eq 0 ] + echo Diff contents for layer 2: + echo "$output" + [ "${#lines[*]}" -eq 14 ] + [ "${lines[0]}" = '.wh.layer1file1' ] + [ "${lines[1]}" = '.wh.layer1file2' ] + [ "${lines[2]}" = '.wh.layerdir1' ] + [ "${lines[3]}" = '.wh.layerdir2' ] + [ "${lines[4]}" = '.wh.layerdir4' ] + [ "${lines[5]}" = '.wh.layerdir5' ] + [ "${lines[6]}" = '.wh.layerdir7' ] + [ "${lines[7]}" = '.wh.layerdir8' ] + [ "${lines[8]}" = 'layer2file1' ] + [ "${lines[9]}" = 'layerdir10/' ] + [ "${lines[10]}" = 'layerdir11/' ] + [ "${lines[11]}" = 'layerdir11/layer2subdir/' ] + [ "${lines[12]}" = 'layerdir12/' ] + [ "${lines[13]}" = 'layerdir12/layer2file2' ] + # Check the third layer. + storage diff -u -f $TESTDIR/upper.tar $upperlayer + tar tf $TESTDIR/upper.tar > $TESTDIR/upper.txt + run env LC_ALL=C sort $TESTDIR/upper.txt + [ "$status" -eq 0 ] + echo Diff contents for layer 3: + echo "$output" + [ "${#lines[*]}" -eq 9 ] + [ "${lines[0]}" = 'layerdir1/' ] + [ "${lines[1]}" = 'layerdir3/' ] + [ "${lines[2]}" = 'layerdir3/layer3subdir/' ] + [ "${lines[3]}" = 'layerdir3/layer3subdir/layer3subsubdir/' ] + [ "${lines[4]}" = 'layerdir4/' ] + [ "${lines[5]}" = 'layerdir4/layer1subdir/' ] + [ "${lines[6]}" = 'layerdir7/' ] + [ "${lines[7]}" = 'layerdir7/layer1file4' ] + [ "${lines[8]}" = 'layerfile1' ] +} diff --git a/tests/idmaps.bats b/tests/idmaps.bats new file mode 100644 index 0000000..470dd1b --- /dev/null +++ b/tests/idmaps.bats @@ -0,0 +1,1050 @@ +#!/usr/bin/env bats + +load helpers + +@test "idmaps-create-apply-layer" { + # This test needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + btrfs|devicemapper|overlay*|vfs|zfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + + n=5 + host=2 + + # Create some temporary files. + for i in $(seq $n) ; do + createrandom "$TESTDIR"/file$i + chown ${i}:${i} "$TESTDIR"/file$i + ln -s . $TESTDIR/subdir$i + done + # Use them to create some diffs. + pushd $TESTDIR > /dev/null + for i in $(seq $n) ; do + tar cf diff${i}.tar subdir$i/ + done + popd > /dev/null + # Select some ID ranges. + for i in $(seq $n) ; do + uidrange[$i]=$((($RANDOM+32767)*65536)) + gidrange[$i]=$((($RANDOM+32767)*65536)) + done + # Create a layer using the host's mappings. + run storage --debug=false create-layer --hostuidmap --hostgidmap + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer. + run storage --debug=false mount $lowerlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + # Copy the files in (host mapping, so it's fine), and set ownerships on them. + cp -p "$TESTDIR"/file1 ${lowermount} + cp -p "$TESTDIR"/file2 ${lowermount} + cp -p "$TESTDIR"/file3 ${lowermount} + cp -p "$TESTDIR"/file4 ${lowermount} + cp -p "$TESTDIR"/file5 ${lowermount} + + # Create a hard link + createrandom ${lowermount}/origin-file + ln ${lowermount}/origin-file ${lowermount}/ln-file + + # Create new layers. + for i in $(seq $n) ; do + if test $host -ne $i ; then + run storage --debug=false create-layer --uidmap 0:${uidrange[$i]}:$(($n+1)) --gidmap 0:${gidrange[$i]}:$(($n+1)) $lowerlayer + else + uidrange[$host]=0 + gidrange[$host]=0 + run storage --debug=false create-layer --hostuidmap --hostgidmap $lowerlayer + fi + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + run storage --debug=false mount $upperlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppermount="$output" + run storage --debug=false apply-diff $upperlayer < ${TESTDIR}/diff${i}.tar + echo "$output" + [ "$status" -eq 0 ] + [ "$output" = "" ] + + # Verify that the hard link is maintained + origin_ino=$(stat -c %i ${uppermount}/origin-file) + ln_ino=$(stat -c %i ${uppermount}/ln-file) + echo test ${origin_ino} = ${ln_ino} + test ${origin_ino} = ${ln_ino} + + for j in $(seq $n) ; do + # Check the inherited original files. + cmp ${uppermount}/file$j "$TESTDIR"/file$j + uid=$(stat -c %u ${uppermount}/file$j) + gid=$(stat -c %g ${uppermount}/file$j) + echo test found ${uid}:${gid} = expected $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) for file$j + test ${uid}:${gid} = $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) + # Check the inherited/current layer's diff files. + for k in $(seq $i) ; do + cmp ${uppermount}/subdir$k/file$j "$TESTDIR"/file$j + uid=$(stat -c %u ${uppermount}/subdir$k/file$j) + gid=$(stat -c %g ${uppermount}/subdir$k/file$j) + echo test found ${uid}:${gid} = expected $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) for subdir$k/file$j + test ${uid}:${gid} = $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) + done + done + lowerlayer=$upperlayer + done +} + +@test "idmaps-create-diff-layer" { + # This test needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + btrfs|devicemapper|overlay*|vfs|zfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + n=5 + host=2 + # Create some temporary files. + for i in $(seq $n) ; do + createrandom "$TESTDIR"/file$i + done + # Select some ID ranges. + for i in 0 $(seq $n) ; do + uidrange[$i]=$((($RANDOM+32767)*65536)) + gidrange[$i]=$((($RANDOM+32767)*65536)) + done + # Create a layer using some random mappings. + run storage --debug=false create-layer --uidmap 0:${uidrange[0]}:$(($n+1)) --gidmap 0:${gidrange[0]}:$(($n+1)) + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer. + run storage --debug=false mount $lowerlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + # Copy the files in, and set ownerships on them. + for i in $(seq $n) ; do + cp "$TESTDIR"/file$i ${lowermount} + chown $((${uidrange[0]}+$i)):$((${gidrange[0]}+$i)) ${lowermount}/file$i + done + # Create new layers. + for i in $(seq $n) ; do + if test $host -ne $i ; then + run storage --debug=false create-layer --uidmap 0:${uidrange[$i]}:$(($n+1)) --gidmap 0:${gidrange[$i]}:$(($n+1)) $lowerlayer + else + uidrange[$host]=0 + gidrange[$host]=0 + run storage --debug=false create-layer --hostuidmap --hostgidmap $lowerlayer + fi + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + run storage --debug=false mount $upperlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppermount="$output" + # Change the owner of one file to 0:0. + chown ${uidrange[$i]}:${gidrange[$i]} ${uppermount}/file$i + # Verify that the file is the only thing that shows up in a change list. + run storage --debug=false changes $upperlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + [ "${#lines[*]}" -eq 1 ] + [ "$output" = "Modify \"/file$i\"" ] + # Verify that the file is the only thing that shows up in a diff. + run storage --debug=false diff -f $TESTDIR/diff.tar $upperlayer + echo "$output" + [ "$status" -eq 0 ] + run tar tf $TESTDIR/diff.tar + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + [ "${#lines[*]}" -eq 1 ] + [ "$output" = file$i ] + # Check who owns that file, according to the diff. + mkdir "$TESTDIR"/subdir$i + pushd "$TESTDIR"/subdir$i > /dev/null + run tar xf $TESTDIR/diff.tar + [ "$status" -eq 0 ] + run stat -c %u:%g file$i + [ "$status" -eq 0 ] + [ "$output" = 0:0 ] + popd > /dev/null + lowerlayer=$upperlayer + done +} + +@test "idmaps-create-container" { + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + btrfs|devicemapper|overlay*|vfs|zfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + n=5 + host=2 + # Create some temporary files. + for i in $(seq $n) ; do + createrandom "$TESTDIR"/file$i + done + # Select some ID ranges. + for i in 0 $(seq $(($n+1))) ; do + uidrange[$i]=$((($RANDOM+32767)*65536)) + gidrange[$i]=$((($RANDOM+32767)*65536)) + done + # Create a layer using some random mappings. + run storage --debug=false create-layer --uidmap 0:${uidrange[0]}:$(($n+1)) --gidmap 0:${gidrange[0]}:$(($n+1)) + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer. + run storage --debug=false mount $lowerlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + # Copy the files in, and set ownerships on them. + for i in $(seq $n) ; do + cp "$TESTDIR"/file$i ${lowermount} + chown $((${uidrange[0]}+$i)):$((${gidrange[0]}+$i)) ${lowermount}/file$i + done + # Create new layers. + for i in $(seq $n) ; do + if test $host -ne $i ; then + run storage --debug=false create-layer --uidmap 0:${uidrange[$i]}:$(($n+1)) --gidmap 0:${gidrange[$i]}:$(($n+1)) $lowerlayer + else + uidrange[$host]=0 + gidrange[$host]=0 + run storage --debug=false create-layer --hostuidmap --hostgidmap $lowerlayer + fi + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + run storage --debug=false mount $upperlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppermount="$output" + # Change the owner of one file to 0:0. + chown ${uidrange[$i]}:${gidrange[$i]} ${uppermount}/file$i + # Verify that the file is the only thing that shows up in a change list. + run storage --debug=false changes $upperlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + [ "${#lines[*]}" -eq 1 ] + [ "$output" = "Modify \"/file$i\"" ] + lowerlayer=$upperlayer + done + # Create new containers based on the layer. + imagename=idmappedimage + storage create-image --name=$imagename $lowerlayer + + run storage --debug=false create-container --hostuidmap --hostgidmap $imagename + [ "$status" -eq 0 ] + [ "$output" != "" ] + hostcontainer="$output" + run storage --debug=false mount $hostcontainer + [ "$status" -eq 0 ] + [ "$output" != "" ] + hostmount="$output" + for i in $(seq $n) ; do + run stat -c %u:%g "$hostmount"/file$i + [ "$status" -eq 0 ] + [ "$output" = 0:0 ] + done + + run storage --debug=false create-container --hostuidmap --hostgidmap $imagename + [ "$status" -eq 0 ] + [ "$output" != "" ] + hostcontainer="$output" + run storage --debug=false mount $hostcontainer + [ "$status" -eq 0 ] + [ "$output" != "" ] + hostmount="$output" + for i in $(seq $n) ; do + run stat -c %u:%g "$hostmount"/file$i + [ "$status" -eq 0 ] + [ "$output" = 0:0 ] + done + + run storage --debug=false create-container --uidmap 0:${uidrange[$(($n+1))]}:$(($n+1)) --gidmap 0:${gidrange[$(($n+1))]}:$(($n+1)) $imagename + [ "$status" -eq 0 ] + [ "$output" != "" ] + newmapcontainer="$output" + run storage --debug=false mount $newmapcontainer + [ "$status" -eq 0 ] + [ "$output" != "" ] + newmapmount="$output" + for i in $(seq $n) ; do + run stat -c %u:%g "$newmapmount"/file$i + [ "$status" -eq 0 ] + [ "$output" = ${uidrange[$(($n+1))]}:${gidrange[$(($n+1))]} ] + done + + run storage --debug=false create-container $imagename + [ "$status" -eq 0 ] + [ "$output" != "" ] + defmapcontainer="$output" + run storage --debug=false mount $defmapcontainer + [ "$status" -eq 0 ] + [ "$output" != "" ] + defmapmount="$output" + for i in $(seq $n) ; do + run stat -c %u:%g "$defmapmount"/file$i + [ "$status" -eq 0 ] + [ "$output" = "0:0" ] + done +} + +@test "idmaps-parent-owners" { + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + btrfs|devicemapper|overlay*|vfs|zfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + n=5 + # Create some temporary files. + for i in $(seq $n) ; do + createrandom "$TESTDIR"/file$i + done + # Select some ID ranges. + uidrange=$((($RANDOM+32767)*65536)) + gidrange=$((($RANDOM+32767)*65536)) + # Create a layer using some random mappings. + run storage --debug=false create-layer --uidmap 0:${uidrange}:$(($n+1)) --gidmap 0:${gidrange}:$(($n+1)) + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer="$output" + # Mount the layer. + run storage mount $layer + echo "$output" + [ "$status" -eq 0 ] + # Check who owns the parent directories. + run storage --debug=false layer-parent-owners $layer + echo "$output" + [ "$status" -eq 0 ] + # Assume that except for root and maybe us, there are no other owners of parent directories of our layer. + if ! fgrep -q 'UIDs: [0]' <<< "$output" ; then + fgrep -q 'UIDs: [0, '$(id -u)']' <<< "$output" + fi + if ! fgrep -q 'GIDs: [0]' <<< "$output" ; then + fgrep -q 'GIDs: [0, '$(id -g)']' <<< "$output" + fi + # Create a new container based on the layer. + imagename=idmappedimage + storage create-image --name=$imagename $layer + run storage --debug=false create-container $imagename + [ "$status" -eq 0 ] + [ "$output" != "" ] + container="$output" + # Mount the container. + run storage mount $container + echo "$output" + [ "$status" -eq 0 ] + # Check who owns the parent directories. + run storage --debug=false container-parent-owners $container + [ "$status" -eq 0 ] + cat <<< "$output" | tr '\n' '_' + # Check there are no unmapped IDs + fgrep -q 'UIDs: []' <<< "$output" + fgrep -q 'GIDs: []' <<< "$output" +} + +@test "idmaps-copy" { + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + btrfs|devicemapper|overlay*|vfs|zfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + n=5 + host=2 + # Create some temporary files. + mkdir -p "$TESTDIR"/subdir/subdir2 + for i in 0 $(seq $n) ; do + createrandom "$TESTDIR"/file$i + chown "$i":"$i" "$TESTDIR"/file$i + createrandom "$TESTDIR"/subdir/subdir2/file$i + chown "$i":"$i" "$TESTDIR"/subdir/subdir2/file$i + done + chown "$(($n+1))":"$(($n+1))" "$TESTDIR"/subdir/subdir2 + # Select some ID ranges for ID mappings. + for i in 0 $(seq $(($n+1))) ; do + uidrange[$i]=$((($RANDOM+32767)*65536)) + gidrange[$i]=$((($RANDOM+32767)*65536)) + # Create a layer using some those mappings. + run storage --debug=false create-layer --uidmap 0:${uidrange[$i]}:101 --gidmap 0:${gidrange[$i]}:101 + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer[$i]="$output" + done + # Copy the file in, and check that its ownerships get mapped correctly. + for i in 0 $(seq $n) ; do + run storage copy "$TESTDIR"/file$i ${layer[$i]}:/file$i + echo "$output" + [ "$status" -eq 0 ] + run storage --debug=false mount ${layer[$i]} + echo "$output" + [ "$status" -eq 0 ] + mnt[$i]="$output" + run stat -c "%u:%g" ${mnt[$i]}/file$i + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+$i)) + gid=$((${gidrange[$i]}+$i)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + # Try copying with --chown. + run storage copy --chown 100:100 "$TESTDIR"/file$i ${layer[$i]}:/file$i + echo "$output" + [ "$status" -eq 0 ] + run storage --debug=false mount ${layer[$i]} + echo "$output" + [ "$status" -eq 0 ] + mnt[$i]="$output" + run stat -c "%u:%g" ${mnt[$i]}/file$i + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+100)) + gid=$((${gidrange[$i]}+100)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + done + # Copy the subdirectory, and check that its ownerships and that of its contents get mapped correctly. + for i in 0 $(seq $n) ; do + run storage copy "$TESTDIR"/file$i ${layer[$i]}:/file$i + echo "$output" + [ "$status" -eq 0 ] + run stat -c "%u:%g" ${mnt[$i]}/file$i + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+$i)) + gid=$((${gidrange[$i]}+$i)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + + # Try copying with --chown. + run storage copy --chown 100:100 "$TESTDIR"/file$i ${layer[$i]}:/file$i + echo "$output" + [ "$status" -eq 0 ] + run stat -c "%u:%g" ${mnt[$i]}/file$i + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+100)) + gid=$((${gidrange[$i]}+100)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + + # Try copying a directory tree. + run storage copy "$TESTDIR"/subdir ${layer[$i]}:/subdir + echo "$output" + [ "$status" -eq 0 ] + run stat -c "%u:%g" ${mnt[$i]}/subdir/subdir2/file$i + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+$i)) + gid=$((${gidrange[$i]}+$i)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + run stat -c "%u:%g" ${mnt[$i]}/subdir/subdir2 + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+$n+1)) + gid=$((${gidrange[$i]}+$n+1)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + + # Try copying a directory tree with --chown. + run storage copy --chown 100:100 "$TESTDIR"/subdir ${layer[$i]}:/subdir2 + echo "$output" + [ "$status" -eq 0 ] + run stat -c "%u:%g" ${mnt[$i]}/subdir2/subdir2/file$i + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+100)) + gid=$((${gidrange[$i]}+100)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + run stat -c "%u:%g" ${mnt[$i]}/subdir2/subdir2 + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$i]}+100)) + gid=$((${gidrange[$i]}+100)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + done + + # Copy a file out of a layer, into another one. + run storage copy "$TESTDIR"/file$n ${layer[0]}:/file$n + echo "$output" + [ "$status" -eq 0 ] + run storage copy ${layer[0]}:/file$n ${layer[$n]}:/file$n + echo "$output" + [ "$status" -eq 0 ] + run stat -c "%u:%g" ${mnt[$n]}/file$n + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$n]}+$n)) + gid=$((${gidrange[$n]}+$n)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + + # Try copying a directory tree. + run storage copy ${layer[0]}:/subdir ${layer[$n]}:/subdir + echo "$output" + [ "$status" -eq 0 ] + run stat -c "%u:%g" ${mnt[$n]}/subdir/subdir2/file$n + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$n]}+$n)) + gid=$((${gidrange[$n]}+$n)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] + run stat -c "%u:%g" ${mnt[$n]}/subdir/subdir2 + echo "$output" + [ "$status" -eq 0 ] + uid=$((${uidrange[$n]}+$n+1)) + gid=$((${gidrange[$n]}+$n+1)) + echo comparing "$output" and "$uid:$gid" + [ "$output" == "$uid:$gid" ] +} + +@test "idmaps-create-mapped-image" { + # This test needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + btrfs|devicemapper|overlay*|vfs|zfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + n=5 + host=2 + filelist= + # Create some temporary files. + for i in $(seq $n) ; do + createrandom "$TESTDIR"/file$i + chown ${i}:${i} "$TESTDIR"/file$i + filelist="$filelist file$i" + done + # Select some ID ranges. + for i in $(seq $n) ; do + uidrange[$i]=$((($RANDOM+32767)*65536)) + gidrange[$i]=$((($RANDOM+32767)*65536)) + done + # Create a base layer using the host's mappings. + run storage --debug=false create-layer --hostuidmap --hostgidmap + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + baselayer="$output" + # Create an empty layer blob and apply it to the layer. + dd if=/dev/zero bs=1k count=1 of="$TESTDIR"/layer.empty + run storage --debug=false applydiff -f "$TESTDIR"/layer.empty $baselayer + # Create a layer using the host's mappings. + run storage --debug=false create-layer --hostuidmap --hostgidmap $baselayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Create a layer blob containing the files and apply it to the layer. + tar --directory "$TESTDIR" -cvf "$TESTDIR"/layer.tar $filelist + run storage --debug=false applydiff -f "$TESTDIR"/layer.tar $lowerlayer + # Create an image record for this layer. + run storage --debug=false create-image $lowerlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + image="$output" + echo image:$image + # Check that we can compute the size of the image. + run storage --debug=false image $image + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + size=$(grep ^Size: <<< "$output" | sed 's,^Size: ,,g') + [ "$size" -ne 0 ] + echo size:$size + # Create containers using this image. + containers= + for i in $(seq $n) ; do + if test $host -ne $i ; then + run storage --debug=false create-container --uidmap 0:${uidrange[$i]}:$(($n+1)) --gidmap 0:${gidrange[$i]}:$(($n+1)) $image + else + uidrange[$host]=0 + gidrange[$host]=0 + run storage --debug=false create-container --hostuidmap --hostgidmap $image + fi + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${lines[0]} + containers[$i-1]="$container" + + # Check that the ownerships came out right. + run storage --debug=false mount "$container" + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + mount="$output" + + for j in $(seq $n) ; do + ownerids=$(stat -c %u:%g ${mount}/file$j) + echo on-disk IDs: "$ownerids" + echo expected IDs: $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) + [ "$ownerids" = $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) ] + done + run storage --debug=false unmount "$container" + [ "$status" -eq 0 ] + done + # Each of the containers' layers should have a different parent layer, + # all of which should be a top layer for the image. The containers + # themselves have no contents at this point. + declare -a parents + echo containers list is \"${containers[*]}\" + for container in "${containers[@]}" ; do + run storage --debug=false container $container + echo container "$container":"$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + baseimage=$(grep ^Image: <<< "$output" | sed 's,^Image: ,,g') + echo baseimage:"$baseimage" + [ "$baseimage" = "$image" ] + layer=$(grep ^Layer: <<< "$output" | sed 's,^Layer: ,,g') + echo layer:"$layer" + size=$(grep ^Size: <<< "$output" | sed 's,^Size: ,,g') + [ "$size" -eq 0 ] + echo size:$size + + run storage --debug=false layer $layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + parent=$(grep ^Parent: <<< "$output" | sed 's,^Parent: ,,g') + echo parent:"$parent" + + parents[${#parents[*]}]="$parent" + + run storage --debug=false image $baseimage + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + grep "^Top Layer: $parent" <<< "$output" + done + nparents=$(for p in ${parents[@]} ; do echo $p ; done | sort -u | wc -l) + echo nparents:$nparents + [ $nparents -eq $n ] + + # The image should have five top layers at this point, they should all + # have known sizes, and we should be able to diff them all. + run storage --debug=false image $image + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + tops=$(grep '^Top Layer:' <<< "$output" | sed 's,^Top Layer: ,,g') + echo tops: "$tops" + ntops=$(for p in $tops; do echo $p ; done | sort -u | wc -l) + echo ntops:$ntops + [ $ntops -eq $n ] + for p in $tops; do + rm -f "$TESTDIR"/diff.tar + storage --debug=false diff -u -f "$TESTDIR"/diff.tar "$p" + test -s "$TESTDIR"/diff.tar + expected=$(storage --debug=false layer --json $p | sed -r -e 's|.*"diff-size":([^",]*).*|\1|g') + actual=$(stat -c %s "$TESTDIR"/diff.tar) + echo expected diff size "$expected", got "$actual" + test $actual = $expected + expected=$(storage --debug=false layer --json $p | sed -r -e 's|.*"diff-digest":"?([^",]*).*|\1|g') + actual=sha256:$(sha256sum "$TESTDIR"/diff.tar | sed -e 's, .*,,g') + echo expected diff digest "$expected", got "$actual" + test $actual = $expected + done + + # Create a new layer based on the image. + run storage --debug=false create-layer --hostuidmap --hostgidmap $lowerlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + run storage --debug=false applydiff -f "$TESTDIR"/layer.empty $upperlayer + # Create an image record for the new layer. + run storage --debug=false create-image $upperlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperimage="$output" + echo upperimage:$upperimage + + # Remove the containers and images and check that all of the layers we used got removed. + for container in "${containers[@]}" ; do + run storage --debug=false delete-container $container + done + run storage --debug=false delete-image $image + run storage --debug=false delete-image $upperimage + run storage --debug=false layers + echo "$output" + [ "$status" -eq 0 ] + [ "$output" == "" ] +} + +@test "idmaps-create-mapped-container" { + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "${STORAGE_DRIVER}.imagestore option not supported by driver ${STORAGE_DRIVER}" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + n=5 + host=2 + # Create some temporary files. + for i in $(seq $n) ; do + createrandom "$TESTDIR"/file$i + chown ${i}:${i} "$TESTDIR"/file$i + done + # Select some ID ranges. + for i in $(seq $n) ; do + uidrange[$i]=$((($RANDOM+32767)*65536)) + gidrange[$i]=$((($RANDOM+32767)*65536)) + done + # Create a base layer using the host's mappings. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer --hostuidmap --hostgidmap + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + baselayer="$output" + # Create a layer using the host's mappings. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer --hostuidmap --hostgidmap $baselayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot mount $lowerlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + # Copy the files in (host mapping, so it's fine), and set ownerships on them. + cp -p "$TESTDIR"/file1 ${lowermount} + cp -p "$TESTDIR"/file2 ${lowermount} + cp -p "$TESTDIR"/file3 ${lowermount} + cp -p "$TESTDIR"/file4 ${lowermount} + cp -p "$TESTDIR"/file5 ${lowermount} + # Unmount the layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot unmount $lowerlayer + [ "$status" -eq 0 ] + # Create an image record for this layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image $lowerlayer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + image="$output" + echo image:$image + # Check that we can compute the size of the image. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot image $image + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + size=$(grep ^Size: <<< "$output" | sed 's,^Size: ,,g') + [ "$size" -ne 0 ] + echo size:$size + # Done using this location directly. + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + # Create containers using this image. + containers= + for i in $(seq $n) ; do + if test $host -ne $i ; then + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-container --uidmap 0:${uidrange[$i]}:$(($n+1)) --gidmap 0:${gidrange[$i]}:$(($n+1)) $image + else + uidrange[$host]=0 + gidrange[$host]=0 + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root create-container --hostuidmap --hostgidmap $image + fi + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${lines[0]} + containers[$i-1]="$container" + + # Check that the ownerships came out right. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root mount "$container" + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + mount="$output" + + uid=$(stat -c %u ${mount}) + gid=$(stat -c %g ${mount}) + test ${uid}:${gid} = ${uidrange[$i]}:${gidrange[$i]} + + for j in $(seq $n) ; do + ownerids=$(stat -c %u:%g ${mount}/file$j) + echo on-disk IDs: "$ownerids" + echo expected IDs: $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) + [ "$ownerids" = $((${uidrange[$i]}+$j)):$((${gidrange[$i]}+$j)) ] + done + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root unmount "$container" + [ "$status" -eq 0 ] + done + # Each of the containers' layers should have the same parent layer, + # which should be the lone top layer for the image. The containers + # themselves have no contents at this point. + declare -a parents + echo containers list is \"${containers[*]}\" + for container in "${containers[@]}" ; do + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root container $container + echo container "$container":"$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + baseimage=$(grep ^Image: <<< "$output" | sed 's,^Image: ,,g') + echo baseimage:"$baseimage" + [ "$baseimage" = "$image" ] + layer=$(grep ^Layer: <<< "$output" | sed 's,^Layer: ,,g') + echo layer:"$layer" + size=$(grep ^Size: <<< "$output" | sed 's,^Size: ,,g') + [ "$size" -eq 0 ] + echo size:$size + + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layer $layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + parent=$(grep ^Parent: <<< "$output" | sed 's,^Parent: ,,g') + echo parent:"$parent" + + parents[${#parents[*]}]="$parent" + + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root image $baseimage + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + grep "^Top Layer: $parent" <<< "$output" + done + nparents=$(for p in ${parents[@]} ; do echo $p ; done | sort -u | wc -l) + echo nparents:$nparents + [ $nparents -eq 1 ] + + # The image should still have only one top layer at this point. + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root image $image + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + tops=$(grep '^Top Layer:' <<< "$output" | sed 's,^Top Layer: ,,g') + ntops=$(for p in $tops; do echo $p ; done | sort -u | wc -l) + echo ntops:$ntops + [ $ntops -eq 1 ] + + # Remove the containers and image and check that all of the layers we used got removed. + for container in "${containers[@]}" ; do + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root delete-container $container + done + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot delete-image $image + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + run storage --debug=false --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layers + echo "$output" + [ "$status" -eq 0 ] + [ "$output" == "" ] +} + +@test "idmaps-create-mapped-container-shifting" { + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + overlay*) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + + # Create a base layer. + run storage --debug=false create-layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + baselayer="$output" + # Create the lower layer. + run storage --debug=false create-layer $baselayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer. + run storage --debug=false mount $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + # Put a file in the layer. + createrandom "$lowermount"/file + storage unmount $lowerlayer + + imagename=idmappedimage-shifting + storage create-image --name=$imagename $lowerlayer +} + +@test "idmaps-create-layer-from-another-image-store" { + # This test needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + if [ "$OS" != "Linux" ]; then + skip "not supported on $OS" + fi + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip ".imagestore option not supported by driver ${STORAGE_DRIVER}" + ;; + esac + case "$STORAGE_OPTION" in + *mount_program*) + skip "test not supported when using mount_program" + ;; + esac + + n=5 + host=2 + # Create some temporary files. + for i in $(seq $n) ; do + createrandom "$TESTDIR"/file$i + chown ${i}:${i} "$TESTDIR"/file$i + ln -s . $TESTDIR/subdir$i + done + # Use them to create some diffs. + pushd $TESTDIR > /dev/null + for i in $(seq $n) ; do + tar cf diff${i}.tar subdir$i/ + done + popd > /dev/null + + # Create a layer using the host's mappings. + run storage --graph=$TESTDIR/imagestore --debug=false create-layer --hostuidmap --hostgidmap + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer="$output" + + run storage --graph=$TESTDIR/imagestore --debug=false create-image $layer + echo "$output" + [ "$status" -eq 0 ] + + run storage --graph=$TESTDIR/newstore --storage-opt=.imagestore=$TESTDIR/imagestore --debug=false create-image $layer + echo "$output" + [ "$status" -eq 0 ] + image="$output" + + for i in 0 $(seq $n) ; do + uidrange[$i]=$((($RANDOM+32767)*65536)) + gidrange[$i]=$((($RANDOM+32767)*65536)) + done + + run storage --graph=$TESTDIR/newstore --storage-opt=.imagestore=$TESTDIR/imagestore --debug=false create-container --uidmap 0:${uidrange[0]}:$(($n+1)) --gidmap 0:${gidrange[0]}:$(($n+1)) $image + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + + storage --graph ${TESTDIR}/imagestore shutdown + storage --graph ${TESTDIR}/newstore shutdown +} diff --git a/tests/image-by-digest.bats b/tests/image-by-digest.bats new file mode 100644 index 0000000..465aa9e --- /dev/null +++ b/tests/image-by-digest.bats @@ -0,0 +1,113 @@ +#!/usr/bin/env bats + +load helpers + +@test "images-by-digest" { + # Bail if "sha256sum" isn't available. + if test -z "$(which sha256sum 2> /dev/null)" ; then + skip "need sha256sum" + fi + + # Create a couple of random files. + createrandom ${TESTDIR}/random1 + createrandom ${TESTDIR}/random2 + createrandom ${TESTDIR}/random3 + digest1=$(sha256sum ${TESTDIR}/random1) + digest2=$(sha256sum ${TESTDIR}/random2) + digest3=$(sha256sum ${TESTDIR}/random3) + + # Create a layer. + run storage --debug=false create-layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image using that layer. + run storage --debug=false create-image $layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + firstimage=${output%% *} + # Set the first file as the manifest of this image. + run storage --debug=false set-image-data -f ${TESTDIR}/random1 ${firstimage} manifest + echo "$output" + + # Create another image using that layer. + run storage --debug=false create-image $layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + secondimage=${output%% *} + # Set the first file as the manifest of this image. + run storage --debug=false set-image-data -f ${TESTDIR}/random1 ${secondimage} manifest + echo "$output" + + # Create yet another image using that layer. + run storage --debug=false create-image $layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + thirdimage=${output%% *} + # Set the second file as the manifest of this image. + run storage --debug=false set-image-data -f ${TESTDIR}/random2 ${thirdimage} manifest + echo "$output" + + # Create still another image using that layer. + run storage --debug=false create-image --digest sha256:${digest3// *} $layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + fourthimage=${output%% *} + + # Create another image using that layer. + run storage --debug=false create-image --digest sha256:${digest3// *} $layer + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + fifthimage=${output%% *} + # Set the third file as the manifest of this image. + run storage --debug=false set-image-data -f ${TESTDIR}/random3 ${fifthimage} manifest + echo "$output" + + # Check that "images-by-digest" lists the right images. + run storage --debug=false images-by-digest --quiet sha256:${digest1// *} + echo "$output" + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 2 ] + [ "${lines[0]}" != "${lines[1]}" ] + [ "${lines[0]}" = "$firstimage" ] || [ "${lines[0]}" = "$secondimage" ] + [ "${lines[1]}" = "$firstimage" ] || [ "${lines[1]}" = "$secondimage" ] + + run storage --debug=false images-by-digest --quiet sha256:${digest2// *} + echo "$output" + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 1 ] + [ "${lines[0]}" = "$thirdimage" ] + + run storage --debug=false images-by-digest --quiet sha256:${digest3// *} + echo "$output" + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 2 ] + [ "${lines[0]}" = "$fourthimage" ] || [ "${lines[0]}" = "$fifthimage" ] + [ "${lines[1]}" = "$fourthimage" ] || [ "${lines[1]}" = "$fifthimage" ] + + run storage --debug=false delete-image ${secondimage} + echo "$output" + [ "$status" -eq 0 ] + + run storage --debug=false images-by-digest --quiet sha256:${digest1// *} + echo "$output" + [ "$status" -eq 0 ] + [ "${#lines[*]}" -eq 1 ] + [ "${lines[0]}" = "$firstimage" ] + + run storage --debug=false delete-image ${firstimage} + echo "$output" + [ "$status" -eq 0 ] + + run storage --debug=false images-by-digest --quiet sha256:${digest1// *} + echo "$output" + [ "$status" -eq 0 ] + [ "$output" = "" ] +} diff --git a/tests/image.bats b/tests/image.bats new file mode 100644 index 0000000..d38607f --- /dev/null +++ b/tests/image.bats @@ -0,0 +1,56 @@ +#!/usr/bin/env bats + +load helpers + +@test "image" { + # Create and populate three interesting layers. + populate + + # Create an image using to top layer. + name=wonderful-image + run storage --debug=false create-image --name $name $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${lines[0]} + + # Add a couple of big data items. + createrandom ${TESTDIR}/random1 + createrandom ${TESTDIR}/random2 + storage set-image-data -f ${TESTDIR}/random1 $image random1 + storage set-image-data -f ${TESTDIR}/random2 $image random2 + + # Get information about the image, and make sure the ID, name, and data names were preserved. + run storage image $image + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "ID: $image" ]] + [[ "$output" =~ "Name: $name" ]] + [[ "$output" =~ "Data: random1" ]] + [[ "$output" =~ "Data: random2" ]] +} + +@test "layerless-image" { + # Add an image with no specified layers. + name=wonderful-image + run storage --debug=false create-image --name $name + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${lines[0]} + + # Add a couple of big data items. + createrandom ${TESTDIR}/random1 + createrandom ${TESTDIR}/random2 + storage set-image-data -f ${TESTDIR}/random1 $image random1 + storage set-image-data -f ${TESTDIR}/random2 $image random2 + + # Get information about the image, and make sure the ID, name, and data names were preserved, + # and that we can properly report its disk usage. + run storage image $image + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "ID: $image" ]] + [[ "$output" =~ "Name: $name" ]] + [[ "$output" =~ "Data: random1" ]] + [[ "$output" =~ "Data: random2" ]] + [[ "$output" =~ "Size: 512" ]] +} diff --git a/tests/import-layer.bats b/tests/import-layer.bats new file mode 100644 index 0000000..ee33e38 --- /dev/null +++ b/tests/import-layer.bats @@ -0,0 +1,136 @@ +#!/usr/bin/env bats + +load helpers + +@test "import-layer" { + # The checkdiffs function needs "tar". + if test -z "$(which tar 2> /dev/null)" ; then + skip "need tar" + fi + + # Create and populate three interesting layers. + populate + + # Extract the layers. + storage diff -u -f $TESTDIR/lower.tar $lowerlayer + storage diff -c -f $TESTDIR/middle.tar $midlayer + storage diff -u -f $TESTDIR/upper.tar $upperlayer + + # Delete the layers. + storage delete-layer $upperlayer + storage delete-layer $midlayer + storage delete-layer $lowerlayer + + # Import new layers using the layer diffs. + run storage --debug=false import-layer -f $TESTDIR/lower.tar + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + + run storage --debug=false import-layer -f $TESTDIR/middle.tar "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + midlayer="$output" + + run storage --debug=false import-layer -f $TESTDIR/upper.tar "$midlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + + # The contents of these new layers should match what the old ones had. + checkchanges + checkdiffs +} + +set_immutable() { + chflags schg $1 +} + +reset_immutable() { + chflags noschg $1 +} + +is_immutable() { + local flags=$(stat -f %#Xf $1) + [ "$((($flags & 0x20000) == 0x20000))" -ne 0 ] +} + +@test "import-layer-with-immutable" { + if [ "$OS" != "FreeBSD" ]; then + skip "not supported on $OS" + fi + + # Create a layer with a directory containing two files, both + # immutable. The directory is also set as immutablr. + run storage --debug=false create-layer + echo $output + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + run storage --debug=false mount $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + local m="$output" + mkdir $m/dir + createrandom $m/dir/layer1file1 + createrandom $m/dir/layer1file2 + set_immutable $m/dir/layer1file1 + set_immutable $m/dir/layer1file2 + set_immutable $m/dir + storage unmount $lowerlayer + + # Create a second layer which deletes one file and removes immutable from the other + run storage --debug=false create-layer "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + run storage --debug=false mount $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + m="$output" + reset_immutable $m/dir + reset_immutable $m/dir/layer1file1 + rm $m/dir/layer1file1 + reset_immutable $m/dir/layer1file2 + set_immutable $m/dir + storage unmount $upperlayer + + # Extract the layers. + storage diff -u -f $TESTDIR/lower.tar $lowerlayer + storage diff -u -f $TESTDIR/upper.tar $upperlayer + + # Delete the layers. + storage delete-layer $upperlayer + storage delete-layer $lowerlayer + + # Import new layers using the layer diffs. + run storage --debug=false import-layer -f $TESTDIR/lower.tar + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + + run storage --debug=false import-layer -f $TESTDIR/upper.tar "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + + # Verify layer contents + run storage --debug=false mount $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + m="$output" + is_immutable $m/dir/layer1file1 + is_immutable $m/dir/layer1file2 + storage unmount $lowerlayer + + run storage --debug=false mount $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + m="$output" + [ ! -f $m/dir/layer1file1 ] + ! is_immutable $m/dir/layer1file2 + storage unmount $upperlayer + + storage delete-layer $upperlayer + storage delete-layer $lowerlayer +} diff --git a/tests/layers.bats b/tests/layers.bats new file mode 100644 index 0000000..80ec896 --- /dev/null +++ b/tests/layers.bats @@ -0,0 +1,58 @@ +#!/usr/bin/env bats +# vim:set syn=bash: + +load helpers + +@test "allow storing images with more than 127 layers" { + LAYER="" + LIMIT=300 + for i in $(seq 0 ${LIMIT}); do + echo "Layer: $i" + + # Create a layer. + run storage --debug=false create-layer "$LAYER" + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + LAYER="$output" + run storage --debug=false mount "$LAYER" + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + ROOTFS="$output" + touch "${ROOTFS}"/$i + run storage --debug=false unmount "$LAYER" + echo "$output" + [ "$status" -eq 0 ] + done + + # Create the image + run storage --debug=false create-image "$LAYER" + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + IMAGE="$output" + + # Make sure the image has all of the content. + run storage --debug=false create-container "$IMAGE" + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + CONTAINER="$output" + + run storage --debug=false mount "$CONTAINER" + echo "$output" + [ "$status" -eq 0 ] + [ "$output" != "" ] + ROOTFS="$output" + for i in $(seq 0 ${LIMIT}); do + if ! test -r "${ROOTFS}"/$i ; then + echo File from layer $i of ${LIMIT} was not visible after mounting + false + fi + done + + run storage --debug=false unmount "$CONTAINER" + echo "$output" + [ "$status" -eq 0 ] +} diff --git a/tests/manifests.bats b/tests/manifests.bats new file mode 100644 index 0000000..1985d1f --- /dev/null +++ b/tests/manifests.bats @@ -0,0 +1,67 @@ +#!/usr/bin/env bats + +load helpers + +@test "manifests" { + # Create and populate three interesting layers. + populate + + # Create an image using the top layer. + name=wonderful-image + run storage --debug=false create-image --name $name $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${lines[0]} + + # Add a couple of big data items as manifests. + createrandom ${TESTDIR}/random1 + createrandom ${TESTDIR}/random2 + createrandom ${TESTDIR}/random3 + digest1=$(sha256sum ${TESTDIR}/random1) + digest1=${digest1// *} + digest2=$(sha256sum ${TESTDIR}/random2) + digest2=${digest2// *} + digest3=$(sha256sum ${TESTDIR}/random3) + digest3=${digest3// *} + storage set-image-data -f ${TESTDIR}/random1 $image manifest + storage set-image-data -f ${TESTDIR}/random2 $image manifest-random2 + storage set-image-data -f ${TESTDIR}/random3 $image manifest-random3 + storage add-names --name localhost/fooimage:latest $image + + # Get information about the image, and make sure the ID, name, and data names were preserved. + run storage image $image + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "ID: $image" ]] + [[ "$output" =~ "Name: $name" ]] + [[ "$output" =~ "Digest: sha256:$digest1" ]] + [[ "$output" =~ "Digest: sha256:$digest2" ]] + [[ "$output" =~ "Digest: sha256:$digest3" ]] + + run storage images-by-digest sha256:$digest1 + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "$image" ]] + [[ "$output" =~ "name: $name" ]] + [[ "$output" =~ "digest: sha256:$digest1" ]] + [[ "$output" =~ "digest: sha256:$digest2" ]] + [[ "$output" =~ "digest: sha256:$digest3" ]] + + run storage images-by-digest sha256:$digest2 + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "$image" ]] + [[ "$output" =~ "name: $name" ]] + [[ "$output" =~ "digest: sha256:$digest1" ]] + [[ "$output" =~ "digest: sha256:$digest2" ]] + [[ "$output" =~ "digest: sha256:$digest3" ]] + + run storage images-by-digest sha256:$digest3 + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "$image" ]] + [[ "$output" =~ "name: $name" ]] + [[ "$output" =~ "digest: sha256:$digest1" ]] + [[ "$output" =~ "digest: sha256:$digest2" ]] + [[ "$output" =~ "digest: sha256:$digest3" ]] +} diff --git a/tests/metadata.bats b/tests/metadata.bats new file mode 100644 index 0000000..eb2aabd --- /dev/null +++ b/tests/metadata.bats @@ -0,0 +1,137 @@ +#!/usr/bin/env bats + +load helpers + +@test "metadata" { + echo danger > $TESTDIR/danger.txt + + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Make sure the layer's there. + storage exists -l $layer + + # Create an image using the layer and directly-supplied metadata. + run storage --debug=false create-image -m danger $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Make sure that the image is there. + storage exists -i $image + + # Read back the metadata and make sure it's the right value. + run storage --debug=false metadata -q $image + [ "$status" -eq 0 ] + [ "$output" = "danger" ] + + # Change the metadata to a directly-supplied value. + run storage set-metadata -m thunder $image + [ "$status" -eq 0 ] + + # Read back the metadata and make sure it's the new value. + run storage --debug=false metadata -q $image + [ "$status" -eq 0 ] + [ "$output" = "thunder" ] + + # Change the metadata to a value supplied via a file. + storage set-metadata -f $TESTDIR/danger.txt $image + + # Read back the metadata and make sure it's the newer value. + run storage --debug=false metadata -q $image + [ "$status" -eq 0 ] + [ "$output" = "danger" ] + + # Create an image using the layer and metadata read from a file. + run storage --debug=false create-image -f $TESTDIR/danger.txt $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Make sure that the image is there. + storage exists -i $image + + # Read back the metadata and make sure it's the right value. + run storage --debug=false metadata -q $image + [ "$status" -eq 0 ] + [ "$output" = "danger" ] + + # Change the metadata to a directly-supplied value. + storage set-metadata -m thunder $image + + # Read back the metadata and make sure it's the new value. + run storage --debug=false metadata -q $image + [ "$status" -eq 0 ] + [ "$output" = "thunder" ] + + # Change the metadata to a value supplied via a file. + storage set-metadata -f $TESTDIR/danger.txt $image + + # Read back the metadata and make sure it's the newer value. + run storage --debug=false metadata -q $image + [ "$status" -eq 0 ] + [ "$output" = "danger" ] + + # Create a container based on the image and directly-supplied metadata. + run storage --debug=false create-container -m danger $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Make sure the container is there. + storage exists -c $container + + # Read the metadata and make sure it's the right value. + run storage --debug=false metadata -q $container + [ "$status" -eq 0 ] + [ "$output" = "danger" ] + + # Change the metadata to a new value. + storage set-metadata -m thunder $container + + # Read back the new metadata value. + run storage --debug=false metadata -q $container + [ "$status" -eq 0 ] + [ "$output" = "thunder" ] + + # Change the metadata to a new value read from a file. + storage set-metadata -f $TESTDIR/danger.txt $container + + # Read back the newer metadata value. + run storage --debug=false metadata -q $container + [ "$status" -eq 0 ] + [ "$output" = "danger" ] + + # Create a container based on the image and metadata read from a file. + run storage --debug=false create-container -f $TESTDIR/danger.txt $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Make sure the container is there. + storage exists -c $container + + # Read the metadata and make sure it's the right value. + run storage --debug=false metadata -q $container + [ "$status" -eq 0 ] + [ "$output" = "danger" ] + + # Change the metadata to a new value. + storage set-metadata -m thunder $container + + # Read back the new metadata value. + run storage --debug=false metadata -q $container + [ "$status" -eq 0 ] + [ "$output" = "thunder" ] + + # Change the metadata to a new value read from a file. + storage set-metadata -f $TESTDIR/danger.txt $container + + # Read back the newer metadata value. + run storage --debug=false metadata -q $container + [ "$status" -eq 0 ] + [ "$output" = "danger" ] +} diff --git a/tests/mount-layer.bats b/tests/mount-layer.bats new file mode 100644 index 0000000..2508436 --- /dev/null +++ b/tests/mount-layer.bats @@ -0,0 +1,85 @@ +#!/usr/bin/env bats + +load helpers + +@test "mount-layer" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer="$output" + + # Mount the layer. + run storage --debug=false mount $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + # Check if layer is mounted. + run storage --debug=false mounted $layer + [ "$status" -eq 0 ] + [ "$output" == "$layer mounted" ] + # Unmount the layer. + run storage --debug=false unmount $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + # Make sure layer is not mounted. + run storage --debug=false mounted $layer + [ "$status" -eq 0 ] + [ "$output" == "" ] + + # Mount the layer twice. + run storage --debug=false mount $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + run storage --debug=false mount $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + # Check if layer is mounted. + run storage --debug=false mounted $layer + [ "$status" -eq 0 ] + [ "$output" == "$layer mounted" ] + # Unmount the second layer. + run storage --debug=false unmount $layer + [ "$status" -eq 0 ] + [ "$output" == "" ] + # Check if layer is mounted. + run storage --debug=false mounted $layer + [ "$status" -eq 0 ] + [ "$output" == "$layer mounted" ] + # Unmount the first layer. + run storage --debug=false unmount $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + # Make sure layer is not mounted. + run storage --debug=false mounted $layer + [ "$status" -eq 0 ] + [ "$output" == "" ] + + + # Mount the layer twice and force umount. + run storage --debug=false mount $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + run storage --debug=false mount $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + # Check if layer is mounted. + run storage --debug=false mounted $layer + [ "$status" -eq 0 ] + [ "$output" == "$layer mounted" ] + # Unmount all layers. + run storage --debug=false unmount --force $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + # Make sure no layers are mounted. + run storage --debug=false mounted $layer + [ "$status" -eq 0 ] + [ "$output" == "" ] + + # Mount the layer with nosuid + run storage --debug=false mount --option nosuid $layer + [ "$status" -ne 0 ] + + # Delete the first layer + run storage delete-layer $layer + [ "$status" -eq 0 ] +} diff --git a/tests/names.bats b/tests/names.bats new file mode 100644 index 0000000..0d8779f --- /dev/null +++ b/tests/names.bats @@ -0,0 +1,722 @@ +#!/usr/bin/env bats + +load helpers + +# Helper function to scan the list of names of an item for a particular value. +check-for-name() { + name="$1" + shift + run storage --debug=false get-names "$@" + [ "$status" -eq 0 ] + [[ "$output" =~ "$name" ]] +} + +@test "names at creation: layers" { + # Create a layer with no name. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer=$output + + # Verify that the layer exists and can be found by ID. + run storage exists -l $lowerlayer + [ "$status" -eq 0 ] + # Verify that these three names don't appear to be assigned. + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -ne 0 ] + run storage exists -l barlayer + [ "$status" -ne 0 ] + + # Create a new layer and give it two of the above-mentioned names. + run storage --debug=false create-layer -n foolayer -n barlayer $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer=${output%% *} + + # Verify that the new layer exists and can be found by its ID. + run storage exists -l $upperlayer + [ "$status" -eq 0 ] + # Verify that two of the names we checked earlier are now assigned, and to the new layer. + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -eq 0 ] + run storage exists -l barlayer + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $upperlayer + [ "$status" -ne 0 ] + run check-for-name foolayer $upperlayer + [ "$status" -eq 0 ] + run check-for-name barlayer $upperlayer + [ "$status" -eq 0 ] +} + +@test "add-names: layers" { + # Create a layer with no name. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer=$output + + # Verify that we can find the layer by its ID. + run storage exists -l $lowerlayer + [ "$status" -eq 0 ] + + # Check that these three names are not currently assigned. + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -ne 0 ] + run storage exists -l barlayer + [ "$status" -ne 0 ] + + # Create a new layer with names. + run storage --debug=false create-layer -n foolayer -n barlayer $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer=${output%% *} + + # Add names to the new layer. + run storage add-names -n newlayer -n otherlayer $upperlayer + [ "$status" -eq 0 ] + + # Verify that we can find the new layer by its ID. + run storage exists -l $upperlayer + [ "$status" -eq 0 ] + # Verify that the name we didn't assign is still unassigned, and that the two names we + # started with, along with the two we added, are assigned, to the new layer. + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -eq 0 ] + run storage exists -l barlayer + [ "$status" -eq 0 ] + run storage exists -l newlayer + [ "$status" -eq 0 ] + run storage exists -l otherlayer + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $upperlayer + [ "$status" -ne 0 ] + run check-for-name foolayer $upperlayer + [ "$status" -eq 0 ] + run check-for-name barlayer $upperlayer + [ "$status" -eq 0 ] + run check-for-name newlayer $upperlayer + [ "$status" -eq 0 ] + run check-for-name otherlayer $upperlayer + [ "$status" -eq 0 ] +} + +@test "set-names: layers" { + # Create a layer with no name. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer=$output + + # Verify that we can find the layer by its ID. + run storage exists -l $lowerlayer + [ "$status" -eq 0 ] + + # Check that these three names are not currently assigned. + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -ne 0 ] + run storage exists -l barlayer + [ "$status" -ne 0 ] + + # Create a new layer with two names. + run storage --debug=false create-layer -n foolayer -n barlayer $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer=${output%% *} + + # Assign a list of two names to the layer, which should remove its other names. + run storage set-names -n newlayer -n otherlayer $upperlayer + [ "$status" -eq 0 ] + + # Check that the old names are not assigned at all, but the new names are, to it. + run storage exists -l $upperlayer + [ "$status" -eq 0 ] + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -ne 0 ] + run storage exists -l barlayer + [ "$status" -ne 0 ] + run storage exists -l newlayer + [ "$status" -eq 0 ] + run storage exists -l otherlayer + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $upperlayer + [ "$status" -ne 0 ] + run check-for-name foolayer $upperlayer + [ "$status" -ne 0 ] + run check-for-name barlayer $upperlayer + [ "$status" -ne 0 ] + run check-for-name newlayer $upperlayer + [ "$status" -eq 0 ] + run check-for-name otherlayer $upperlayer + [ "$status" -eq 0 ] +} + +@test "move-names: layers" { + # Create a layer with no name. + run storage --debug=false create-layer -n foolayer -n barlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer=${output%% *} + + # Verify that we can find the layer by its ID. + run storage exists -l $lowerlayer + [ "$status" -eq 0 ] + + # Check that these three names are not currently assigned. + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -eq 0 ] + run storage exists -l barlayer + [ "$status" -eq 0 ] + + # Create another layer with no names. + run storage --debug=false create-layer $lowerlayer + [ "$status" -eq 0 ] + upperlayer=${output%% *} + + # Set names on that new layer, which should remove the names from the old one. + run storage set-names -n foolayer -n barlayer $upperlayer + [ "$status" -eq 0 ] + + # Verify that we can find the layer by its ID, and that the two names exist. + run storage exists -l $upperlayer + [ "$status" -eq 0 ] + run storage exists -l no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -l foolayer + [ "$status" -eq 0 ] + run storage exists -l barlayer + [ "$status" -eq 0 ] + + # Check that the names are attached to the new layer and not the old one. + run check-for-name foolayer $lowerlayer + [ "$status" -ne 0 ] + run check-for-name barlayer $lowerlayer + [ "$status" -ne 0 ] + run check-for-name foolayer $upperlayer + [ "$status" -eq 0 ] + run check-for-name barlayer $upperlayer + [ "$status" -eq 0 ] +} + +@test "names at creation: images" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image with names that uses that layer. + run storage --debug=false create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Check that we can find that image by ID and by its names. + run storage exists -i $image + [ "$status" -eq 0 ] + run storage exists -i no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -i fooimage + [ "$status" -eq 0 ] + run storage exists -i barimage + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $image + [ "$status" -ne 0 ] + run check-for-name fooimage $image + [ "$status" -eq 0 ] + run check-for-name barimage $image + [ "$status" -eq 0 ] +} + +@test "add-names: images" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image with names that uses that layer. + run storage --debug=false create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Check that we can find that image by ID and by its names. + run storage exists -i $image + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $image + [ "$status" -ne 0 ] + run check-for-name fooimage $image + [ "$status" -eq 0 ] + run check-for-name barimage $image + [ "$status" -eq 0 ] + + # Add two names to the image. + run storage add-names -n newimage -n otherimage $image + [ "$status" -eq 0 ] + + # Check that all of the names are now assigned. + run storage exists -i no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -i fooimage + [ "$status" -eq 0 ] + run storage exists -i barimage + [ "$status" -eq 0 ] + run storage exists -i newimage + [ "$status" -eq 0 ] + run storage exists -i otherimage + [ "$status" -eq 0 ] + + # Check that all of the names are now assigned to this image. + run check-for-name no-such-thing-as-this-name $image + [ "$status" -ne 0 ] + run check-for-name fooimage $image + [ "$status" -eq 0 ] + run check-for-name barimage $image + [ "$status" -eq 0 ] + run check-for-name newimage $image + [ "$status" -eq 0 ] + run check-for-name otherimage $image + [ "$status" -eq 0 ] +} + +@test "set-names: images" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image with names that uses that layer. + run storage --debug=false create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Check that we can find that image by ID and by its names. + run storage exists -i $image + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $image + [ "$status" -ne 0 ] + run check-for-name fooimage $image + [ "$status" -eq 0 ] + run check-for-name barimage $image + [ "$status" -eq 0 ] + + # Set the names for the image to two new names. + run storage set-names -n newimage -n otherimage $image + [ "$status" -eq 0 ] + + # Check that the two new names are the only ones assigned. + run storage exists -i no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -i fooimage + [ "$status" -ne 0 ] + run storage exists -i barimage + [ "$status" -ne 0 ] + run storage exists -i newimage + [ "$status" -eq 0 ] + run storage exists -i otherimage + [ "$status" -eq 0 ] + + # Check that the two new names are the only ones on this image. + run check-for-name no-such-thing-as-this-name $image + [ "$status" -ne 0 ] + run check-for-name fooimage $image + [ "$status" -ne 0 ] + run check-for-name barimage $image + [ "$status" -ne 0 ] + run check-for-name newimage $image + [ "$status" -eq 0 ] + run check-for-name otherimage $image + [ "$status" -eq 0 ] +} + +@test "move-names: images" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image with names that uses that layer. + run storage --debug=false create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + firstimage=${output%% *} + + # Create another image with no names. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Check that we can find the first image by ID and by its names. + run storage exists -i $firstimage + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $firstimage + [ "$status" -ne 0 ] + run check-for-name fooimage $firstimage + [ "$status" -eq 0 ] + run check-for-name barimage $firstimage + [ "$status" -eq 0 ] + + # Set a name list on the new image that includes the names of the old one. + run storage set-names -n fooimage -n barimage -n newimage -n otherimage $image + [ "$status" -eq 0 ] + + # Check that all of the names are assigned. + run storage exists -i no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -i fooimage + [ "$status" -eq 0 ] + run storage exists -i barimage + [ "$status" -eq 0 ] + run storage exists -i newimage + [ "$status" -eq 0 ] + run storage exists -i otherimage + [ "$status" -eq 0 ] + + # Check that all of the names are assigned to the new image. + run check-for-name no-such-thing-as-this-name $image + [ "$status" -ne 0 ] + run check-for-name fooimage $image + [ "$status" -eq 0 ] + run check-for-name barimage $image + [ "$status" -eq 0 ] + run check-for-name newimage $image + [ "$status" -eq 0 ] + run check-for-name otherimage $image + [ "$status" -eq 0 ] +} + +@test "add-names: ro-images" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + + mkdir ${TESTDIR}/{ro-root,ro-runroot} + + # Create a layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image with names that uses that layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Check that we can find the image by ID and by its names. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i $image + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i fooimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i barimage + [ "$status" -eq 0 ] + + # Add a pair of names to the image. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root add-names -n newimage -n otherimage $image + echo "add-names:" "$output" + [ "$status" -eq 0 ] + + # Check that all of the names are resolveable. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root images + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i $image + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i fooimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i barimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i newimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i otherimage + [ "$status" -eq 0 ] +} + +@test "remove-names: ro-images" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + + mkdir ${TESTDIR}/{ro-root,ro-runroot} + + # Create a layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image with names that uses that layer. + run storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot create-image -n fooimage -n barimage -n newimage -n otherimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + storage --debug=false --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Check that we can find the image by ID and by its names. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i $image + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i fooimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i barimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i newimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i otherimage + [ "$status" -eq 0 ] + + # Remove one of the names from the image. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root remove-names -n newimage $image + echo "remove-names:" "$output" + [ "$status" -eq 0 ] + + # Check that all of the names are still resolveable, except for the one we removed. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i $image + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i fooimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i barimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i newimage + [ "$status" -ne 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root exists -i otherimage + [ "$status" -eq 0 ] +} + +@test "names at creation: containers" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image that uses that layer. + run storage --debug=false create-image $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container with two names, based on that image. + run storage --debug=false create-container -n foocontainer -n barcontainer $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that we can find the container using either its ID or names. + run storage exists -c $container + [ "$status" -eq 0 ] + run storage exists -c no-such-thing-as-this-name + [ "$status" -ne 0 ] + run storage exists -c foocontainer + [ "$status" -eq 0 ] + run storage exists -c barcontainer + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $container + [ "$status" -ne 0 ] + run check-for-name foocontainer $container + [ "$status" -eq 0 ] + run check-for-name barcontainer $container + [ "$status" -eq 0 ] +} + +@test "add-names: containers" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image that uses that layer. + run storage --debug=false create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container with two names, based on that image. + run storage --debug=false create-container -n foocontainer -n barcontainer $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that we can find the container using either its ID or names. + run storage exists -c $container + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $container + [ "$status" -ne 0 ] + run check-for-name foocontainer $container + [ "$status" -eq 0 ] + run check-for-name barcontainer $container + [ "$status" -eq 0 ] + + # Add two names to the container. + run storage add-names -n newcontainer -n othercontainer $container + [ "$status" -eq 0 ] + + # Verify that all of those names are assigned to the container. + run storage exists -c $container + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $container + [ "$status" -ne 0 ] + run check-for-name foocontainer $container + [ "$status" -eq 0 ] + run check-for-name barcontainer $container + [ "$status" -eq 0 ] + run check-for-name newcontainer $container + [ "$status" -eq 0 ] + run check-for-name othercontainer $container + [ "$status" -eq 0 ] +} + +@test "set-names: containers" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image that uses that layer. + run storage --debug=false create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container with two names, based on that image. + run storage --debug=false create-container -n foocontainer -n barcontainer $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that we can find the container using either its ID or names. + run storage exists -c $container + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $container + [ "$status" -ne 0 ] + run check-for-name foocontainer $container + [ "$status" -eq 0 ] + run check-for-name barcontainer $container + [ "$status" -eq 0 ] + + # Set the list of names for the container to just these two values. + run storage set-names -n newcontainer -n othercontainer $container + [ "$status" -eq 0 ] + + # Check that these are the only two names attached to the container. + run storage exists -c $container + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $container + [ "$status" -ne 0 ] + run check-for-name foocontainer $container + [ "$status" -ne 0 ] + run check-for-name barcontainer $container + [ "$status" -ne 0 ] + run check-for-name newcontainer $container + [ "$status" -eq 0 ] + run check-for-name othercontainer $container + [ "$status" -eq 0 ] +} + +@test "move-names: containers" { + # Create a layer. + run storage --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + layer=$output + + # Create an image that uses that layer. + run storage --debug=false create-image -n fooimage -n barimage $layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${output%% *} + + # Create a container with two names, based on that image. + run storage --debug=false create-container -n foocontainer -n barcontainer $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + firstcontainer=${output%% *} + + # Create another container with two different names, based on that image. + run storage --debug=false create-container -n newcontainer -n othercontainer $image + [ "$status" -eq 0 ] + [ "$output" != "" ] + container=${output%% *} + + # Check that we can access both containers by ID, and that they have the right names. + run storage exists -c $firstcontainer + [ "$status" -eq 0 ] + run storage exists -c $container + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $firstcontainer + [ "$status" -ne 0 ] + run check-for-name foocontainer $firstcontainer + [ "$status" -eq 0 ] + run check-for-name barcontainer $firstcontainer + [ "$status" -eq 0 ] + run check-for-name newcontainer $firstcontainer + [ "$status" -ne 0 ] + run check-for-name othercontainer $firstcontainer + [ "$status" -ne 0 ] + run check-for-name foocontainer $container + [ "$status" -ne 0 ] + run check-for-name barcontainer $container + [ "$status" -ne 0 ] + run check-for-name newcontainer $container + [ "$status" -eq 0 ] + run check-for-name othercontainer $container + [ "$status" -eq 0 ] + + # Set the names on the new container to the names we gave the old one. + run storage set-names -n foocontainer -n barcontainer $container + [ "$status" -eq 0 ] + + # Check that the containers can still be found, and that the names are correctly set. + run storage exists -c $firstcontainer + [ "$status" -eq 0 ] + run storage exists -c $container + [ "$status" -eq 0 ] + run check-for-name no-such-thing-as-this-name $container + [ "$status" -ne 0 ] + run check-for-name foocontainer $firstcontainer + [ "$status" -ne 0 ] + run check-for-name barcontainer $firstcontainer + [ "$status" -ne 0 ] + run check-for-name newcontainer $firstcontainer + [ "$status" -ne 0 ] + run check-for-name othercontainer $firstcontainer + [ "$status" -ne 0 ] + run check-for-name foocontainer $container + [ "$status" -eq 0 ] + run check-for-name barcontainer $container + [ "$status" -eq 0 ] + run check-for-name newcontainer $container + [ "$status" -ne 0 ] + run check-for-name othercontainer $container + [ "$status" -ne 0 ] +} diff --git a/tests/overlay-recreate.bats b/tests/overlay-recreate.bats new file mode 100644 index 0000000..038a488 --- /dev/null +++ b/tests/overlay-recreate.bats @@ -0,0 +1,33 @@ +#!/usr/bin/env bats + +load helpers + +@test "overlay-recreate" { + case "$STORAGE_DRIVER" in + overlay) + ;; + *) + skip "not applicable to driver $STORAGE_DRIVER" + ;; + esac + populate + # behold my destructive power! + rm -v ${TESTDIR}/root/overlay/l/* + # we should be able to recover from that. + storage mount "$lowerlayer" + storage unmount "$lowerlayer" + storage mount "$midlayer" + storage unmount "$midlayer" + storage mount "$upperlayer" + storage unmount "$upperlayer" + # okay, but how about this? + rm -v ${TESTDIR}/root/overlay/*/link + # yeah, we can handle that, too. + storage mount "$lowerlayer" + storage unmount "$lowerlayer" + storage mount "$midlayer" + storage unmount "$midlayer" + storage mount "$upperlayer" + storage unmount "$upperlayer" + # okay, not bad, kid. +} diff --git a/tests/split-store.bats b/tests/split-store.bats new file mode 100644 index 0000000..dbd69dd --- /dev/null +++ b/tests/split-store.bats @@ -0,0 +1,109 @@ +#!/usr/bin/env bats + +load helpers + +@test "split-store" { + # Create and populate three interesting layers. + populate + + # Create an image using to top layer. + name=wonderful-image + run mkdir -p ${TESTDIR}/imagestore + run mkdir -p ${TESTDIR}/emptyimagestore + run storage --graph ${TESTDIR}/graph/ --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ --debug=false create-image --name $name + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${lines[0]} + + # Add a couple of big data items. + createrandom ${TESTDIR}/random1 + createrandom ${TESTDIR}/random2 + storage --graph ${TESTDIR}/graph/ --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ set-image-data -f ${TESTDIR}/random1 $image random1 + storage --graph ${TESTDIR}/graph/ --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ set-image-data -f ${TESTDIR}/random2 $image random2 + + # Get information about the image, and make sure the ID, name, and data names were preserved. + run storage --graph ${TESTDIR}/graph/ --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ image $image + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "ID: $image" ]] + [[ "$output" =~ "Name: $name" ]] + [[ "$output" =~ "Data: random1" ]] + [[ "$output" =~ "Data: random2" ]] + + # shutdown store + run storage --graph ${TESTDIR}/graph/ --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ shutdown + + # Similar data must not be shown when image-store is switched to empty store + run storage --graph ${TESTDIR}/graph/ --image-store ${TESTDIR}/emptyimagestore/ --run ${TESTDIR}/runroot/ image $image + echo "$output" + [[ "$output" != "ID: $image" ]] + [[ "$output" != "Name: $name" ]] + [[ "$output" != "Data: random1" ]] + [[ "$output" != "Data: random2" ]] + + # shutdown store + run storage --graph ${TESTDIR}/graph/ --image-store ${TESTDIR}/emptyimagestore/ --run ${TESTDIR}/runroot/ shutdown +} + +@test "split-store - use graphRoot as an additional store by default" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "additional store not supported by driver $STORAGE_DRIVER" + ;; + esac + # Create and populate three interesting layers. + populate + + # Create an image using to top layer. + name=wonderful-image + run mkdir -p ${TESTDIR}/imagestore + run storage --graph ${TESTDIR}/graph --debug=false create-image --name $name + [ "$status" -eq 0 ] + [ "$output" != "" ] + image=${lines[0]} + + # Add a couple of big data items. + createrandom ${TESTDIR}/random1 + createrandom ${TESTDIR}/random2 + storage --graph ${TESTDIR}/graph set-image-data -f ${TESTDIR}/random1 $image random1 + storage --graph ${TESTDIR}/graph set-image-data -f ${TESTDIR}/random2 $image random2 + + # Get information about the image, and make sure the ID, name, and data names were preserved. + run storage --graph ${TESTDIR}/graph image $image + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "ID: $image" ]] + [[ "$output" =~ "Name: $name" ]] + [[ "$output" =~ "Data: random1" ]] + [[ "$output" =~ "Data: random2" ]] + + # shutdown store + run storage --graph ${TESTDIR}/graph shutdown + + # Similar data must not be shown when image-store is switched to empty store + run storage --graph ${TESTDIR}/graph --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ image $image + echo "$output" + [[ "$output" =~ "ID: $image" ]] + [[ "$output" =~ "Name: $name" ]] + [[ "$output" =~ "Data: random1" ]] + [[ "$output" =~ "Data: random2" ]] + + # shutdown store + run storage --graph ${TESTDIR}/graph --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ shutdown + + # Even though image only exists on graphRoot, user must + # be able able to delete the image on graphRoot while `--image-store` + # is still set. + run storage --graph ${TESTDIR}/graph --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ delete-image $image + # shutdown store + run storage --graph ${TESTDIR}/graph --image-store ${TESTDIR}/imagestore/ --run ${TESTDIR}/runroot/ shutdown + + # Now since image was deleted from graphRoot, we should + # get false output while checking if image still exists + run storage --graph ${TESTDIR}/graph exists -i $image + [ "$status" -ne 0 ] + # shutdown store + run storage --graph ${TESTDIR}/graph shutdown +} diff --git a/tests/status.bats b/tests/status.bats new file mode 100644 index 0000000..30f7a4b --- /dev/null +++ b/tests/status.bats @@ -0,0 +1,18 @@ +#!/usr/bin/env bats + +load helpers + +@test "status" { + run storage --debug=false status + echo :"$output": + [ "$status" -eq 0 ] + # Expect the first line of the output to be the storage root directory location. + [ "${lines[0]/:*/}" = "Root" ] + [ "${lines[0]/*: /}" = "${TESTDIR}/root" ] + # Expect the second line of the output to be the storage runroot directory location. + [ "${lines[1]/:*/}" = "Run Root" ] + [ "${lines[1]/*: /}" = "${TESTDIR}/runroot" ] + # Expect the third line of the output to be "Driver Name: $STORAGE_DRIVER". + [ "${lines[2]/:*/}" = "Driver Name" ] + [ "${lines[2]/*: /}" = "$STORAGE_DRIVER" ] +} diff --git a/tests/stores.bats b/tests/stores.bats new file mode 100644 index 0000000..dbe99e3 --- /dev/null +++ b/tests/stores.bats @@ -0,0 +1,153 @@ +#!/usr/bin/env bats + +load helpers + +@test "additional-stores" { + case "$STORAGE_DRIVER" in + overlay*|vfs) + ;; + *) + skip "not supported by driver $STORAGE_DRIVER" + ;; + esac + # Initialize a store somewhere that we'll later use as a read-only store. + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot layers + # Fail this test if we can't initialize the driver with the option. + storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layers + # Create a layer in what will become the read-only store. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-layer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerlayer="$output" + # Mount the layer in what will become the read-only store. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false mount $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowermount="$output" + # Put a file in the layer in what will become the read-only store. + createrandom "$lowermount"/layer1file1 + + # Create a second layer based on the first one in what will become the read-only store. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-layer "$lowerlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + midlayer="$output" + # Mount that layer, too. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false mount $midlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + midmount="$output" + # Check that the file from the first layer is there. + test -s "$midmount"/layer1file1 + # Check that we can remove it... + rm -f -v "$midmount"/layer1file1 + # ... and that doing so doesn't affect the first layer. + test -s "$lowermount"/layer1file1 + # Create a new file in this layer. + createrandom "$midmount"/layer2file1 + # Unmount this layer. + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot unmount $midlayer + # Unmount the first layer. + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot unmount $lowerlayer + + # Create an image using this second layer. + run storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot --debug=false create-image $midlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + lowerimage=${output%% *} + + # We no longer need to use the read-only root as a writeable location, so shut it down. + storage --graph ${TESTDIR}/ro-root --run ${TESTDIR}/ro-runroot shutdown + + # Create a third layer based on the second one. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false create-layer "$midlayer" + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperlayer="$output" + # Mount this layer. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false mount $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppermount="$output" + # Check that the file we removed from the second layer is still gone. + run test -s "$uppermount"/layer1file1 + [ "$status" -ne 0 ] + # Check that the file we added to the second layer is still there. + test -s "$uppermount"/layer2file1 + # Unmount the third layer. + storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root unmount $upperlayer + + # Create an image using this third layer. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false create-image $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + upperimage=${output%% *} + # Create a container based on the upperimage. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false create-container "$upperimage" + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppercontainer="$output" + # Mount this container. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false mount $uppercontainer + [ "$status" -eq 0 ] + [ "$output" != "" ] + uppercontainermount="$output" + # Check that the file we removed from the second layer is still gone. + run test -s "$uppercontainermount"/layer1file1 + [ "$status" -ne 0 ] + # Check that the file we added to the second layer is still there. + test -s "$uppercontainermount"/layer2file1 + # Unmount the container. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false unmount $uppercontainer + [ "$status" -eq 0 ] + [ "$output" != "" ] + # Delete the container. + storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root delete-container $uppercontainer + [ "$status" -eq 0 ] + [ "$output" != "" ] + + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root add-names -n newimage $lowerimage + [ "$status" -eq 0 ] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root delete-image newimage + [ "$status" -eq 0 ] + + # Create a container based on the lowerimage. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false create-container "$lowerimage" + [ "$status" -eq 0 ] + [ "$output" != "" ] + container="$output" + # Mount this container. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root --debug=false mount $container + [ "$status" -eq 0 ] + [ "$output" != "" ] + containermount="$output" + # Check that the file we removed from the second layer is still gone. + run test -s "$containermount"/layer1file1 + [ "$status" -ne 0 ] + # Check that the file we added to the second layer is still there. + test -s "$containermount"/layer2file1 + # Unmount the container. + storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root delete-container $container + + # Check that the first two layers and the first image are marked read-only, and that the rest are not. + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layer $lowerlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + [[ "$output" =~ "Read Only: true" ]] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layer $midlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + [[ "$output" =~ "Read Only: true" ]] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root layer $upperlayer + [ "$status" -eq 0 ] + [ "$output" != "" ] + ! [[ "$output" =~ "Read Only: true" ]] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root image $lowerimage + [ "$status" -eq 0 ] + [ "$output" != "" ] + [[ "$output" =~ "Read Only: true" ]] + run storage --storage-opt ${STORAGE_DRIVER}.imagestore=${TESTDIR}/ro-root image $upperimage + [ "$status" -eq 0 ] + [ "$output" != "" ] + ! [[ "$output" =~ "Read Only: true" ]] +} diff --git a/tests/test_drivers.bash b/tests/test_drivers.bash new file mode 100755 index 0000000..f552260 --- /dev/null +++ b/tests/test_drivers.bash @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +TMPDIR=${TMPDIR:-/var/tmp} + +aufs() { + modprobe aufs 2> /dev/null + grep -E -q ' aufs$' /proc/filesystems +} + +btrfs() { + [ $(stat -f -c %T ${TMPDIR}) = btrfs ] +} + +devicemapper() { + for binary in pvcreate vgcreate lvcreate lvconvert lvchange thin_check ; do + if ! which $binary > /dev/null 2> /dev/null ; then + return 1 + fi + done + pkg-config devmapper 2> /dev/null +} + +overlay() { + modprobe overlay 2> /dev/null + grep -E -q ' overlay$' /proc/filesystems +} + +zfs() { + [ "$(stat -f -c %T ${TMPDIR:-/tmp})" = zfs ] +} + +if [ "$STORAGE_DRIVER" = "" ] ; then + drivers=vfs + if aufs ; then + drivers="$drivers aufs" + fi + if btrfs; then + drivers="$drivers btrfs" + fi + if devicemapper; then + drivers="$drivers devicemapper" + fi + if overlay; then + drivers="$drivers overlay" + fi + if zfs; then + drivers="$drivers zfs" + fi +else + drivers="$STORAGE_DRIVER" +fi +set -e +for driver in $drivers ; do + echo '['STORAGE_DRIVER="$driver"']' + env STORAGE_DRIVER="$driver" $(dirname ${BASH_SOURCE})/test_runner.bash "$@" +done diff --git a/tests/test_runner.bash b/tests/test_runner.bash new file mode 100755 index 0000000..868df60 --- /dev/null +++ b/tests/test_runner.bash @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e + +cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" + +# Load the helpers. +. helpers.bash + +function execute() { + >&2 echo "++ $@" + eval "$@" +} + +# Tests to run. Defaults to all. +TESTS=${@:-.} + +# Run the tests. +execute time bats --tap $TESTS diff --git a/tests/tools/Makefile b/tests/tools/Makefile new file mode 100644 index 0000000..9cc9eed --- /dev/null +++ b/tests/tools/Makefile @@ -0,0 +1,34 @@ +GO := go +BUILDDIR := build + +all: $(BUILDDIR) + +.PHONY: vendor +vendor: + $(GO) mod tidy + $(GO) mod vendor + $(GO) mod verify + +define go-build + $(shell cd `pwd` && $(GO) build -mod=vendor -o $(BUILDDIR)/$(shell basename $(1)) $(1)) + @echo > /dev/null +endef + +.PHONY: clean +clean: + rm -rf $(BUILDDIR) + +$(BUILDDIR): \ + $(BUILDDIR)/git-validation \ + $(BUILDDIR)/go-md2man \ + $(BUILDDIR)/golangci-lint + +$(BUILDDIR)/git-validation: + $(call go-build,./vendor/github.com/vbatts/git-validation) + +$(BUILDDIR)/go-md2man: + $(call go-build,./vendor/github.com/cpuguy83/go-md2man) + +$(BUILDDIR)/golangci-lint: VERSION=v1.51.2 +$(BUILDDIR)/golangci-lint: + curl -fsSL https://raw.githubusercontent.com/golangci/golangci-lint/$(VERSION)/install.sh | sh -s -- -b ./$(BUILDDIR) $(VERSION) diff --git a/tests/tools/go.mod b/tests/tools/go.mod new file mode 100644 index 0000000..6a5d78a --- /dev/null +++ b/tests/tools/go.mod @@ -0,0 +1,16 @@ +module github.com/containers/storage/tests/tools + +go 1.18 + +require ( + github.com/cpuguy83/go-md2man v1.0.10 + github.com/vbatts/git-validation v1.0.0 +) + +require ( + github.com/hashicorp/go-version v1.2.0 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect + github.com/russross/blackfriday v1.5.2 // indirect + github.com/sirupsen/logrus v1.4.1 // indirect + golang.org/x/sys v0.5.0 // indirect +) diff --git a/tests/tools/go.sum b/tests/tools/go.sum new file mode 100644 index 0000000..09ec98b --- /dev/null +++ b/tests/tools/go.sum @@ -0,0 +1,22 @@ +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/vbatts/git-validation v1.0.0 h1:Eb7bD3ThOk/2P01M+KaUng0gka9+MVvpn6d0a6AKxq0= +github.com/vbatts/git-validation v1.0.0/go.mod h1:QyK3uQnRYWGt/5ezd8kcpwPrm6zn9tNM/KtozbpfU6k= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/tests/tools/tools.go b/tests/tools/tools.go new file mode 100644 index 0000000..05dd78c --- /dev/null +++ b/tests/tools/tools.go @@ -0,0 +1,12 @@ +//go:build tools +// +build tools + +package tools + +// Importing the packages here will allow to vendor those via +// `go mod vendor`. + +import ( + _ "github.com/cpuguy83/go-md2man" + _ "github.com/vbatts/git-validation" +) |