8
# Enumerate every one of the manifest names used everywhere below
9
echo "[ teardown - ignore 'image not known' errors below ]"
10
run_podman '?' manifest rm test:1.0 \
11
localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test:1.0
16
# Helper function for several of the tests which verifies compression.
18
# Usage: validate_instance_compression INDEX MANIFEST ARCH COMPRESSION
20
# INDEX instance which needs to be verified in
21
# provided manifest list.
23
# MANIFEST OCI manifest specification in json format
25
# ARCH instance architecture
27
# COMPRESSION compression algorithm name; e.g "zstd".
29
function validate_instance_compression {
33
run jq -r '.manifests['$1'].annotations' <<< $2
34
# annotation is `null` for gzip compression
35
assert "$output" = "null" ".manifests[$1].annotations (null means gzip)"
39
# annotation `'"io.github.containers.compression.zstd": "true"'` must be there for zstd compression
40
run jq -r '.manifests['$1'].annotations."io.github.containers.compression.zstd"' <<< $2
41
assert "$output" = "true" ".manifests[$1].annotations.'io.github.containers.compression.zstd' (io.github.containers.compression.zstd must be set)"
45
run jq -r '.manifests['$1'].platform.architecture' <<< $2
46
assert "$output" = $3 ".manifests[$1].platform.architecture"
49
# Regression test for #8931
50
@test "podman images - bare manifest list" {
51
# Create an empty manifest list and list images.
53
run_podman inspect --format '{{.ID}}' $IMAGE
56
run_podman manifest create test:1.0
58
run_podman manifest inspect --verbose $mid
59
is "$output" ".*\"mediaType\": \"application/vnd.docker.distribution.manifest.list.v2+json\"" "--insecure is a noop want to make sure manifest inspect is successful"
60
run_podman manifest inspect -v $mid
61
is "$output" ".*\"mediaType\": \"application/vnd.docker.distribution.manifest.list.v2+json\"" "--insecure is a noop want to make sure manifest inspect is successful"
62
run_podman images --format '{{.ID}}' --no-trunc
63
is "$output" ".*sha256:$iid" "Original image ID still shown in podman-images output"
64
run_podman rmi test:1.0
67
@test "podman manifest --tls-verify and --authfile" {
68
skip_if_remote "running a local registry doesn't work with podman-remote"
70
authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
71
run_podman login --tls-verify=false \
72
--username ${PODMAN_LOGIN_USER} \
74
--authfile=$authfile \
75
localhost:${PODMAN_LOGIN_REGISTRY_PORT} <<<"${PODMAN_LOGIN_PASS}"
76
is "$output" "Login Succeeded!" "output from podman login"
78
manifest1="localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test:1.0"
79
run_podman manifest create $manifest1
81
run_podman manifest push --authfile=$authfile \
82
--tls-verify=false $mid \
84
run_podman manifest rm $manifest1
86
# Default is to require TLS; also test explicit opts
87
for opt in '' '--insecure=false' '--tls-verify=true' "--authfile=$authfile"; do
88
run_podman 125 manifest inspect $opt $manifest1
89
assert "$output" =~ "Error: reading image \"docker://$manifest1\": pinging container registry localhost:${PODMAN_LOGIN_REGISTRY_PORT}:.*x509" \
90
"TLE check: fails (as expected) with ${opt:-default}"
93
run_podman manifest inspect --authfile=$authfile --tls-verify=false $manifest1
94
is "$output" ".*\"mediaType\": \"application/vnd.docker.distribution.manifest.list.v2+json\"" "Verify --tls-verify=false --authfile works against an insecure registry"
95
run_podman manifest inspect --authfile=$authfile --insecure $manifest1
96
is "$output" ".*\"mediaType\": \"application/vnd.docker.distribution.manifest.list.v2+json\"" "Verify --insecure --authfile works against an insecure registry"
97
REGISTRY_AUTH_FILE=$authfile run_podman manifest inspect --tls-verify=false $manifest1
98
is "$output" ".*\"mediaType\": \"application/vnd.docker.distribution.manifest.list.v2+json\"" "Verify --tls-verify=false with REGISTRY_AUTH_FILE works against an insecure registry"
101
@test "manifest list --add-compression with zstd" {
102
skip_if_remote "running a local registry doesn't work with podman-remote"
105
# Using TARGETARCH gives us distinct images for each arch
106
dockerfile=$PODMAN_TMPDIR/Dockerfile
107
cat >$dockerfile <<EOF
110
COPY Dockerfile /i-am-\${TARGETARCH}
112
authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
113
run_podman login --tls-verify=false \
114
--username ${PODMAN_LOGIN_USER} \
116
--authfile=$authfile \
117
localhost:${PODMAN_LOGIN_REGISTRY_PORT} <<<"${PODMAN_LOGIN_PASS}"
118
is "$output" "Login Succeeded!" "output from podman login"
120
# Build two images, different arches, and add each to one manifest list
121
local manifestlocal="test:1.0"
122
run_podman manifest create $manifestlocal
123
for arch in amd arm;do
124
# This leaves behind a <none>:<none> image that must be purged, below
125
run_podman build -t image_$arch --platform linux/${arch}64 -f $dockerfile
126
run_podman manifest add $manifestlocal containers-storage:localhost/image_$arch:latest
132
# Push to local registry; the magic key here is --add-compression...
133
local manifestpushed="localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test:1.0"
134
run_podman manifest push --authfile=$authfile --all --compression-format gzip --add-compression zstd --tls-verify=false $manifestlocal $manifestpushed
136
# ...and use skopeo to confirm that each component has the right settings
137
echo "$_LOG_PROMPT skopeo inspect ... $manifestpushed"
138
list=$(skopeo inspect --authfile=$authfile --tls-verify=false --raw docker://$manifestpushed)
141
validate_instance_compression "0" "$list" "amd64" "gzip"
142
validate_instance_compression "1" "$list" "arm64" "gzip"
143
validate_instance_compression "2" "$list" "amd64" "zstd"
144
validate_instance_compression "3" "$list" "arm64" "zstd"
146
run_podman rmi image_amd image_arm
147
run_podman manifest rm $manifestlocal
149
# Needed because the above build leaves a dangling <none>
150
run_podman image prune -f
153
function manifestListAddArtifactOnce() {
154
echo listFlags="$listFlags"
155
echo platformFlags="$platformFlags"
156
echo typeFlag="$typeFlag"
157
echo layerTypeFlag="$layerTypeFlag"
158
echo configTypeFlag="$configTypeFlag"
159
echo configFlag="$configFlag"
160
echo titleFlag="$titleFlag"
161
local index artifact firstdigest seconddigest config configSize defaulttype filetitle requested expected actual
162
run_podman manifest create $listFlags $list
163
run_podman manifest add $list ${platformFlags} --artifact ${typeFlag} ${layerTypeFlag} ${configTypeFlag} ${configFlag} ${titleFlag} ${PODMAN_TMPDIR}/listed.txt
164
run_podman manifest add $list ${platformFlags} --artifact ${typeFlag} ${layerTypeFlag} ${configTypeFlag} ${configFlag} ${titleFlag} ${PODMAN_TMPDIR}/zeroes
165
run_podman manifest inspect $list
166
run_podman tag $list localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test
167
run_podman manifest push --tls-verify=false localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test
168
run skopeo inspect --tls-verify=false --raw docker://localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test
172
if [[ -n "$listFlags" ]] ; then
173
assert $(jq -r '.annotations["global"]' <<<"$index") == local
175
if [[ -n "$platformFlags" ]] ; then
176
assert $(jq -r '.manifests[1].platform.os' <<<"$index") == linux
177
assert $(jq -r '.manifests[1].platform.architecture' <<<"$index") == amd64
179
if [[ -n "$typeFlag" ]] ; then
180
actual=$(jq -r '.manifests[0].artifactType' <<<"$index")
181
assert "${actual#null}" == "${typeFlag#--artifact-type=}"
182
actual=$(jq -r '.manifests[1].artifactType' <<<"$index")
183
assert "${actual#null}" == "${typeFlag#--artifact-type=}"
185
firstdigest=$(jq -r '.manifests[0].digest' <<<"$index")
186
seconddigest=$(jq -r '.manifests[1].digest' <<<"$index")
187
for digest in $firstdigest $seconddigest ; do
191
defaulttype=text/plain
195
defaulttype=application/octet-stream
201
run skopeo inspect --raw --tls-verify=false docker://localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test@${digest}
205
if [[ -n "$typeFlag" ]] ; then
206
actual=$(jq -r '.artifactType' <<<"$artifact")
207
assert "${actual#null}" == "${typeFlag#--artifact-type=}"
209
actual=$(jq -r '.artifactType' <<<"$artifact")
210
assert "${actual}" == application/vnd.unknown.artifact.v1
212
if [ -n "$layerTypeFlag" ] ; then
213
actual=$(jq -r '.layers[0].mediaType' <<<"$artifact")
214
assert "${actual}" == "${layerTypeFlag#--artifact-layer-type=}"
216
actual=$(jq -r '.layers[0].mediaType' <<<"$artifact")
217
assert "${actual}" == "$defaulttype"
219
requested=${configTypeFlag#--artifact-config-type=}
220
actual=$(jq -r '.config.mediaType' <<<"$artifact")
221
if test -n "$requested" ; then
222
assert "$actual" == "$requested"
224
config=${configFlag#--artifact-config=}
225
if [ -z "$config" ] ; then
226
expected=application/vnd.oci.empty.v1+json
228
configSize=$(wc -c <"$config")
229
if [ $configSize -gt 0 ] ; then
230
expected=application/vnd.oci.image.config.v1+json
232
expected=application/vnd.oci.empty.v1+json
235
assert "$actual" == "$expected"
237
if test -n "$titleFlag" ; then
238
assert $(jq -r '.layers[0].annotations["org.opencontainers.image.title"]' <<<"$artifact") == null
240
assert $(jq -r '.layers[0].annotations["org.opencontainers.image.title"]' <<<"$artifact") == $filetitle
243
run_podman rmi $list localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test
246
@test "manifest list --add --artifact" {
247
# Build a list and add some files to it, making sure to exercise and verify
248
# every flag available.
249
skip_if_remote "running a local registry doesn't work with podman-remote"
251
run_podman login --tls-verify=false \
252
--username ${PODMAN_LOGIN_USER} \
254
--authfile=$authfile \
255
localhost:${PODMAN_LOGIN_REGISTRY_PORT} <<<"${PODMAN_LOGIN_PASS}"
256
local list="test:1.0"
257
truncate -s 20M ${PODMAN_TMPDIR}/zeroes
258
echo oh yeah > ${PODMAN_TMPDIR}/listed.txt
259
echo '{}' > ${PODMAN_TMPDIR}/minimum-config.json
260
local listFlags platformFlags typeFlag configTypeFlag configFlag layerTypeFlag titleFlag
261
for listFlags in "" "--annotation global=local" ; do
262
manifestListAddArtifactOnce
264
for platformFlags in "" "--os=linux --arch=amd64" ; do
265
manifestListAddArtifactOnce
267
for typeFlag in "" --artifact-type="" --artifact-type=application/octet-stream --artifact-type=text/plain ; do
268
manifestListAddArtifactOnce
270
for configTypeFlag in "" --artifact-config-type=application/octet-stream --artifact-config-type=text/plain ; do
271
for configFlag in "" --artifact-config= --artifact-config=${PODMAN_TMPDIR}/minimum-config.json ; do
272
manifestListAddArtifactOnce
275
for layerTypeFlag in "" --artifact-layer-type=application/octet-stream --artifact-layer-type=text/plain ; do
276
manifestListAddArtifactOnce
278
for titleFlag in "" "--artifact-exclude-titles" ; do
279
manifestListAddArtifactOnce