# -*- 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=2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9" 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" # check logs output, IMPORTANT the container should write no logs to reproduce #23712 APIV2_TEST_EXPECT_TIMEOUT=1 t GET "containers/${CTRNAME}/logs?follow=true&stdout=true&stderr=true" 999 is "" "$(<$WORKDIR/curl.result.out)" "Container MUST NOT log output" like "$(<$WORKDIR/curl.headers.out)" ".*HTTP.* 200 OK.*" \ "Received headers from /container//logs" 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' # Regression check for #15036 (Umask) and #25026 (CreateCommand) t GET libpod/containers/${cid}/json 200 \ .Id=$cid \ .State.Status~\\\(exited\\\|stopped\\\) \ .State.Running=false \ .State.ExitCode=0 \ .Config.Umask=0022 \ .Config.CreateCommand=null \ .Config.HealthLogDestination=local \ .Config.HealthcheckMaxLogCount=5 \ .Config.HealthcheckMaxLogSize=500 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~"FROM docker\.io/.*" # 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" # Regression check for #25026 (CreateCommand) t GET libpod/containers/${cid}/json 200 \ .Id=$cid \ .Config.CreateCommand=null 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=2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9 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 compact API in rootless mode ignores ulimits https://github.com/containers/podman/issues/25881 t POST containers/create \ Image=$IMAGE \ HostConfig='{"Ulimits":[{"Name":"cpu","Soft":1,"Hard":2}]}' \ 201 \ .Id~[0-9a-f]\\{64\\} cid=$(jq -r '.Id' <<<"$output") t GET containers/$cid/json 200 \ .HostConfig.Ulimits[0].Name="RLIMIT_CPU" \ .HostConfig.Ulimits[0].Hard=2 \ .HostConfig.Ulimits[0].Soft=1 \ t DELETE containers/$cid 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 rm -f bar # confirm exposed port 8080 shows up in /containers/json podman run -d --rm --name bar --expose 8080 $IMAGE top t GET containers/json 200 \ .[0].Ports[0].PrivatePort=8080 \ .[0].Ports[0].Type="tcp" podman rm -f 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 # Create a temporary containers.conf with custom base_hosts_file set testdir=$(mktemp -d) cat > $testdir/containers.base_hosts_file.conf < $testdir/hosts <${TMPD}/update.json t POST libpod/containers/updateCtr/update ${TMPD}/update.json 201 cgroupPath=/sys/fs/cgroup/cpu.weight # Verify CPU weight 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 like "$(<$WORKDIR/curl.result.out)" $'^\x01.\(20\|5\)$' "cpu.weight is 5 or 20" BlkioDeviceReadBps_expected='[ { "Path": "/dev/nullb0", "Rate": 10485760 } ]' BlkioDeviceWriteBPs_expected='[ { "Path": "/dev/nullb0", "Rate": 31457280 } ]' BlkioDeviceReadIOPs_expected='[ { "Path": "/dev/nullb0", "Rate": 2000 } ]' BlkioDeviceWriteIOPs_expected='[ { "Path": "/dev/nullb0", "Rate": 4000 } ]' # Verify Device limits t GET containers/updateCtr/json 200 \ .HostConfig.BlkioDeviceReadBps="$BlkioDeviceReadBps_expected" \ .HostConfig.BlkioDeviceWriteBps="$BlkioDeviceWriteBPs_expected" \ .HostConfig.BlkioDeviceReadIOps="$BlkioDeviceReadIOPs_expected" \ .HostConfig.BlkioDeviceWriteIOps="$BlkioDeviceWriteIOPs_expected" \ # 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 # test apiv2 create container with empty entrypoint # --data '{"Image":"quay.io/libpod/some:thing","Entrypoint": []}' # Fixes #26078 podman image build -t test1:latest -<