github.com/containers/podman/v5@v5.1.0-rc1/test/system/200-pod.bats (about)

     1  #!/usr/bin/env bats
     2  
     3  load helpers
     4  load helpers.network
     5  
     6  LOOPDEVICE=
     7  
     8  # This is a long ugly way to clean up pods and remove the pause image
     9  function teardown() {
    10      run_podman pod rm -f -t 0 -a
    11      run_podman rm -f -t 0 -a
    12      run_podman rmi --ignore $(pause_image)
    13      basic_teardown
    14      if [[ -n "$LOOPDEVICE" ]]; then
    15          losetup -d $LOOPDEVICE
    16      fi
    17  }
    18  
    19  
    20  @test "podman pod - basic tests" {
    21      run_podman pod list --noheading
    22      is "$output" "" "baseline: empty results from list --noheading"
    23  
    24      run_podman pod ls -n
    25      is "$output" "" "baseline: empty results from ls -n"
    26  
    27      run_podman pod ps --noheading
    28      is "$output" "" "baseline: empty results from ps --noheading"
    29  }
    30  
    31  @test "podman pod top - containers in different PID namespaces" {
    32      # With infra=false, we don't get a /pause container
    33      no_infra='--infra=false'
    34      run_podman pod create $no_infra
    35      podid="$output"
    36  
    37      # Start two containers...
    38      run_podman run -d --pod $podid $IMAGE top -d 2
    39      cid1="$output"
    40      run_podman run -d --pod $podid $IMAGE top -d 2
    41      cid2="$output"
    42  
    43      # ...and wait for them to actually start.
    44      wait_for_output "PID \+PPID \+USER " $cid1
    45      wait_for_output "PID \+PPID \+USER " $cid2
    46  
    47      # Both containers have emitted at least one top-like line.
    48      # Now run 'pod top', and expect two 'top -d 2' processes running.
    49      run_podman pod top $podid
    50      is "$output" ".*root.*top -d 2.*root.*top -d 2" "two 'top' containers"
    51  
    52      # By default (podman pod create w/ default --infra) there should be
    53      # a /pause container.
    54      if [ -z "$no_infra" ]; then
    55          is "$output" ".*0 \+1 \+0 \+[0-9. ?s]\+/pause" "there is a /pause container"
    56      fi
    57  
    58      # Cannot remove pod while containers are still running. Error messages
    59      # differ slightly between local and remote; these are the common elements.
    60      run_podman 125 pod rm $podid
    61      assert "${lines[0]}" =~ "Error: not all containers could be removed from pod $podid: removing pod containers.*" \
    62             "pod rm while busy: error message line 1 of 3"
    63      assert "${lines[1]}" =~ "cannot remove container .* as it is running - running or paused containers cannot be removed without force: container state improper" \
    64             "pod rm while busy: error message line 2 of 3"
    65      assert "${lines[2]}" =~ "cannot remove container .* as it is running - running or paused containers cannot be removed without force: container state improper" \
    66             "pod rm while busy: error message line 3 of 3"
    67  
    68      # Clean up
    69      run_podman --noout pod rm -f -t 0 $podid
    70      is "$output" "" "output should be empty"
    71  }
    72  
    73  
    74  @test "podman pod create - custom volumes" {
    75      skip_if_remote "CONTAINERS_CONF_OVERRIDE only affects server side"
    76      image="i.do/not/exist:image"
    77      tmpdir=$PODMAN_TMPDIR/pod-test
    78      mkdir -p $tmpdir
    79      containersconf=$tmpdir/containers.conf
    80      cat >$containersconf <<EOF
    81  [containers]
    82  volumes = ["/tmp:/foobar"]
    83  EOF
    84  
    85      CONTAINERS_CONF_OVERRIDE=$containersconf run_podman pod create
    86      podid="$output"
    87  
    88      CONTAINERS_CONF_OVERRIDE=$containersconf run_podman create --pod $podid $IMAGE grep foobar /proc/mounts
    89  }
    90  
    91  
    92  @test "podman pod create - custom infra image" {
    93      skip_if_remote "CONTAINERS_CONF_OVERRIDE only affects server side"
    94      image="i.do/not/exist:image"
    95      tmpdir=$PODMAN_TMPDIR/pod-test
    96      mkdir -p $tmpdir
    97      containersconf=$tmpdir/containers.conf
    98      cat >$containersconf <<EOF
    99  [engine]
   100  infra_image="$image"
   101  EOF
   102  
   103      run_podman 125 pod create --infra-image $image
   104      is "$output" ".*initializing source docker://$image:.*"
   105  
   106      CONTAINERS_CONF_OVERRIDE=$containersconf run_podman 125 pod create
   107      is "$output" ".*initializing source docker://$image:.*"
   108  
   109      CONTAINERS_CONF_OVERRIDE=$containersconf run_podman 125 create --pod new:test $IMAGE
   110      is "$output" ".*initializing source docker://$image:.*"
   111  }
   112  
   113  @test "podman pod - communicating between pods" {
   114      podname=pod$(random_string)
   115      run_podman 1 pod exists $podname
   116      run_podman pod create --infra=true --name=$podname
   117      podid="$output"
   118      run_podman pod exists $podname
   119      run_podman pod exists $podid
   120  
   121      # (Assert that output is formatted, not a one-line blob: #8021)
   122      run_podman pod inspect $podname
   123      assert "${#lines[*]}" -ge 10 "Output from 'pod inspect'; see #8011"
   124  
   125      # Randomly-assigned port in the 5xxx range
   126      port=$(random_free_port)
   127  
   128      # Listener. This will exit as soon as it receives a message.
   129      run_podman run -d --pod $podname $IMAGE nc -l -p $port
   130      cid1="$output"
   131  
   132      # (While we're here, test the 'Pod' field of 'podman ps'. Expect two ctrs)
   133      run_podman ps --format '{{.Pod}}'
   134      newline="
   135  "
   136      is "$output" "${podid:0:12}${newline}${podid:0:12}" "ps shows 2 pod IDs"
   137  
   138      # Talker: send the message via common port on localhost
   139      message=$(random_string 15)
   140      run_podman run --rm --pod $podname $IMAGE \
   141                 sh -c "echo $message | nc 127.0.0.1 $port"
   142  
   143      # Back to the first (listener) container. Make sure message was received.
   144      run_podman logs $cid1
   145      is "$output" "$message" "message sent from one container to another"
   146  
   147      # Clean up. First the nc -l container...
   148      run_podman rm $cid1
   149  
   150      # ...then rm the pod, then rmi the pause image so we don't leave strays.
   151      run_podman pod rm $podname
   152  
   153      # Pod no longer exists
   154      run_podman 1 pod exists $podid
   155      run_podman 1 pod exists $podname
   156  }
   157  
   158  @test "podman pod - communicating via /dev/shm " {
   159      podname=pod$(random_string)
   160      run_podman 1 pod exists $podname
   161      run_podman pod create --infra=true --name=$podname
   162      podid="$output"
   163      run_podman pod exists $podname
   164      run_podman pod exists $podid
   165  
   166      run_podman run --rm --pod $podname $IMAGE touch /dev/shm/test1
   167      run_podman run --rm --pod $podname $IMAGE ls /dev/shm/test1
   168      is "$output" "/dev/shm/test1"
   169  
   170      # ...then rm the pod, then rmi the pause image so we don't leave strays.
   171      run_podman pod rm $podname
   172  
   173      # Pod no longer exists
   174      run_podman 1 pod exists $podid
   175      run_podman 1 pod exists $podname
   176  }
   177  
   178  # Random byte
   179  function octet() {
   180      echo $(( $RANDOM & 255 ))
   181  }
   182  
   183  # random MAC address: convention seems to be that 2nd lsb=1, lsb=0
   184  # (i.e. 0bxxxxxx10) in the first octet guarantees a private space.
   185  # FIXME: I can't find a definitive reference for this though
   186  # Generate the address IN CAPS (A-F), but we will test it in lowercase.
   187  function random_mac() {
   188      local mac=$(printf "%02X" $(( $(octet) & 242 | 2 )) )
   189      for i in $(seq 2 6); do
   190          mac+=$(printf ":%02X" $(octet))
   191      done
   192  
   193      echo $mac
   194  }
   195  
   196  # Random RFC1918 IP address
   197  function random_ip() {
   198      local ip="172.20"
   199      for i in 1 2;do
   200          ip+=$(printf ".%d" $(octet))
   201      done
   202      echo $ip
   203  }
   204  
   205  @test "podman pod create - hashtag AllTheOptions" {
   206      mac=$(random_mac)
   207      add_host_ip=$(random_ip)
   208      add_host_n=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).xyz
   209  
   210      dns_server=$(random_ip)
   211      dns_opt="ndots:$(octet)"
   212      dns_search=$(random_string 15 | tr A-Z a-z).abc
   213  
   214      hostname=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).net
   215  
   216      labelname=$(random_string 11)
   217      labelvalue=$(random_string 22)
   218  
   219      pod_id_file=${PODMAN_TMPDIR}/pod-id-file
   220  
   221      # Randomly-assigned ports in the 5xxx and 6xxx range
   222      port_in=$(random_free_port 5000-5999)
   223      port_out=$(random_free_port 6000-6999)
   224  
   225      # Create a pod with all the desired options
   226      # FIXME: --ip=$ip fails:
   227      #      Error adding network: failed to allocate all requested IPs
   228      local mac_option="--mac-address=$mac"
   229  
   230      # Create a custom image so we can test --infra-image and -command.
   231      # It will have a randomly generated infra command, using the
   232      # existing 'pause' script in our testimage. We assign a bogus
   233      # entrypoint to confirm that --infra-command will override.
   234      local infra_image="infra_$(random_string 10 | tr A-Z a-z)"
   235      local infra_command="/pause_$(random_string 10)"
   236      local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)"
   237      run_podman build -t $infra_image - << EOF
   238  FROM $IMAGE
   239  RUN ln /home/podman/pause $infra_command
   240  ENTRYPOINT ["/original-entrypoint-should-be-overridden"]
   241  EOF
   242  
   243      if is_rootless; then
   244          mac_option=
   245      fi
   246      run_podman pod create --name=mypod                   \
   247                 --pod-id-file=$pod_id_file                \
   248                 $mac_option                               \
   249                 --hostname=$hostname                      \
   250                 --add-host   "$add_host_n:$add_host_ip"   \
   251                 --dns        "$dns_server"                \
   252                 --dns-search "$dns_search"                \
   253                 --dns-option "$dns_opt"                   \
   254                 --publish    "$port_out:$port_in"         \
   255                 --label      "${labelname}=${labelvalue}" \
   256                 --infra-image   "$infra_image"            \
   257                 --infra-command "$infra_command"          \
   258                 --infra-name "$infra_name"
   259      pod_id="$output"
   260  
   261      # Check --pod-id-file
   262      is "$(<$pod_id_file)" "$pod_id" "contents of pod-id-file"
   263  
   264      # Get ID of infra container
   265      run_podman pod inspect --format '{{(index .Containers 0).ID}}' mypod
   266      local infra_cid="$output"
   267      # confirm that entrypoint is what we set
   268      run_podman container inspect --format '{{.Config.Entrypoint}}' $infra_cid
   269      is "$output" "[${infra_command}]" "infra-command took effect"
   270      # confirm that infra container name is set
   271      run_podman container inspect --format '{{.Name}}' $infra_cid
   272      is "$output" "$infra_name" "infra-name took effect"
   273  
   274      # Check each of the options
   275      if [ -n "$mac_option" ]; then
   276          run_podman run --rm --pod mypod $IMAGE ip link show
   277          # 'ip' outputs hex in lower-case, ${expr,,} converts UC to lc
   278          is "$output" ".* link/ether ${mac,,} " "requested MAC address was set"
   279      fi
   280  
   281      run_podman run --rm --pod mypod $IMAGE hostname
   282      is "$output" "$hostname" "--hostname set the hostname"
   283      run_podman 125 run --rm --pod mypod --hostname foobar $IMAGE hostname
   284      is "$output" ".*invalid config provided: cannot set hostname when joining the pod UTS namespace: invalid configuration" "--hostname should not be allowed in share UTS pod"
   285  
   286      run_podman run --rm --pod $pod_id $IMAGE cat /etc/hosts
   287      is "$output" ".*$add_host_ip[[:blank:]]$add_host_n" "--add-host was added"
   288      is "$output" ".*	$hostname"            "--hostname is in /etc/hosts"
   289      #               ^^^^ this must be a tab, not a space
   290  
   291      run_podman run --rm --pod mypod $IMAGE cat /etc/resolv.conf
   292      is "$output" ".*nameserver $dns_server"  "--dns [server] was added"
   293      is "$output" ".*search $dns_search"      "--dns-search was added"
   294      is "$output" ".*options $dns_opt"        "--dns-option was added"
   295  
   296      # pod inspect
   297      run_podman pod inspect --format '{{.Name}}: {{.ID}} : {{.NumContainers}} : {{.Labels}}' mypod
   298      is "$output" "mypod: $pod_id : 1 : map\[${labelname}:${labelvalue}]" \
   299         "pod inspect --format ..."
   300  
   301      # pod ps
   302      run_podman pod ps --format '{{.ID}} {{.Name}} {{.Status}} {{.Labels}}'
   303      is "$output" "${pod_id:0:12} mypod Running map\[${labelname}:${labelvalue}]"  "pod ps"
   304  
   305      run_podman pod ps --no-trunc --filter "label=${labelname}=${labelvalue}" --format '{{.ID}}'
   306      is "$output" "$pod_id" "pod ps --filter label=..."
   307  
   308      # Test local port forwarding, as well as 'ps' output showing ports
   309      # Run 'nc' in a container, waiting for input on the published port.
   310      c_name=$(random_string 15)
   311      run_podman run -d --pod mypod --name $c_name $IMAGE nc -l -p $port_in
   312      cid="$output"
   313  
   314      # Try running another container also listening on the same port.
   315      run_podman 1 run --pod mypod --name dsfsdfsdf $IMAGE nc -l -p $port_in
   316      is "$output" "nc: bind: Address in use" \
   317         "two containers cannot bind to same port"
   318  
   319      # make sure we can ping; failure here might mean that capabilities are wrong
   320      run_podman run --rm --pod mypod $IMAGE ping -c1 127.0.0.1
   321      run_podman run --rm --pod mypod $IMAGE ping -c1 $hostname
   322  
   323      # While the container is still running, run 'podman ps' (no --format)
   324      # and confirm that the output includes the published port
   325      run_podman ps --filter id=$cid
   326      is "${lines[1]}" "${cid:0:12}  $IMAGE  nc -l -p $port_in .* 0.0.0.0:$port_out->$port_in/tcp  $c_name" \
   327         "output of 'podman ps'"
   328  
   329      # send a random string to the container. This will cause the container
   330      # to output the string to its logs, then exit.
   331      teststring=$(random_string 30)
   332      echo "$teststring" | nc 127.0.0.1 $port_out
   333  
   334      # Confirm that the container log output is the string we sent it.
   335      run_podman wait $cid
   336      run_podman logs $cid
   337      is "$output" "$teststring" "test string received on container"
   338  
   339      # Finally, confirm the infra-container and -command. We run this late,
   340      # not at pod creation, to give the infra container time to start & log.
   341      run_podman logs $infra_cid
   342      is "$output" "Confirmed: testimage pause invoked as $infra_command" \
   343         "pod ran with our desired infra container + command"
   344  
   345      # Clean up
   346      run_podman rm $cid
   347      run_podman pod rm -t 0 -f --pod-id-file $pod_id_file
   348      if [[ -e $pod_id_file ]]; then
   349          die "pod-id-file $pod_id_file should be removed along with pod"
   350      fi
   351      run_podman rmi $infra_image
   352  }
   353  
   354  @test "podman pod create should fail when infra-name is already in use" {
   355      local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)"
   356      local infra_image="quay.io/libpod/k8s-pause:3.5"
   357      local pod_name="$(random_string 10 | tr A-Z a-z)"
   358  
   359      run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "$infra_image"
   360      is "$output" "" "output from pod create should be empty"
   361  
   362      run_podman 125 pod create --infra-name "$infra_name"
   363      assert "$output" =~ "^Error: .*: the container name \"$infra_name\" is already in use by .* You have to remove that container to be able to reuse that name: that name is already in use" \
   364             "Trying to create two pods with same infra-name"
   365  
   366      run_podman pod rm -f $pod_name
   367      run_podman rmi $infra_image
   368  }
   369  
   370  @test "podman pod create --share" {
   371      local pod_name="$(random_string 10 | tr A-Z a-z)"
   372      run_podman 125 pod create --share bogus --name $pod_name
   373      is "$output" ".*invalid kernel namespace to share: bogus. Options are: cgroup, ipc, net, pid, uts or none" \
   374         "pod test for bogus --share option"
   375      run_podman pod create --share ipc --name $pod_name
   376      run_podman pod inspect $pod_name --format "{{.SharedNamespaces}}"
   377      is "$output" "[ipc]"
   378      run_podman run --rm --pod $pod_name --hostname foobar $IMAGE hostname
   379      is "$output" "foobar" "--hostname should work with non share UTS namespace"
   380      run_podman pod create --share +pid --replace --name $pod_name
   381      run_podman pod inspect $pod_name --format "{{.SharedNamespaces}}"
   382      for ns in uts pid ipc net; do
   383          is "$output" ".*$ns"
   384      done
   385  }
   386  
   387  @test "podman pod create --pod new:$POD --hostname" {
   388      local pod_name="$(random_string 10 | tr A-Z a-z)"
   389      run_podman run --rm --pod "new:$pod_name" --hostname foobar $IMAGE hostname
   390      is "$output" "foobar" "--hostname should work when creating a new:pod"
   391      run_podman pod rm $pod_name
   392      run_podman run --rm --pod "new:$pod_name" $IMAGE hostname
   393      is "$output" "$pod_name" "new:POD should have hostname name set to podname"
   394  }
   395  
   396  @test "podman rm --force to remove infra container" {
   397      local pod_name="$(random_string 10 | tr A-Z a-z)"
   398      run_podman create --pod "new:$pod_name" $IMAGE
   399      container_ID="$output"
   400      run_podman pod inspect --format "{{.InfraContainerID}}" $pod_name
   401      infra_ID="$output"
   402  
   403      run_podman 125 container rm $infra_ID
   404      is "$output" ".* and cannot be removed without removing the pod"
   405      run_podman 125 container rm --force $infra_ID
   406      is "$output" ".* and cannot be removed without removing the pod"
   407  
   408      run_podman container rm --depend $infra_ID
   409      is "$output" ".*$infra_ID.*"
   410      is "$output" ".*$container_ID.*"
   411  
   412      # Now make sure that --force --all works as well
   413      run_podman create --pod "new:$pod_name" $IMAGE
   414      container_1_ID="$output"
   415      run_podman create --pod "$pod_name" $IMAGE
   416      container_2_ID="$output"
   417      run_podman create $IMAGE
   418      container_3_ID="$output"
   419      run_podman pod inspect --format "{{.InfraContainerID}}" $pod_name
   420      infra_ID="$output"
   421  
   422      run_podman container rm --force --all $infraID
   423      is "$output" ".*$infra_ID.*"
   424      is "$output" ".*$container_1_ID.*"
   425      is "$output" ".*$container_2_ID.*"
   426      is "$output" ".*$container_3_ID.*"
   427  }
   428  
   429  @test "podman pod create share net" {
   430      run_podman pod create --name test
   431      run_podman pod inspect test --format {{.InfraConfig.HostNetwork}}
   432      is "$output" "false" "Default network sharing should be false"
   433      run_podman pod rm test
   434  
   435      run_podman pod create --share ipc  --network private test
   436      run_podman pod inspect test --format {{.InfraConfig.HostNetwork}}
   437      is "$output" "false" "Private network sharing with only ipc should be false"
   438      run_podman pod rm test
   439  
   440      local name="$(random_string 10 | tr A-Z a-z)"
   441      run_podman pod create --name $name --share net  --network private
   442      run_podman pod inspect $name --format {{.InfraConfig.HostNetwork}}
   443      is "$output" "false" "Private network sharing with only net should be false"
   444  
   445      run_podman pod create --share net --network host --replace $name
   446      run_podman pod inspect $name --format {{.InfraConfig.HostNetwork}}
   447      is "$output" "true" "Host network sharing with only net should be true"
   448      run_podman pod rm $name
   449  
   450      run_podman pod create --name test --share ipc --network host
   451      run_podman pod inspect test --format {{.InfraConfig.HostNetwork}}
   452      is "$output" "true" "Host network sharing with only ipc should be true"
   453      run_podman pod rm test
   454  }
   455  
   456  @test "pod exit policies" {
   457      # Test setting exit policies
   458      run_podman pod create
   459      podID="$output"
   460      run_podman pod inspect $podID --format "{{.ExitPolicy}}"
   461      is "$output" "continue" "default exit policy"
   462      run_podman pod rm $podID
   463  
   464      run_podman pod create --exit-policy stop
   465      podID="$output"
   466      run_podman pod inspect $podID --format "{{.ExitPolicy}}"
   467      is "$output" "stop" "custom exit policy"
   468      run_podman pod rm $podID
   469  
   470      run_podman 125 pod create --exit-policy invalid
   471      is "$output" "Error: .*running pod create option: invalid pod exit policy: \"invalid\"" "invalid exit policy"
   472  
   473      # Test exit-policy behaviour
   474      run_podman pod create --exit-policy continue
   475      podID="$output"
   476      run_podman run --pod $podID $IMAGE true
   477      run_podman pod inspect $podID --format "{{.State}}"
   478      _ensure_pod_state $podID Degraded
   479      run_podman pod rm $podID
   480  
   481      run_podman pod create --exit-policy stop
   482      podID="$output"
   483      run_podman run --pod $podID $IMAGE true
   484      run_podman pod inspect $podID --format "{{.State}}"
   485      _ensure_pod_state $podID Exited
   486      run_podman pod rm -t -1 -f $podID
   487  }
   488  
   489  @test "pod exit policies - play kube" {
   490      # play-kube sets the exit policy to "stop"
   491      local name="$(random_string 10 | tr A-Z a-z)"
   492  
   493      kubeFile="apiVersion: v1
   494  kind: Pod
   495  metadata:
   496    name: $name-pod
   497  spec:
   498    containers:
   499    - command:
   500      - \"true\"
   501      image: $IMAGE
   502      name: ctr
   503    restartPolicy: OnFailure"
   504  
   505      echo "$kubeFile" > $PODMAN_TMPDIR/test.yaml
   506      run_podman play kube $PODMAN_TMPDIR/test.yaml
   507      run_podman pod inspect $name-pod --format "{{.ExitPolicy}}"
   508      is "$output" "stop" "custom exit policy"
   509      _ensure_pod_state $name-pod Exited
   510      run_podman pod rm $name-pod
   511  }
   512  
   513  @test "pod resource limits" {
   514      skip_if_remote "resource limits only implemented on non-remote"
   515      skip_if_rootless "resource limits only work with root"
   516      skip_if_cgroupsv1 "resource limits only meaningful on cgroups V2"
   517  
   518      # create loopback device
   519      lofile=${PODMAN_TMPDIR}/disk.img
   520      fallocate -l 1k  ${lofile}
   521      LOOPDEVICE=$(losetup --show -f $lofile)
   522  
   523      # tr needed because losetup seems to use %2d
   524      lomajmin=$(losetup -l --noheadings --output MAJ:MIN $LOOPDEVICE | tr -d ' ')
   525      run grep -w bfq /sys/block/$(basename ${LOOPDEVICE})/queue/scheduler
   526      if [ $status -ne 0 ]; then
   527          losetup -d $LOOPDEVICE
   528          LOOPDEVICE=
   529          skip "BFQ scheduler is not supported on the system"
   530      fi
   531      echo bfq > /sys/block/$(basename ${LOOPDEVICE})/queue/scheduler
   532  
   533      # FIXME: #15464: blkio-weight-device not working
   534      expected_limits="
   535  cpu.max         | 500000 100000
   536  memory.max      | 5242880
   537  memory.swap.max | 1068498944
   538  io.bfq.weight   | default 50
   539  io.max          | $lomajmin rbps=1048576 wbps=1048576 riops=max wiops=max
   540  "
   541  
   542      for cgm in systemd cgroupfs; do
   543          local name=resources-$cgm
   544          run_podman --cgroup-manager=$cgm pod create --name=$name --cpus=5 --memory=5m --memory-swap=1g --cpu-shares=1000 --cpuset-cpus=0 --cpuset-mems=0 --device-read-bps=${LOOPDEVICE}:1mb --device-write-bps=${LOOPDEVICE}:1mb --blkio-weight=50
   545          run_podman --cgroup-manager=$cgm pod start $name
   546          run_podman pod inspect --format '{{.CgroupPath}}' $name
   547          local cgroup_path="$output"
   548  
   549          while read unit expect; do
   550              local actual=$(< /sys/fs/cgroup/$cgroup_path/$unit)
   551              is "$actual" "$expect" "resource limit under $cgm: $unit"
   552          done < <(parse_table "$expected_limits")
   553          run_podman --cgroup-manager=$cgm pod rm -f $name
   554      done
   555  
   556      # Clean up, and prevent duplicate cleanup in teardown
   557      losetup -d $LOOPDEVICE
   558      LOOPDEVICE=
   559  }
   560  
   561  @test "podman pod ps doesn't race with pod rm" {
   562      # create a few pods
   563      for i in {0..10}; do
   564          run_podman pod create
   565      done
   566  
   567      # and delete them
   568      $PODMAN pod rm -a &
   569  
   570      # pod ps should not fail while pods are deleted
   571      run_podman pod ps -q
   572  
   573      # wait for pod rm -a
   574      wait
   575  }
   576  
   577  @test "podman pod rm --force bogus" {
   578      run_podman 1 pod rm bogus
   579      is "$output" "Error: .*bogus.*: no such pod" "Should print error"
   580      run_podman pod rm -t -1 --force bogus
   581      is "$output" "" "Should print no output"
   582  
   583      run_podman pod create --name testpod
   584      run_podman pod rm --force bogus testpod
   585      assert "$output" =~ "[0-9a-f]{64}" "rm pod"
   586      run_podman pod ps -q
   587      assert "$output" = "" "no pods listed"
   588  }
   589  
   590  @test "podman pod create on failure" {
   591      podname=pod$(random_string)
   592      nwname=pod$(random_string)
   593  
   594      run_podman 125 pod create --network $nwname --name $podname
   595      # FIXME: podman and podman-remote do not return the same error message
   596      # but consistency would be nice
   597      is "$output" "Error: .*unable to find network with name or ID $nwname: network not found"
   598  
   599      # Make sure the pod doesn't get created on failure
   600      run_podman 1 pod exists $podname
   601  }
   602  
   603  @test "podman pod create restart tests" {
   604      podname=pod$(random_string)
   605  
   606      run_podman pod create --restart=on-failure --name $podname
   607      run_podman create --name test-ctr --pod $podname $IMAGE
   608      run_podman container inspect --format '{{ .HostConfig.RestartPolicy.Name }}' test-ctr
   609      is "$output" "on-failure" "container inherits from pod"
   610  
   611      run_podman create --replace --restart=always --name test-ctr --pod $podname $IMAGE
   612      run_podman container inspect --format '{{ .HostConfig.RestartPolicy.Name }}' test-ctr
   613      is "$output" "always" "container overrides restart policy from pod"
   614  
   615      run_podman pod rm -f -a
   616  }
   617  
   618  # Helper used by pod ps --filter test. Creates one pod or container
   619  # with a UNIQUE two-character CID prefix.
   620  function thingy_with_unique_id() {
   621      local what="$1"; shift              # pod or container
   622      local how="$1"; shift               # e.g. "--name p1c1 --pod p1"
   623  
   624      while :;do
   625            local try_again=
   626  
   627            run_podman $what create $how
   628            # This is our return value; it propagates up to caller's namespace
   629            id="$output"
   630  
   631            # Make sure the first two characters aren't already used in an ID
   632            for existing_id in "$@"; do
   633                if [[ -z "$try_again" ]]; then
   634                    if [[ "${existing_id:0:2}" == "${id:0:2}" ]]; then
   635                        run_podman $what rm $id
   636                        try_again=1
   637                    fi
   638                fi
   639            done
   640  
   641            if [[ -z "$try_again" ]]; then
   642                # Nope! groovy! caller gets $id
   643                return
   644            fi
   645      done
   646  }
   647  
   648  @test "podman pod ps --filter" {
   649      local -A podid
   650      local -A ctrid
   651  
   652      # Setup: create three pods, each with three containers, all of them with
   653      # unique (distinct) first two characters of their pod/container ID.
   654      for p in 1 2 3;do
   655          # no infra, please! That creates an extra container with a CID
   656          # that may collide with our other ones, and it's too hard to fix.
   657          thingy_with_unique_id "pod" "--infra=false --name p${p}" \
   658                                ${podid[*]} ${ctrid[*]}
   659          podid[$p]=$id
   660  
   661          for c in 1 2 3; do
   662              thingy_with_unique_id "container" \
   663                                    "--pod p${p} --name p${p}c${c} $IMAGE true" \
   664                                    ${podid[*]} ${ctrid[*]}
   665              ctrid[$p$c]=$id
   666          done
   667      done
   668  
   669      # for debugging; without this, on test failure it's too hard to
   670      # associate IDs with names
   671      run_podman pod ps
   672      run_podman ps -a
   673  
   674      # Test: ps and filter for each pod and container, by ID
   675      for p in 1 2 3; do
   676          local pid=${podid[$p]}
   677  
   678          # Search by short pod ID, longer pod ID, pod ID regex, and pod name
   679          # ps by short ID, longer ID, regex, and name
   680          for filter in "id=${pid:0:2}" "id=${pid:0:10}" "id=^${pid:0:2}" "name=p$p"; do
   681              run_podman pod ps --filter=$filter --format '{{.Name}}:{{.Id}}'
   682              assert "$output" == "p$p:${pid:0:12}" "pod $p, filter=$filter"
   683          done
   684  
   685          # ps by negation (regex) of our pid, should find all other pods
   686          f1="^[^${pid:0:1}]"
   687          f2="^.[^${pid:1:1}]"
   688          run_podman pod ps --filter=id="$f1" --filter=id="$f2" --format '{{.Name}}'
   689          assert "${#lines[*]}" == "2" "filter=$f1 + $f2 finds 2 pods"
   690          assert "$output" !~ "p$p"    "filter=$f1 + $f2 does not find p$p"
   691  
   692          # Search by *container* ID
   693          for c in 1 2 3;do
   694              local cid=${ctrid[$p$c]}
   695              for filter in "ctr-ids=${cid:0:2}" "ctr-ids=^${cid:0:2}.*"; do
   696                  run_podman pod ps --filter=$filter --format '{{.Name}}:{{.Id}}'
   697                  assert "$output" == "p${p}:${pid:0:12}" \
   698                         "pod $p, container $c, filter=$filter"
   699              done
   700          done
   701      done
   702  
   703      # Multiple filters, multiple pods
   704      run_podman pod ps --filter=ctr-ids=${ctrid[12]} \
   705                        --filter=ctr-ids=${ctrid[23]} \
   706                        --filter=ctr-ids=${ctrid[31]} \
   707                        --format='{{.Name}}' --sort=name
   708      assert "$(echo $output)" == "p1 p2 p3" "multiple ctr-ids filters"
   709  
   710      # Clean up
   711      run_podman pod rm -f -a
   712      run_podman rm -f -a
   713  }
   714  
   715  
   716  @test "podman pod cleans cgroup and keeps limits" {
   717      skip_if_remote "we cannot check cgroup settings"
   718      skip_if_rootless_cgroupsv1 "rootless cannot use cgroups on v1"
   719  
   720      for infra in true false; do
   721          run_podman pod create --infra=$infra --memory=256M
   722          podid="$output"
   723          run_podman run -d --pod $podid $IMAGE top -d 2
   724  
   725          run_podman pod inspect $podid --format "{{.CgroupPath}}"
   726          result="$output"
   727          assert "$result" =~ "/" ".CgroupPath is a valid path"
   728  
   729          if is_cgroupsv2; then
   730             cgroup_path=/sys/fs/cgroup/$result
   731          else
   732             cgroup_path=/sys/fs/cgroup/memory/$result
   733          fi
   734  
   735          if test ! -e $cgroup_path; then
   736              die "the cgroup $cgroup_path does not exist"
   737          fi
   738  
   739          run_podman pod stop -t 0 $podid
   740          if test -e $cgroup_path; then
   741              die "the cgroup $cgroup_path should not exist after pod stop"
   742          fi
   743  
   744          run_podman pod start $podid
   745          if test ! -e $cgroup_path; then
   746              die "the cgroup $cgroup_path does not exist"
   747          fi
   748  
   749          # validate that cgroup limits are in place after a restart
   750          # issue #19175
   751          if is_cgroupsv2; then
   752             memory_limit_file=$cgroup_path/memory.max
   753          else
   754             memory_limit_file=$cgroup_path/memory.limit_in_bytes
   755          fi
   756          assert "$(< $memory_limit_file)" = "268435456" "Contents of $memory_limit_file"
   757  
   758          run_podman pod rm -t 0 -f $podid
   759          if test -e $cgroup_path; then
   760              die "the cgroup $cgroup_path should not exist after pod rm"
   761          fi
   762      done
   763  }
   764  
   765  # vim: filetype=sh