mirror of
https://github.com/containers/podman.git
synced 2025-12-02 02:58:03 +08:00
We were only splitting on tabs, not spaces, so we returned just a single line most of the time, not an array of the fields in the output of `ps`. Unfortunately, some of these fields are allowed to contain spaces themselves, which makes things complicated, but we got lucky in that Docker took the simplest possible solution and just assumed that only one field would contain spaces and it would always be the last one, which is easy enough to duplicate on our end. Fixes #23981 Signed-off-by: Matt Heon <mheon@redhat.com>
718 lines
23 KiB
Bash
718 lines
23 KiB
Bash
# -*- sh -*-
|
|
#
|
|
# test container-related endpoints
|
|
#
|
|
|
|
# WORKDIR=/data
|
|
MultiTagName=localhost/test/testformultitag:tag
|
|
|
|
podman pull $IMAGE &>/dev/null
|
|
podman tag $IMAGE $MultiTagName
|
|
# Unimplemented
|
|
#t POST libpod/containers/create '' 201 'sdf'
|
|
|
|
# Ensure clean slate
|
|
podman rm -a -f &>/dev/null
|
|
|
|
t GET "libpod/containers/json (at start: clean slate)" 200 \
|
|
"[]" \
|
|
length=0
|
|
# check content type: https://github.com/containers/podman/issues/14647
|
|
response_headers=$(cat "$WORKDIR/curl.headers.out")
|
|
like "$response_headers" ".*Content-Type: application/json.*" "header does not contain application/json"
|
|
|
|
# Regression test for #12904 (race condition in logging code)
|
|
mytext="hi-there-$(random_string 15)"
|
|
podman run --rm -d --replace --name foo $IMAGE sh -c "echo $mytext;sleep 42"
|
|
# Logs output is prepended by ^A^Y (stdout = 1, length = 25 (with newline))
|
|
# Looks like it is missing the required 0 bytes from the message, why?
|
|
t POST "containers/foo/attach?logs=true&stream=false" 200 \
|
|
$'\001\031'$mytext
|
|
|
|
# check old docker header
|
|
response_headers=$(cat "$WORKDIR/curl.headers.out")
|
|
like "$response_headers" ".*Content-Type: application/vnd\.docker\.raw-stream.*" "vnd.docker.raw-stream docker v1.40"
|
|
# check new vnd.docker.multiplexed-stream header
|
|
t POST "/v1.42/containers/foo/attach?logs=true&stream=false" 200
|
|
response_headers=$(cat "$WORKDIR/curl.headers.out")
|
|
like "$response_headers" ".*Content-Type: application/vnd\.docker\.multiplexed-stream.*" "vnd.docker.multiplexed-stream docker v1.42"
|
|
t POST "/v4.6.0/libpod/containers/foo/attach?logs=true&stream=false" 200
|
|
response_headers=$(cat "$WORKDIR/curl.headers.out")
|
|
like "$response_headers" ".*Content-Type: application/vnd\.docker\.raw-stream.*" "vnd.docker.raw-stream libpod v4.6.0"
|
|
t POST "/v4.7.0/libpod/containers/foo/attach?logs=true&stream=false" 200
|
|
response_headers=$(cat "$WORKDIR/curl.headers.out")
|
|
like "$response_headers" ".*Content-Type: application/vnd\.docker\.multiplexed-stream.*" "vnd.docker.multiplexed-stream libpod v4.7.0"
|
|
|
|
t POST "containers/foo/attach?logs=true&stream=false" 101
|
|
response_headers=$(cat "$WORKDIR/curl.headers.out")
|
|
like "$response_headers" ".*Content-Type: application/vnd\.docker\.raw-stream.*" "hijacked connection header: Content-type: application/vnd.docker.raw-stream"
|
|
like "$response_headers" ".*Upgrade: tcp.*" "hijacked connection header: Upgrade: tcp"
|
|
|
|
t POST "containers/foo/kill" 204
|
|
|
|
podman run --replace --name=foo -v /tmp:/tmp $IMAGE true
|
|
# cannot kill non-running container
|
|
t POST "containers/foo/kill" 409
|
|
t POST "libpod/containers/foo/kill" 409
|
|
|
|
t GET libpod/containers/json 200 length=0
|
|
|
|
# bad all input
|
|
t GET libpod/containers/json?all='garb1age' 500 \
|
|
.cause="schema: error converting value for \"all\""
|
|
|
|
t GET libpod/containers/json?all=true 200 \
|
|
length=1 \
|
|
.[0].Id~[0-9a-f]\\{64\\} \
|
|
.[0].Image=$IMAGE \
|
|
.[0].Command[0]="true" \
|
|
.[0].State~\\\(exited\\\|stopped\\\) \
|
|
.[0].ExitCode=0 \
|
|
.[0].Mounts~.*/tmp \
|
|
.[0].IsInfra=false
|
|
|
|
# Test compat API for Network Settings (.Network is N/A when rootless)
|
|
network_expect="Networks.pasta.NetworkID=pasta"
|
|
if root; then
|
|
network_expect="Networks.podman.NetworkID=podman"
|
|
fi
|
|
t GET /containers/json?all=true 200 \
|
|
length=1 \
|
|
.[0].Id~[0-9a-f]\\{64\\} \
|
|
.[0].Image=$IMAGE \
|
|
.[0].Mounts~.*/tmp \
|
|
.[0].NetworkSettings.$network_expect
|
|
|
|
# compat API imageid with sha256: prefix
|
|
t GET containers/json?limit=1 200 \
|
|
.[0].ImageID~sha256:[0-9a-f]\\{64\\}
|
|
|
|
# Make sure `limit` works.
|
|
t GET libpod/containers/json?limit=1 200 \
|
|
length=1 \
|
|
.[0].Id~[0-9a-f]\\{64\\} \
|
|
.[0].Image=$IMAGE \
|
|
.[0].Command[0]="true" \
|
|
.[0].State~\\\(exited\\\|stopped\\\) \
|
|
.[0].ExitCode=0 \
|
|
.[0].IsInfra=false
|
|
|
|
# Make sure `last` works, which is an alias for `limit`.
|
|
# See https://github.com/containers/podman/issues/6413.
|
|
t GET libpod/containers/json?last=1 200 \
|
|
length=1 \
|
|
.[0].Id~[0-9a-f]\\{64\\} \
|
|
.[0].Image=$IMAGE \
|
|
.[0].Command[0]="true" \
|
|
.[0].State~\\\(exited\\\|stopped\\\) \
|
|
.[0].ExitCode=0 \
|
|
.[0].IsInfra=false
|
|
|
|
cid=$(jq -r '.[0].Id' <<<"$output")
|
|
|
|
t GET "libpod/containers/stats?containers=$cid&stream=false" 200 \
|
|
.memory_stats.max_usage=null
|
|
|
|
t DELETE libpod/containers/$cid 200 .[0].Id=$cid
|
|
|
|
# Issue #14676: make sure the stats show the memory limit specified for the container
|
|
if root; then
|
|
CTRNAME=ctr-with-limit
|
|
podman run --name $CTRNAME -d -m 512m -v /tmp:/tmp $IMAGE top
|
|
|
|
t GET libpod/containers/$CTRNAME/stats?stream=false 200 \
|
|
.memory_stats.limit=536870912 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
|
|
# Make sure docker compat endpoint shows "id" lowercase
|
|
t GET containers/$CTRNAME/stats?stream=false 200 \
|
|
.memory_stats.limit=536870912 \
|
|
.id~[0-9a-f]\\{64\\}
|
|
|
|
t GET containers/$CTRNAME/top?stream=false 200 \
|
|
.Titles='[
|
|
"UID",
|
|
"PID",
|
|
"PPID",
|
|
"C",
|
|
"STIME",
|
|
"TTY",
|
|
"TIME",
|
|
"CMD"
|
|
]'
|
|
|
|
podman rm -f $CTRNAME
|
|
fi
|
|
|
|
# Verify that compat top endpoint combines multi-entry COMMAND lines
|
|
CTRNAME=testtopproc
|
|
podman run --name $CTRNAME -d $IMAGE sleep 25
|
|
t GET containers/$CTRNAME/top?stream=false 200 \
|
|
.Processes.[0].[6]="00:00:00" \
|
|
.Processes.[0].[7]="sleep 25"
|
|
podman rm -f -t0 $CTRNAME
|
|
|
|
CTRNAME=test123
|
|
podman run --name $CTRNAME -d $IMAGE top
|
|
t GET libpod/containers/$CTRNAME/top?ps_args=--invalid 500 \
|
|
.cause~".*unknown gnu long option.*"
|
|
t GET containers/$CTRNAME/top?ps_args=--invalid 500 \
|
|
.cause~".*unknown gnu long option.*"
|
|
|
|
podman rm -f $CTRNAME
|
|
|
|
# Issue #15765: make sure the memory limit is capped
|
|
if root; then
|
|
CTRNAME=ctr-with-limit
|
|
podman run --name $CTRNAME -d -m 512m -v /tmp:/tmp $IMAGE top
|
|
|
|
t GET libpod/containers/$CTRNAME/stats?stream=false 200 \
|
|
.memory_stats.limit!=18446744073709552000
|
|
|
|
podman rm -f $CTRNAME
|
|
fi
|
|
|
|
# Container create without existing image should return 404
|
|
t POST libpod/containers/create Image="foo" 404 \
|
|
.cause="image not known"
|
|
|
|
# Issue #6799: it should be possible to start a container, even w/o args.
|
|
t POST libpod/containers/create?name=test_noargs Image=${IMAGE} 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
# Prior to the fix in #6835, this would fail 500 "args must not be empty"
|
|
t POST libpod/containers/${cid}/start 204
|
|
# Container should exit almost immediately. Wait for it, confirm successful run
|
|
t POST "libpod/containers/${cid}/wait?condition=stopped&condition=exited" 200 '0'
|
|
t GET libpod/containers/${cid}/json 200 \
|
|
.Id=$cid \
|
|
.State.Status~\\\(exited\\\|stopped\\\) \
|
|
.State.Running=false \
|
|
.State.ExitCode=0 \
|
|
.Config.Umask=0022 # regression check for #15036
|
|
t DELETE libpod/containers/$cid 200 .[0].Id=$cid
|
|
|
|
CNAME=myfoo
|
|
podman run -d --name $CNAME $IMAGE top
|
|
t GET libpod/containers/json?all=true 200 \
|
|
.[0].Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.[0].Id' <<<"$output")
|
|
|
|
# No such container
|
|
t POST "libpod/commit?container=nonesuch" 404
|
|
|
|
# Comment can only be used with docker format, not OCI
|
|
cparam="repo=newrepo&comment=foo&author=bob"
|
|
t POST "libpod/commit?container=$CNAME&$cparam" 500 \
|
|
.cause="messages are only compatible with the docker image format (-f docker)"
|
|
|
|
# Commit a new image from the container
|
|
t POST "libpod/commit?container=$CNAME" 200 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
iid=$(jq -r '.Id' <<<"$output")
|
|
t GET libpod/images/$iid/json 200 \
|
|
.RepoTags[0]=null \
|
|
.Author="" \
|
|
.Comment=""
|
|
|
|
# Commit a new image w/o tag
|
|
cparam="repo=newrepo&comment=foo&author=bob&format=docker"
|
|
t POST "libpod/commit?container=$CNAME&$cparam" 200
|
|
t GET libpod/images/newrepo:latest/json 200 \
|
|
.RepoTags[0]=localhost/newrepo:latest \
|
|
.Author=bob \
|
|
.Comment=foo
|
|
|
|
# Commit a new image w/ specified tag and author
|
|
cparam="repo=newrepo&tag=v1&author=alice"
|
|
t POST "libpod/commit?container=$cid&$cparam&pause=false" 200
|
|
t GET libpod/images/newrepo:v1/json 200 \
|
|
.RepoTags[0]=localhost/newrepo:v1 \
|
|
.Author=alice
|
|
|
|
# Commit a new image w/ full parameters
|
|
cparam="repo=newrepo&tag=v2&comment=bar&author=eric"
|
|
cparam="$cparam&format=docker&changes=CMD=/bin/foo"
|
|
|
|
t POST "libpod/commit?container=${cid:0:12}&$cparam&pause=true" 200
|
|
t GET libpod/images/newrepo:v2/json 200 \
|
|
.RepoTags[0]=localhost/newrepo:v2 \
|
|
.Author=eric \
|
|
.Comment=bar \
|
|
.Config.Cmd[-1]="/bin/foo"
|
|
t DELETE images/localhost/newrepo:v2?force=true 200
|
|
|
|
# Create a container for testing the container initializing later
|
|
podman create -t -i --name myctr $IMAGE ls
|
|
|
|
# Check configuration before initializing
|
|
t GET libpod/containers/myctr/json 200 \
|
|
.Id~[0-9a-f]\\{64\\} \
|
|
.State.Status="created" \
|
|
.State.Pid=0 \
|
|
.ResolvConfPath="" \
|
|
.HostnamePath="" \
|
|
.HostsPath="" \
|
|
.NetworkSettings.SandboxKey=""
|
|
|
|
cpid_file=$(jq -r '.ConmonPidFile' <<<"$output")
|
|
userdata_path=$(dirname $cpid_file)
|
|
|
|
# Initializing the container
|
|
t POST libpod/containers/myctr/init 204
|
|
|
|
# Check configuration after initializing
|
|
t GET libpod/containers/myctr/json 200 \
|
|
.Id~[0-9a-f]\\{64\\} \
|
|
.State.Status="initialized" \
|
|
.State.Pid~[0-9]\\{1\,8\\} \
|
|
.ResolvConfPath=$userdata_path/resolv.conf \
|
|
.HostnamePath=$userdata_path/hostname \
|
|
.HostsPath=$userdata_path/hosts \
|
|
.NetworkSettings.SandboxKey~.*/netns/netns- \
|
|
.OCIConfigPath~.*config\.json \
|
|
.GraphDriver.Data.MergedDir~.*merged
|
|
|
|
# Test TS are in UTC
|
|
t GET containers/myctr/json 200 \
|
|
.Created~.*Z \
|
|
.State.StartedAt~.*Z \
|
|
.State.FinishedAt~.*Z
|
|
|
|
t DELETE images/localhost/newrepo:latest?force=true 200
|
|
t DELETE images/localhost/newrepo:v1?force=true 200
|
|
t DELETE libpod/containers/$cid?force=true 200 .[0].Id=$cid
|
|
t DELETE libpod/containers/myctr 200
|
|
t DELETE libpod/containers/bogus 404
|
|
|
|
|
|
# test apiv2 create container with correct entrypoint and cmd
|
|
# --data '{"Image":"quay.io/libpod/some:thing","Entrypoint":["echo"],"Cmd":["param1","param2"]}'
|
|
t POST containers/create \
|
|
Image=$IMAGE \
|
|
Entrypoint='["echo"]' \
|
|
Cmd='["param1","param2"]' \
|
|
201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.Config.Entrypoint[0]="echo" \
|
|
.Config.Cmd[0]="param1" \
|
|
.Config.Cmd[1]="param2" \
|
|
.Path="echo" \
|
|
.Args[0]="param1" \
|
|
.Args[1]="param2"
|
|
t DELETE containers/$cid 204
|
|
|
|
# test only set the entrypoint, Cmd should be []
|
|
t POST containers/create \
|
|
Image=$IMAGE \
|
|
Entrypoint='["echo","param1"]' \
|
|
201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.Config.Entrypoint[0]="echo" \
|
|
.Config.Entrypoint[1]="param1" \
|
|
.Config.Cmd='[]' \
|
|
.Path="echo" \
|
|
.Args[0]="param1"
|
|
|
|
# create a running container for after
|
|
t POST containers/create Image=$IMAGE Entrypoint='["top"]' 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid_top=$(jq -r '.Id' <<<"$output")
|
|
|
|
t GET containers/${cid_top}/json 200 \
|
|
.Config.Entrypoint[0]="top" \
|
|
.Config.Cmd='[]' \
|
|
.Config.StopTimeout="10" \
|
|
.Path="top" \
|
|
.NetworkSettings.Networks.podman.NetworkID=podman
|
|
t POST containers/${cid_top}/start 204
|
|
# make sure the container is running
|
|
t GET containers/${cid_top}/json 200 \
|
|
.State.Status="running"
|
|
|
|
# 0 means unlimited, need same with docker
|
|
t GET containers/json?limit=0 200 \
|
|
.[0].Id~[0-9a-f]\\{64\\}
|
|
|
|
t GET 'containers/json?limit=0&all=1' 200 \
|
|
.[0].Id~[0-9a-f]\\{64\\} \
|
|
.[1].Id~[0-9a-f]\\{64\\}
|
|
|
|
t GET containers/json?limit=2 200 length=2
|
|
|
|
# Filter with two ids should return both container
|
|
t GET containers/json?filters='{"id":["'${cid}'","'${cid_top}'"]}&all=1' 200 length=2
|
|
# Filter with two ids and status running should return only 1 container
|
|
t GET containers/json?filters='{"id":["'${cid}'","'${cid_top}'"],"status":["running"]}&all=1' 200 \
|
|
length=1 \
|
|
.[0].Id=${cid_top}
|
|
|
|
t POST containers/${cid_top}/stop 204
|
|
|
|
t DELETE containers/$cid 204
|
|
t DELETE containers/$cid_top 204
|
|
|
|
# test the WORKDIR and StopSignal
|
|
t POST containers/create \
|
|
Image=$IMAGE \
|
|
WorkingDir=/dataDir \
|
|
StopSignal=\"9\" \
|
|
201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.Config.WorkingDir="/dataDir" \
|
|
.Config.StopSignal="9"
|
|
|
|
t DELETE containers/$cid 204
|
|
|
|
# when the image had multi tags, the container's Image should be correct
|
|
# Fixes https://github.com/containers/podman/issues/8547
|
|
t POST containers/create Image=${MultiTagName} 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.Config.Image=${MultiTagName} \
|
|
.Image~sha256:[0-9a-f]\\{64\\}
|
|
|
|
t DELETE containers/$cid 204
|
|
t DELETE images/${MultiTagName} 200
|
|
# vim: filetype=sh
|
|
|
|
# Test Volumes field adds an anonymous volume
|
|
t POST containers/create Image=$IMAGE Volumes='{"/test":{}}' 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.Mounts[0].Destination="/test"
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# Test Volumes with bind mount, for some reason docker-py sets this #18454
|
|
t POST containers/create Image=$IMAGE Volumes='{"/test/":{}}' HostConfig='{"Binds":["/tmp:/test/:ro"]}' 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.Mounts[0].Destination="/test/"
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# test port mapping
|
|
podman run -d --rm --name bar -p 8080:9090 $IMAGE top
|
|
|
|
t GET containers/json 200 \
|
|
.[0].Ports[0].PrivatePort=9090 \
|
|
.[0].Ports[0].PublicPort=8080 \
|
|
.[0].Ports[0].Type="tcp"
|
|
|
|
podman stop bar
|
|
|
|
#compat api list containers sanity checks
|
|
podman run -d --rm --name labelcontainer_with --label slartibart=fast $IMAGE top
|
|
podman run -d --rm --name labelcontainer_without $IMAGE top
|
|
|
|
t GET containers/json?filters='garb1age}' 500 \
|
|
.cause="invalid character 'g' looking for beginning of value"
|
|
t GET containers/json?filters='{"label":["testl' 500 \
|
|
.cause="unexpected end of JSON input"
|
|
|
|
|
|
#libpod api list containers sanity checks
|
|
t GET libpod/containers/json?filters='{"status":["removing"]}' 200 length=0
|
|
t GET libpod/containers/json?filters='{"status":["bogus"]}' 500 \
|
|
.cause="invalid argument"
|
|
t GET libpod/containers/json?filters='garb1age}' 500 \
|
|
.cause="invalid character 'g' looking for beginning of value"
|
|
t GET libpod/containers/json?filters='{"label":["testl' 500 \
|
|
.cause="unexpected end of JSON input"
|
|
|
|
# Prune containers - bad filter input
|
|
t POST containers/prune?filters='garb1age}' 500 \
|
|
.cause="invalid character 'g' looking for beginning of value"
|
|
t POST libpod/containers/prune?filters='garb1age}' 500 \
|
|
.cause="invalid character 'g' looking for beginning of value"
|
|
|
|
# Prune containers with illformed label
|
|
t POST containers/prune?filters='{"label":["tes' 500 \
|
|
.cause="unexpected end of JSON input"
|
|
t POST libpod/containers/prune?filters='{"label":["tes' 500 \
|
|
.cause="unexpected end of JSON input"
|
|
|
|
t GET libpod/containers/json?filters='{"label":["slartibart"]}' 200 \
|
|
length=1 \
|
|
.[0].Names[0]="labelcontainer_with"
|
|
t GET libpod/containers/json?filters='{"label!":["slartibart"]}' 200 \
|
|
length=1 \
|
|
.[0].Names[0]="labelcontainer_without"
|
|
t GET libpod/containers/json?filters='{"label!":["testlabel"]}' 200 length=2
|
|
|
|
podman stop -t0 labelcontainer_with labelcontainer_without
|
|
|
|
# libpod api: do not use list filters for prune
|
|
t POST libpod/containers/prune?filters='{"name":["anyname"]}' 500 \
|
|
.cause="name is an invalid filter"
|
|
t POST libpod/containers/prune?filters='{"id":["anyid"]}' 500 \
|
|
.cause="id is an invalid filter"
|
|
t POST libpod/containers/prune?filters='{"network":["anynetwork"]}' 500 \
|
|
.cause="network is an invalid filter"
|
|
|
|
# compat api: do not use list filters for prune
|
|
t POST containers/prune?filters='{"name":["anyname"]}' 500 \
|
|
.cause="name is an invalid filter"
|
|
t POST containers/prune?filters='{"id":["anyid"]}' 500 \
|
|
.cause="id is an invalid filter"
|
|
t POST containers/prune?filters='{"network":["anynetwork"]}' 500 \
|
|
.cause="network is an invalid filter"
|
|
|
|
# Test CPU limit (NanoCPUs)
|
|
nanoCpu=500000
|
|
t POST containers/create Image=$IMAGE HostConfig='{"NanoCpus":500000}' 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.HostConfig.NanoCpus=$nanoCpu
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# Test Compat Create with default network mode (#10569)
|
|
t POST containers/create Image=$IMAGE HostConfig='{"NetworkMode":"default"}' 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.HostConfig.NetworkMode="bridge"
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# test create with default netns="host"
|
|
stop_service
|
|
CONTAINERS_CONF=$TESTS_DIR/containers.host-netns.conf start_service
|
|
|
|
# check that the default docker netns "default" is rewritten to "host"
|
|
# when the containers.conf explicitly uses "host"
|
|
t POST containers/create Image=$IMAGE HostConfig='{"NetworkMode":"default"}' 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.HostConfig.NetworkMode="host"
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# test create container like Docker >= 25 cli: NetworkMode="default" but EndpointsConfig struct is explicitly set and netns="host"
|
|
t POST containers/create \
|
|
Image=$IMAGE \
|
|
HostConfig='{"NetworkMode":"default"}' \
|
|
NetworkingConfig='{"EndpointsConfig":{"default":{"IPAMConfig":null,"Links":null,"Aliases":null,"MacAddress":"","NetworkID":"","EndpointID":"","Gateway":"","IPAddress":"","IPPrefixLen":0,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"DriverOpts":null,"DNSNames":null}}}' \
|
|
201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.HostConfig.NetworkMode="host"
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# test creating a container fails with netns="hosts" on podman side but keep using the default network mode
|
|
# on docker CLI side and trying to use --ip 1.2.3.4 which is only valid for the bridge network mode (docker CLI
|
|
# will assume the default is the bridge mode, so it's valid from docker CLI point of view).
|
|
t POST containers/create \
|
|
Image=$IMAGE \
|
|
HostConfig='{"NetworkMode":"default"}' \
|
|
NetworkingConfig='{"EndpointsConfig":{"default":{"IPAMConfig":null,"Links":null,"Aliases":null,"MacAddress":"","NetworkID":"","EndpointID":"","Gateway":"","IPAddress":"1.2.3.4","IPPrefixLen":0,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"DriverOpts":null,"DNSNames":null}}}' \
|
|
500 \
|
|
.cause="networks and static ip/mac address can only be used with Bridge mode networking"
|
|
|
|
# Restart with the default containers.conf for next tests.
|
|
stop_service
|
|
start_service
|
|
|
|
# Test Compat Create with healthcheck, check default values
|
|
t POST containers/create Image=$IMAGE Cmd='["top"]' Healthcheck='{"Test":["true"]}' 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.Config.Healthcheck.Interval=30000000000 \
|
|
.Config.Healthcheck.Timeout=30000000000 \
|
|
.Config.Healthcheck.Retries=3
|
|
|
|
# compat api: Test for mount options support
|
|
# Sigh, JSON can't handle octal. 0755(octal) = 493(decimal)
|
|
payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch","TmpfsOptions":{"SizeBytes":1024,"Mode":493}}]}'
|
|
t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.HostConfig.Tmpfs['"/mnt/scratch"']~.*size=1024.* \
|
|
.HostConfig.Tmpfs['"/mnt/scratch"']~.*mode=755.*
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# compat api: tmpfs without mount options
|
|
payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch"}]}'
|
|
t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.HostConfig.Tmpfs['"/mnt/scratch"']~.*tmpcopyup.* \
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# compat api: bind mount without mount options
|
|
payload='{"Mounts":[{"Type":"bind","Source":"/tmp","Target":"/mnt"}]}'
|
|
t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
t GET containers/$cid/json 200 \
|
|
.HostConfig.Binds[0]~/tmp:/mnt:.* \
|
|
|
|
t DELETE containers/$cid?v=true 204
|
|
|
|
# test apiv2 create/commit
|
|
t POST containers/create \
|
|
Image=$IMAGE \
|
|
Entrypoint='["echo"]' \
|
|
Cmd='["param1","param2"]' \
|
|
201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
|
|
# No such container
|
|
t POST "commit?container=nonesuch" 404
|
|
|
|
cparam="repo=newrepo&tag=v3&comment=abcd&author=eric"
|
|
cparam="$cparam&format=docker&changes=CMD%20/bin/bar%0aEXPOSE%209090"
|
|
t POST "commit?container=${cid:0:12}&$cparam" 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
iid=$(jq -r '.Id' <<<"$output")
|
|
t GET images/$iid/json 200 \
|
|
.RepoTags[0]=docker.io/library/newrepo:v3 \
|
|
.Config.ExposedPorts~.*"9090/tcp" \
|
|
.Config.Cmd~.*"/bin/bar" \
|
|
.Comment="abcd"
|
|
|
|
t DELETE containers/$cid 204
|
|
t DELETE images/docker.io/library/newrepo:v3?force=false 200
|
|
|
|
# test create without default no_hosts
|
|
t POST containers/create \
|
|
Image=$IMAGE \
|
|
201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
|
|
t POST libpod/containers/$cid/init 204
|
|
|
|
t GET libpod/containers/$cid/json 200
|
|
|
|
cpid_file=$(jq -r '.ConmonPidFile' <<<"$output")
|
|
userdata_path=$(dirname $cpid_file)
|
|
|
|
t GET libpod/containers/$cid/json 200 \
|
|
.HostsPath=$userdata_path/hosts
|
|
|
|
t DELETE containers/$cid 204
|
|
|
|
# test create with default no_hosts=true
|
|
stop_service
|
|
|
|
CONTAINERS_CONF=$TESTS_DIR/containers.no_hosts.conf start_service
|
|
|
|
# check docker and libpod endpoint
|
|
for endpoint in containers/create libpod/containers/create; do
|
|
t POST $endpoint \
|
|
Image=$IMAGE \
|
|
201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
cid=$(jq -r '.Id' <<<"$output")
|
|
|
|
t POST libpod/containers/$cid/init 204
|
|
|
|
t GET libpod/containers/$cid/json 200 \
|
|
.HostsPath=""
|
|
|
|
t DELETE containers/$cid 204
|
|
done
|
|
|
|
stop_service
|
|
start_service
|
|
|
|
# Our states are different from Docker's.
|
|
# Regression test for #14700 (Docker compat returning unknown "initialized" for status.status) to ensure the stay compatible
|
|
podman create --name status-test $IMAGE sh -c "sleep 3"
|
|
t GET containers/status-test/json 200 .State.Status="created"
|
|
|
|
podman init status-test
|
|
t GET containers/status-test/json 200 .State.Status="created"
|
|
|
|
podman start status-test
|
|
t GET containers/status-test/json 200 .State.Status="running"
|
|
|
|
podman pause status-test
|
|
t GET containers/status-test/json 200 .State.Status="paused"
|
|
|
|
podman unpause status-test
|
|
t GET containers/status-test/json 200 .State.Status="running"
|
|
|
|
podman stop status-test &
|
|
sleep 1
|
|
t GET containers/status-test/json 200 .State.Status="stopping"
|
|
|
|
sleep 3
|
|
t GET containers/status-test/json 200 .State.Status="exited"
|
|
|
|
# test podman generate spec as input for the api
|
|
cname=specgen$(random_string 10)
|
|
podman create --name=$cname $IMAGE
|
|
|
|
TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX)
|
|
|
|
podman generate spec -f ${TMPD}/myspec.json -c $cname
|
|
|
|
# Create a container based on that spec
|
|
t POST libpod/containers/create ${TMPD}/myspec.json 201 \
|
|
.Id~[0-9a-f]\\{64\\}
|
|
|
|
# Verify
|
|
t GET libpod/containers/$cname/json 200 \
|
|
.ImageName=$IMAGE \
|
|
.Name=$cname
|
|
|
|
if root; then
|
|
podman run -dt --name=updateCtr alpine
|
|
echo '{"Memory":{"Limit":500000}, "CPU":{"Shares":123}}' >${TMPD}/update.json
|
|
t POST libpod/containers/updateCtr/update ${TMPD}/update.json 201
|
|
|
|
cgroupPath=/sys/fs/cgroup/cpu.weight
|
|
# 002 is the byte length
|
|
cpu_weight_expect=$'\001\0025'
|
|
|
|
# Verify
|
|
echo '{ "AttachStdout":true,"Cmd":["cat", "'$cgroupPath'"]}' >${TMPD}/exec.json
|
|
t POST containers/updateCtr/exec ${TMPD}/exec.json 201 .Id~[0-9a-f]\\{64\\}
|
|
eid=$(jq -r '.Id' <<<"$output")
|
|
t POST exec/$eid/start 200 $cpu_weight_expect
|
|
|
|
# Now use the compat API
|
|
echo '{ "Memory": 536870912 }' >${TMPD}/compatupdate.json
|
|
t POST containers/updateCtr/update ${TMPD}/compatupdate.json 200
|
|
t GET libpod/containers/updateCtr/json 200 \
|
|
.HostConfig.Memory=536870912
|
|
|
|
podman rm -f updateCtr
|
|
fi
|
|
|
|
rm -rf $TMPD
|
|
|
|
podman container rm -fa
|
|
|
|
# 18951: Make sure container create supports the platform parameter. Force an
|
|
# initial architecture to make sure the test runs on all platforms.
|
|
podman pull --platform=linux/amd64 $IMAGE
|
|
t POST containers/create?platform=linux/amd64 \
|
|
Image=$IMAGE \
|
|
201
|
|
t POST containers/create?platform=linux/aarch64 \
|
|
Image=$IMAGE \
|
|
404
|
|
podman rmi -f $IMAGE
|