1
0
mirror of https://github.com/opencontainers/umoci.git synced 2026-02-05 09:45:50 +01:00
Files
umoci/test/stat.bats
Aleksa Sarai 712f78763a *: update license headers
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2026-01-10 11:14:14 +01:00

682 lines
20 KiB
Bash

#!/usr/bin/env bats -t
# SPDX-License-Identifier: Apache-2.0
# umoci: Umoci Modifies Open Containers' Images
# Copyright (C) 2016-2025 SUSE LLC
# Copyright (C) 2026 Aleksa Sarai <cyphar@cyphar.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load helpers
function setup() {
setup_tmpdirs
setup_image
}
function teardown() {
teardown_tmpdirs
teardown_image
}
function digest_to_path() {
layout="$1"
digest="$2"
echo "$1/blobs/$(tr : / <<<"$2")"
}
@test "umoci stat --json" {
# Make sure that stat looks about right.
umoci stat --image "${IMAGE}:${TAG}" --json
[ "$status" -eq 0 ]
statFile="$(setup_tmpdir)/stat"
echo "$output" > "$statFile"
# .manifest.descriptor should describe a config blob
sane_run jq -SMr '.manifest.descriptor.mediaType' "$statFile"
[ "$status" -eq 0 ]
[[ "$output" == "application/vnd.oci.image.manifest.v1+json" ]]
# .manifest.blob should match .manifest.descriptor data
sane_run jq -SMr '.manifest.descriptor.digest' "$statFile"
[ "$status" -eq 0 ]
manifest_digest="$output"
sane_run jq -SMr '.manifest.blob' "$statFile"
[ "$status" -eq 0 ]
manifest_data="$output"
sane_run jq -SMr '.' "$(digest_to_path "$IMAGE" "$manifest_digest")"
[ "$status" -eq 0 ]
[[ "$output" == "$manifest_data" ]]
# .config.descriptor should describe a config blob
sane_run jq -SMr '.config.descriptor.mediaType' "$statFile"
[ "$status" -eq 0 ]
[[ "$output" == "application/vnd.oci.image.config.v1+json" ]]
# .config.blob should match .config.descriptor data
sane_run jq -SMr '.config.descriptor.digest' "$statFile"
[ "$status" -eq 0 ]
config_digest="$output"
sane_run jq -SMr '.config.blob' "$statFile"
[ "$status" -eq 0 ]
config_data="$output"
sane_run jq -SMr '.' "$(digest_to_path "$IMAGE" "$config_digest")"
[ "$status" -eq 0 ]
[[ "$output" == "$config_data" ]]
# .history should have at least one entry.
sane_run jq -SMr '.history | length' "$statFile"
[ "$status" -eq 0 ]
[ "$output" -ge 1 ]
# There should be at least one non-empty_layer.
sane_run jq -SMr '[.history[] | .empty_layer == null] | any' "$statFile"
[ "$status" -eq 0 ]
[[ "$output" == "true" ]]
image-verify "${IMAGE}"
}
# We can't really test the output for non-JSON output, but we can smoke test it.
@test "umoci stat [smoke]" {
# Set some values to make sure they show up in stat properly.
umoci config --image "${IMAGE}:${TAG}" \
--config.user "foobar" \
--manifest.annotation "org.opencontainers.umoci.test=foo"
[ "$status" -eq 0 ]
# Make sure that stat looks about right.
umoci stat --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
# We should have some manifest information.
echo "$output" | grep "== MANIFEST =="
echo "$output" | grep "Media Type: application/vnd.oci.image.manifest.v1+json"
echo "$output" | grep "org.opencontainers.umoci.test: foo"
echo "$output" | grep "org.opencontainers.image.ref.name: ${TAG}"
# We should have some config information.
echo "$output" | grep "== CONFIG =="
echo "$output" | grep "Media Type: application/vnd.oci.image.config.v1+json"
echo "$output" | grep "User: foobar"
# We should have some history information.
echo "$output" | grep "== HISTORY =="
echo "$output" | grep 'LAYER'
echo "$output" | grep 'CREATED'
echo "$output" | grep 'CREATED BY'
echo "$output" | grep 'SIZE'
echo "$output" | grep 'COMMENT'
image-verify "${IMAGE}"
}
@test "umoci stat [output snapshot: blank image]" {
EXPECTED_OUTPUT="$(cat <<EOF
== MANIFEST ==
Schema Version: 2
Media Type: application/vnd.oci.image.manifest.v1+json
Config:
Descriptor:
Media Type: application/vnd.oci.image.config.v1+json
Digest: sha256:e5101a46118c740a7709af8eaeec19cbc50a567f4fe7741f8420af39a3779a77
Size: 135B
Descriptor:
Media Type: application/vnd.oci.image.manifest.v1+json
Digest: sha256:98a4b5d5fe4ea076a0a9059075dad54741e055fd0fa016903a8e2b858dcbad80
Size: 249B
Annotations:
org.opencontainers.image.ref.name: latest
== CONFIG ==
Created: 2025-09-05T13:05:10.12345+10:00
Author: ""
Platform:
OS: $(go env GOOS)
Architecture: $(go env GOARCH)
Image Config:
User: ""
Command: (empty)
Descriptor:
Media Type: application/vnd.oci.image.config.v1+json
Digest: sha256:e5101a46118c740a7709af8eaeec19cbc50a567f4fe7741f8420af39a3779a77
Size: 135B
== HISTORY ==
LAYER CREATED CREATED BY SIZE COMMENT
EOF
)"
IMAGE="$(setup_tmpdir)/image" TAG="latest"
STATFILE_DIR="$(setup_tmpdir)"
expected="${STATFILE_DIR}/expected"
cat >"$expected" <<<"$EXPECTED_OUTPUT"
umoci init --layout "${IMAGE}"
[ "$status" -eq 0 ]
umoci new --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
umoci config --no-history --created="2025-09-05T13:05:10.12345+10:00" --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
umoci stat --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
got="${STATFILE_DIR}/got"
cat >"$got" <<<"$output"
sane_run diff -u "$expected" "$got"
[ "$status" -eq 0 ]
}
@test "umoci stat [output snapshot: minimal image]" {
EXPECTED_OUTPUT="$(cat <<EOF
== MANIFEST ==
Schema Version: 2
Media Type: application/vnd.oci.image.manifest.v1+json
Config:
Descriptor:
Media Type: application/vnd.oci.image.config.v1+json
Digest: sha256:01a6fc95c8afce1ebfaca585848ff2c42fe89ea0f5913c8e8fd6a0f8b691cd39
Size: 1.107kB
Layers:
Descriptor:
Media Type: application/vnd.oci.image.layer.v1.tar+gzip
Digest: sha256:088ca2b11e89a40e143aeb9d4564d0ffb69d26a380b3341af07fa28c2dbdaece
Size: 238B
Annotations:
ci.umo.uncompressed_blob_size: 4608
Descriptor:
Media Type: application/vnd.oci.image.layer.v1.tar+zstd
Digest: sha256:92226702a21491c696a910e56da759a2d6fe979211a7ad91c60ca715b89bc059
Size: 119B
Annotations:
ci.umo.uncompressed_blob_size: 2048
Annotations:
ci.umo.abc: "foobar\tbaz"
ci.umo.xyz: "hello world"
Descriptor:
Media Type: application/vnd.oci.image.manifest.v1+json
Digest: sha256:58fa9705ecfc0ec7d1e8631a729c6cbab46206233d58e46fc55346ca9d25ed43
Size: 737B
Annotations:
org.opencontainers.image.ref.name: latest
== CONFIG ==
Created: 2025-09-05T13:05:10.12345+10:00
Author: "Aleksa Sarai <cyphar@cyphar.com>"
Platform:
OS: gnu+linux
Architecture: riscv64
Image Config:
User: foo:bar
Entrypoint:
/bin/sh
-c
Command:
true
Working Directory: /tmp
Environment:
HOME=/
SHELL=/bin/false
AAA=1234
"ESCAPED=a\tb\nc\vd\re"
Stop Signal: SIGKILL
Exposed Ports: 80/tcp, 8080/udp
Volumes: /tmp, /var, "/with, comma"
Descriptor:
Media Type: application/vnd.oci.image.config.v1+json
Digest: sha256:01a6fc95c8afce1ebfaca585848ff2c42fe89ea0f5913c8e8fd6a0f8b691cd39
Size: 1.107kB
== HISTORY ==
LAYER CREATED CREATED BY SIZE COMMENT
sha256:088ca2b11e89a40e143aeb9d4564d0ffb69d26a380b3341af07fa28c2dbdaece 1997-03-25T13:40:00Z umoci insert 238B basic insert
sha256:92226702a21491c696a910e56da759a2d6fe979211a7ad91c60ca715b89bc059 1997-03-25T13:42:00Z umoci insert --opaque 119B whiteout /
<none> 2025-09-05T13:05:10.12345+10:00 umoci config <none> dummy configuration
EOF
)"
IMAGE="$(setup_tmpdir)/image" TAG="latest"
STATFILE_DIR="$(setup_tmpdir)"
expected="${STATFILE_DIR}/expected"
cat >"$expected" <<<"$EXPECTED_OUTPUT"
umoci init --layout "${IMAGE}"
[ "$status" -eq 0 ]
umoci new --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
umoci config --no-history --image "${IMAGE}:${TAG}" \
--author="Aleksa Sarai <cyphar@cyphar.com>" \
--created="2025-09-05T13:05:10.12345+10:00" \
--os="gnu+linux" \
--architecture="riscv64"
[ "$status" -eq 0 ]
layer="$(setup_tmpdir)"
echo "dummy data" >"$layer/file"
ln -s "foo" "$layer/link"
mkdir -p "$layer/foo/bar/baz"
find "$layer" -print0 | xargs -0 touch -h -d "1997-03-25T13:40:00"
umoci insert --image "${IMAGE}:${TAG}" \
--history.author='Aleksa Sarai <cyphar@cyphar.com>' \
--history.comment="basic insert" \
--history.created="1997-03-25T13:40:00Z" \
"$layer" /
[ "$status" -eq 0 ]
layer="$(setup_tmpdir)"
find "$layer" -print0 | xargs -0 touch -h -d "1997-03-25T13:42:00"
umoci insert --image "${IMAGE}:${TAG}" \
--compress=zstd \
--history.author=$'Foo Bar <foo\tbar\nbaz@fake.email>' \
--history.comment="whiteout /" \
--history.created_by="umoci insert --opaque" \
--history.created="1997-03-25T13:42:00Z" \
--opaque "$layer" /foo
[ "$status" -eq 0 ]
umoci config --image "${IMAGE}:${TAG}" \
--config.user="foo:bar" \
--config.exposedports=80/tcp \
--config.exposedports=8080/udp \
--config.env="HOME=/" \
--config.env="SHELL=/bin/false" \
--config.env="AAA=1234" \
--config.env=$'ESCAPED=a\tb\nc\vd\re' \
--config.entrypoint="/bin/sh" \
--config.entrypoint="-c" \
--config.cmd="true" \
--config.volume="/tmp" \
--config.volume="/var" \
--config.volume="/with, comma" \
--config.workingdir="/tmp" \
--config.stopsignal="SIGKILL" \
--manifest.annotation=$'ci.umo.abc=foobar\tbaz' \
--manifest.annotation="ci.umo.xyz=hello world" \
--history.created="2025-09-05T13:05:10.12345+10:00" \
--history.author="Hello World <another dummy email@foo.com>" \
--history.comment="dummy configuration"
[ "$status" -eq 0 ]
umoci stat --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
got="${STATFILE_DIR}/got"
cat >"$got" <<<"$output"
sane_run diff -u "$expected" "$got"
[ "$status" -eq 0 ]
}
@test "umoci stat [output snapshot: pseudo-artifact w/o config or layers]" {
# Make an empty image.
IMAGE="$(setup_tmpdir)/image" TAG="latest"
umoci init --layout "$IMAGE"
[ "$status" -eq 0 ]
# Construct a dummy OCI artifact with a parseable but non-standard config
# configured.
manifestJSON="$(jq -cSM . <<<'{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/vnd.umoci.testing.fake-artifact+foobar",
"config": {
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2,
"data": "e30="
},
"layers": [
{
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2,
"data": "e30="
}
],
"annotations": {
"ci.umo.test-artifact.build-id": "1234567890",
"ci.umo.test-artifact.data": "foobar"
}
}')"
echo "manifest json:"
jq . <<<"$manifestJSON"
manifestDescriptor="$(insert-blob "application/vnd.oci.image.manifest.v1+json" <<<"$manifestJSON")"
echo "manifest descriptor:"
jq . <<<"$manifestDescriptor"
# Update index.json to reference the new image.
indexReference="$(jq -cSM '.annotations["org.opencontainers.image.ref.name"] = "'"$TAG"'"' <<<"$manifestDescriptor")"
jq -cSM '.manifests += ['"$indexReference"']' <"$IMAGE/index.json" | sponge "$IMAGE/index.json"
# Show all of the files.
( cd "$IMAGE"; find .; )
EXPECTED_OUTPUT="$(cat <<EOF
== MANIFEST ==
Schema Version: 2
Media Type: application/vnd.oci.image.manifest.v1+json
Artifact Type: application/vnd.umoci.testing.fake-artifact+foobar
Config:
Descriptor:
Media Type: application/vnd.oci.empty.v1+json
Digest: sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
Size: 2B
Data: (2 bytes)
0000: 7b7d {}
Layers:
Descriptor:
Media Type: application/vnd.oci.empty.v1+json
Digest: sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
Size: 2B
Data: (2 bytes)
0000: 7b7d {}
Annotations:
ci.umo.test-artifact.build-id: 1234567890
ci.umo.test-artifact.data: foobar
Descriptor:
Media Type: application/vnd.oci.image.manifest.v1+json
Digest: $(jq -rM .digest <<<"$manifestDescriptor")
Size: $(jq -rM .size <<<"$manifestDescriptor")B
Annotations:
org.opencontainers.image.ref.name: $TAG
== CONFIG ==
Descriptor:
Media Type: application/vnd.oci.empty.v1+json
Digest: sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
Size: 2B
Data: (2 bytes)
0000: 7b7d {}
EOF
)"
STATFILE_DIR="$(setup_tmpdir)"
expected="${STATFILE_DIR}/expected"
cat >"$expected" <<<"$EXPECTED_OUTPUT"
umoci stat --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
got="${STATFILE_DIR}/got"
cat >"$got" <<<"$output"
sane_run diff -u "$expected" "$got"
[ "$status" -eq 0 ]
}
@test "umoci stat [output snapshot: pseudo-artifact w/o config]" {
# Make an empty image.
IMAGE="$(setup_tmpdir)/image" TAG="latest"
umoci init --layout "$IMAGE"
[ "$status" -eq 0 ]
# Add some dummy data for the layers.
layer1="$(head -c 128 /dev/urandom | insert-blob "application/vnd.umoci.testing.fake-layer+data")"
echo "layer 1: $layer1"
layer2="$(head -c 256 /dev/urandom | insert-blob "application/vnd.umoci.testing.fake-layer+data")"
echo "layer 2: $layer2"
layer3="$(head -c 512 /dev/urandom | insert-blob "application/vnd.umoci.testing.fake-layer+data")"
echo "layer 3: $layer3"
# Construct a dummy OCI artifact with a parseable but non-standard config
# configured.
manifestJSON="$(jq -cSM . <<<'{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/vnd.umoci.testing.fake-artifact+foobar",
"config": {
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2,
"data": "e30="
},
"layers": [
'"$layer1"',
'"$layer2"',
'"$layer3"'
],
"annotations": {
"ci.umo.test-artifact.build-id": "1234567890"
}
}')"
echo "manifest json:"
jq . <<<"$manifestJSON"
manifestDescriptor="$(insert-blob "application/vnd.oci.image.manifest.v1+json" <<<"$manifestJSON")"
echo "manifest descriptor:"
jq . <<<"$manifestDescriptor"
# Update index.json to reference the new image.
indexReference="$(jq -cSM '.annotations["org.opencontainers.image.ref.name"] = "'"$TAG"'"' <<<"$manifestDescriptor")"
jq -cSM '.manifests += ['"$indexReference"']' <"$IMAGE/index.json" | sponge "$IMAGE/index.json"
# Show all of the files.
( cd "$IMAGE"; find .; )
EXPECTED_OUTPUT="$(cat <<EOF
== MANIFEST ==
Schema Version: 2
Media Type: application/vnd.oci.image.manifest.v1+json
Artifact Type: application/vnd.umoci.testing.fake-artifact+foobar
Config:
Descriptor:
Media Type: application/vnd.oci.empty.v1+json
Digest: sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
Size: 2B
Data: (2 bytes)
0000: 7b7d {}
Layers:
Descriptor:
Media Type: application/vnd.umoci.testing.fake-layer+data
Digest: $(jq -rM .digest <<<"$layer1")
Size: 128B
Descriptor:
Media Type: application/vnd.umoci.testing.fake-layer+data
Digest: $(jq -rM .digest <<<"$layer2")
Size: 256B
Descriptor:
Media Type: application/vnd.umoci.testing.fake-layer+data
Digest: $(jq -rM .digest <<<"$layer3")
Size: 512B
Annotations:
ci.umo.test-artifact.build-id: 1234567890
Descriptor:
Media Type: application/vnd.oci.image.manifest.v1+json
Digest: $(jq -rM .digest <<<"$manifestDescriptor")
Size: $(jq -rM .size <<<"$manifestDescriptor")B
Annotations:
org.opencontainers.image.ref.name: $TAG
== CONFIG ==
Descriptor:
Media Type: application/vnd.oci.empty.v1+json
Digest: sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
Size: 2B
Data: (2 bytes)
0000: 7b7d {}
EOF
)"
STATFILE_DIR="$(setup_tmpdir)"
expected="${STATFILE_DIR}/expected"
cat >"$expected" <<<"$EXPECTED_OUTPUT"
umoci stat --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
got="${STATFILE_DIR}/got"
cat >"$got" <<<"$output"
sane_run diff -u "$expected" "$got"
[ "$status" -eq 0 ]
}
@test "umoci stat [output snapshot: pseudo-artifact w/config]" {
# Make an empty image.
IMAGE="$(setup_tmpdir)/image" TAG="latest"
umoci init --layout "$IMAGE"
[ "$status" -eq 0 ]
config="$(echo '{"dummy": "data"}' | insert-blob "application/vnd.umoci.testing.fake-config+json")"
echo "config: $config"
# Add some dummy data for the layers.
layer1="$(head -c 128 /dev/urandom | insert-blob "application/vnd.umoci.testing.fake-layer+data")"
echo "layer 1: $layer1"
layer2="$(head -c 256 /dev/urandom | insert-blob "application/vnd.umoci.testing.fake-layer+data")"
echo "layer 2: $layer2"
layer3="$(head -c 512 /dev/urandom | insert-blob "application/vnd.umoci.testing.fake-layer+data")"
echo "layer 3: $layer3"
# Construct a dummy OCI artifact with a parseable but non-standard config
# configured.
manifestJSON="$(jq -cSM . <<<'{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/vnd.umoci.testing.fake-artifact+foobar",
"config": '"$config"',
"layers": [
'"$layer1"',
'"$layer2"',
'"$layer3"'
],
"annotations": {
"ci.umo.test-artifact.build-id": "1234567890"
}
}')"
echo "manifest json:"
jq . <<<"$manifestJSON"
manifestDescriptor="$(insert-blob "application/vnd.oci.image.manifest.v1+json" <<<"$manifestJSON")"
echo "manifest descriptor:"
jq . <<<"$manifestDescriptor"
# Update index.json to reference the new image.
indexReference="$(jq -cSM '.annotations["org.opencontainers.image.ref.name"] = "'"$TAG"'"' <<<"$manifestDescriptor")"
jq -cSM '.manifests += ['"$indexReference"']' <"$IMAGE/index.json" | sponge "$IMAGE/index.json"
# Show all of the files.
( cd "$IMAGE"; find .; )
EXPECTED_OUTPUT="$(cat <<EOF
== MANIFEST ==
Schema Version: 2
Media Type: application/vnd.oci.image.manifest.v1+json
Artifact Type: application/vnd.umoci.testing.fake-artifact+foobar
Config:
Descriptor:
Media Type: application/vnd.umoci.testing.fake-config+json
Digest: $(jq -rM .digest <<<"$config")
Size: $(jq -rM .size <<<"$config")B
Layers:
Descriptor:
Media Type: application/vnd.umoci.testing.fake-layer+data
Digest: $(jq -rM .digest <<<"$layer1")
Size: 128B
Descriptor:
Media Type: application/vnd.umoci.testing.fake-layer+data
Digest: $(jq -rM .digest <<<"$layer2")
Size: 256B
Descriptor:
Media Type: application/vnd.umoci.testing.fake-layer+data
Digest: $(jq -rM .digest <<<"$layer3")
Size: 512B
Annotations:
ci.umo.test-artifact.build-id: 1234567890
Descriptor:
Media Type: application/vnd.oci.image.manifest.v1+json
Digest: $(jq -rM .digest <<<"$manifestDescriptor")
Size: $(jq -rM .size <<<"$manifestDescriptor")B
Annotations:
org.opencontainers.image.ref.name: $TAG
EOF
)"
STATFILE_DIR="$(setup_tmpdir)"
expected="${STATFILE_DIR}/expected"
cat >"$expected" <<<"$EXPECTED_OUTPUT"
umoci stat --image "${IMAGE}:${TAG}"
[ "$status" -eq 0 ]
got="${STATFILE_DIR}/got"
cat >"$got" <<<"$output"
sane_run diff -u "$expected" "$got"
[ "$status" -eq 0 ]
}
@test "umoci stat [invalid arguments]" {
# Missing --image argument.
umoci stat
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Too many positional arguments.
umoci stat --image "${IMAGE}:${TAG}" this-is-an-invalid-argument
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Empty image path.
umoci stat --image ":${TAG}"
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Non-existent image path.
umoci stat --image "${IMAGE}-doesnotexist:${TAG}"
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Empty image source tag.
umoci stat --image "${IMAGE}:"
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Invalid image source tag.
umoci stat --image "${IMAGE}:${TAG}-doesnotexist"
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Invalid image source tag.
umoci stat --image "${IMAGE}:${INVALID_TAG}"
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Unknown flag argument.
umoci stat --this-is-an-invalid-argument --image "${IMAGE}:${TAG}"
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
# Too many positional arguments.
umoci stat --image "${IMAGE}" this-is-an-invalid-argument
[ "$status" -ne 0 ]
image-verify "${IMAGE}"
}
# TODO: Add a test to make sure that empty_layer and layer are mutually
# exclusive. Unfortunately, jq doesn't provide an XOR operator...