github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/apiv2/python/rest_api/test_v2_0_0_container.py (about)

     1  import multiprocessing
     2  import queue
     3  import random
     4  import threading
     5  import unittest
     6  
     7  import requests
     8  import time
     9  from dateutil.parser import parse
    10  
    11  from .fixtures import APITestCase
    12  
    13  
    14  class ContainerTestCase(APITestCase):
    15      def test_list(self):
    16          r = requests.get(self.uri("/containers/json"), timeout=5)
    17          self.assertEqual(r.status_code, 200, r.text)
    18          obj = r.json()
    19          self.assertEqual(len(obj), 1)
    20  
    21      def test_list_filters(self):
    22          r = requests.get(
    23              self.podman_url
    24              + "/v1.40/containers/json?filters%3D%7B%22status%22%3A%5B%22running%22%5D%7D"
    25          )
    26          self.assertEqual(r.status_code, 200, r.text)
    27          payload = r.json()
    28          containerAmnt = len(payload)
    29          self.assertGreater(containerAmnt, 0)
    30  
    31      def test_list_all(self):
    32          r = requests.get(self.uri("/containers/json?all=true"))
    33          self.assertEqual(r.status_code, 200, r.text)
    34          self.assertId(r.content)
    35  
    36      def test_inspect(self):
    37          r = requests.get(self.uri(self.resolve_container("/containers/{}/json")))
    38          self.assertEqual(r.status_code, 200, r.text)
    39          self.assertId(r.content)
    40          _ = parse(r.json()["Created"])
    41  
    42          r = requests.post(
    43              self.podman_url + "/v1.40/containers/create?name=topcontainer",
    44              json={
    45                  "Cmd": ["top"],
    46                  "Image": "alpine:latest",
    47                  "Healthcheck": {
    48                      "Test": ["CMD", "pidof", "top"],
    49                      "Interval": 5000000000,
    50                      "Timeout": 2000000000,
    51                      "Retries": 3,
    52                      "StartPeriod": 5000000000,
    53                  },
    54              },
    55          )
    56          self.assertEqual(r.status_code, 201, r.text)
    57          payload = r.json()
    58          container_id = payload["Id"]
    59          self.assertIsNotNone(container_id)
    60  
    61          r = requests.get(self.podman_url + f"/v1.40/containers/{container_id}/json")
    62          self.assertEqual(r.status_code, 200, r.text)
    63          self.assertId(r.content)
    64          out = r.json()
    65          self.assertIsNotNone(out["State"].get("Health"))
    66          self.assertListEqual(["CMD", "pidof", "top"], out["Config"]["Healthcheck"]["Test"])
    67          self.assertEqual(5000000000, out["Config"]["Healthcheck"]["Interval"])
    68          self.assertEqual(2000000000, out["Config"]["Healthcheck"]["Timeout"])
    69          self.assertEqual(3, out["Config"]["Healthcheck"]["Retries"])
    70          self.assertEqual(5000000000, out["Config"]["Healthcheck"]["StartPeriod"])
    71  
    72          r = requests.get(self.uri(f"/containers/{container_id}/json"))
    73          self.assertEqual(r.status_code, 200, r.text)
    74          self.assertId(r.content)
    75          out = r.json()
    76          hc = out["Config"]["Healthcheck"]["Test"]
    77          self.assertListEqual(["CMD", "pidof", "top"], hc)
    78  
    79          r = requests.post(self.podman_url + f"/v1.40/containers/{container_id}/start")
    80          self.assertEqual(r.status_code, 204, r.text)
    81  
    82          r = requests.get(self.podman_url + f"/v1.40/containers/{container_id}/json")
    83          self.assertEqual(r.status_code, 200, r.text)
    84          out = r.json()
    85          state = out["State"]["Health"]
    86          self.assertIsInstance(state, dict)
    87  
    88      def test_stats(self):
    89          r = requests.get(self.uri(self.resolve_container("/containers/{}/stats?stream=false")))
    90          self.assertIn(r.status_code, (200, 409), r.text)
    91          if r.status_code == 200:
    92              self.assertId(r.content)
    93          r = requests.get(
    94              self.uri(self.resolve_container("/containers/{}/stats?stream=false&one-shot=true"))
    95          )
    96          self.assertIn(r.status_code, (200, 409), r.text)
    97          if r.status_code == 200:
    98              self.assertId(r.content)
    99  
   100      def test_delete(self):
   101          r = requests.delete(self.uri(self.resolve_container("/containers/{}?force=true")))
   102          self.assertEqual(r.status_code, 200, r.text)
   103  
   104      def test_stop(self):
   105          r = requests.post(self.uri(self.resolve_container("/containers/{}/start")))
   106          self.assertIn(r.status_code, (204, 304), r.text)
   107  
   108          r = requests.post(self.uri(self.resolve_container("/containers/{}/stop")))
   109          self.assertIn(r.status_code, (204, 304), r.text)
   110  
   111      def test_start(self):
   112          r = requests.post(self.uri(self.resolve_container("/containers/{}/stop")))
   113          self.assertIn(r.status_code, (204, 304), r.text)
   114  
   115          r = requests.post(self.uri(self.resolve_container("/containers/{}/start")))
   116          self.assertIn(r.status_code, (204, 304), r.text)
   117  
   118      def test_restart(self):
   119          r = requests.post(self.uri(self.resolve_container("/containers/{}/start")))
   120          self.assertIn(r.status_code, (204, 304), r.text)
   121  
   122          r = requests.post(self.uri(self.resolve_container("/containers/{}/restart")), timeout=5)
   123          self.assertEqual(r.status_code, 204, r.text)
   124  
   125      def test_resize(self):
   126          r = requests.post(self.uri(self.resolve_container("/containers/{}/resize?h=43&w=80")))
   127          self.assertIn(r.status_code, (200, 409), r.text)
   128          if r.status_code == 200:
   129              self.assertEqual(r.text, "", r.text)
   130  
   131      def test_attach(self):
   132          self.skipTest("FIXME: Test timeouts")
   133          r = requests.post(self.uri(self.resolve_container("/containers/{}/attach?logs=true")), timeout=5)
   134          self.assertIn(r.status_code, (101, 500), r.text)
   135  
   136      def test_logs(self):
   137          r = requests.get(self.uri(self.resolve_container("/containers/{}/logs?stdout=true")))
   138          self.assertEqual(r.status_code, 200, r.text)
   139          r = requests.post(
   140              self.podman_url + "/v1.40/containers/create?name=topcontainer",
   141              json={"Cmd": ["top", "ls"], "Image": "alpine:latest"},
   142          )
   143          self.assertEqual(r.status_code, 201, r.text)
   144          payload = r.json()
   145          container_id = payload["Id"]
   146          self.assertIsNotNone(container_id)
   147          r = requests.get(
   148              self.podman_url
   149              + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=0"
   150          )
   151          self.assertEqual(r.status_code, 200, r.text)
   152          r = requests.get(
   153              self.podman_url
   154              + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=1"
   155          )
   156          self.assertEqual(r.status_code, 200, r.text)
   157  
   158      def test_commit(self):
   159          r = requests.post(self.uri(self.resolve_container("/commit?container={}")))
   160          self.assertEqual(r.status_code, 200, r.text)
   161          self.assertId(r.content)
   162  
   163          obj = r.json()
   164          self.assertIsInstance(obj, dict)
   165  
   166      def test_prune(self):
   167          name = f"Container_{random.getrandbits(160):x}"
   168  
   169          r = requests.post(
   170              self.podman_url + f"/v1.40/containers/create?name={name}",
   171              json={
   172                  "Cmd": ["cp", "/etc/motd", "/motd.size_test"],
   173                  "Image": "alpine:latest",
   174                  "NetworkDisabled": True,
   175              },
   176          )
   177          self.assertEqual(r.status_code, 201, r.text)
   178          create = r.json()
   179  
   180          r = requests.post(self.podman_url + f"/v1.40/containers/{create['Id']}/start")
   181          self.assertEqual(r.status_code, 204, r.text)
   182  
   183          r = requests.post(self.podman_url + f"/v1.40/containers/{create['Id']}/wait")
   184          self.assertEqual(r.status_code, 200, r.text)
   185          wait = r.json()
   186          self.assertEqual(wait["StatusCode"], 0, wait["Error"])
   187  
   188          prune = requests.post(self.podman_url + "/v1.40/containers/prune")
   189          self.assertEqual(prune.status_code, 200, prune.status_code)
   190          prune_payload = prune.json()
   191          self.assertGreater(prune_payload["SpaceReclaimed"], 0)
   192          self.assertIn(create["Id"], prune_payload["ContainersDeleted"])
   193  
   194          # Delete any orphaned containers
   195          r = requests.get(self.podman_url + "/v1.40/containers/json?all=true")
   196          self.assertEqual(r.status_code, 200, r.text)
   197          for self.resolve_container in r.json():
   198              requests.delete(
   199                  self.podman_url + f"/v1.40/containers/{self.resolve_container['Id']}?force=true"
   200              )
   201  
   202          # Image prune here tied to containers freeing up
   203          prune = requests.post(self.podman_url + "/v1.40/images/prune")
   204          self.assertEqual(prune.status_code, 200, prune.text)
   205          prune_payload = prune.json()
   206          self.assertGreater(prune_payload["SpaceReclaimed"], 0)
   207  
   208          # FIXME need method to determine which image is going to be "pruned" to fix test
   209          # TODO should handler be recursive when deleting images?
   210          # self.assertIn(img["Id"], prune_payload["ImagesDeleted"][1]["Deleted"])
   211  
   212          # FIXME (@vrothberg): I commented this line out during the `libimage` migration.
   213          # It doesn't make sense to report anything to be deleted if the reclaimed space
   214          # is zero.  I think the test needs some rewrite.
   215          # self.assertIsNotNone(prune_payload["ImagesDeleted"][1]["Deleted"])
   216  
   217      def test_status(self):
   218          r = requests.post(
   219              self.podman_url + "/v1.40/containers/create?name=topcontainer",
   220              json={"Cmd": ["top"], "Image": "alpine:latest"},
   221          )
   222          self.assertEqual(r.status_code, 201, r.text)
   223          payload = r.json()
   224          container_id = payload["Id"]
   225          self.assertIsNotNone(container_id)
   226  
   227          r = requests.get(
   228              self.podman_url + "/v1.40/containers/json",
   229              params={"all": "true", "filters": f'{{"id":["{container_id}"]}}'},
   230          )
   231          self.assertEqual(r.status_code, 200, r.text)
   232          payload = r.json()
   233          self.assertEqual(payload[0]["Status"], "Created")
   234  
   235          r = requests.post(self.podman_url + f"/v1.40/containers/{container_id}/start")
   236          self.assertEqual(r.status_code, 204, r.text)
   237  
   238          r = requests.get(
   239              self.podman_url + "/v1.40/containers/json",
   240              params={"all": "true", "filters": f'{{"id":["{container_id}"]}}'},
   241          )
   242          self.assertEqual(r.status_code, 200, r.text)
   243          payload = r.json()
   244          self.assertTrue(str(payload[0]["Status"]).startswith("Up"))
   245  
   246          r = requests.post(self.podman_url + f"/v1.40/containers/{container_id}/pause")
   247          self.assertEqual(r.status_code, 204, r.text)
   248  
   249          r = requests.get(
   250              self.podman_url + "/v1.40/containers/json",
   251              params={"all": "true", "filters": f'{{"id":["{container_id}"]}}'},
   252          )
   253          self.assertEqual(r.status_code, 200, r.text)
   254          payload = r.json()
   255          self.assertTrue(str(payload[0]["Status"]).startswith("Up"))
   256          self.assertTrue(str(payload[0]["Status"]).endswith("(Paused)"))
   257  
   258          r = requests.post(self.podman_url + f"/v1.40/containers/{container_id}/unpause")
   259          self.assertEqual(r.status_code, 204, r.text)
   260          r = requests.post(self.podman_url + f"/v1.40/containers/{container_id}/stop")
   261          self.assertEqual(r.status_code, 204, r.text)
   262  
   263          r = requests.get(
   264              self.podman_url + "/v1.40/containers/json",
   265              params={"all": "true", "filters": f'{{"id":["{container_id}"]}}'},
   266          )
   267          self.assertEqual(r.status_code, 200, r.text)
   268          payload = r.json()
   269          self.assertTrue(str(payload[0]["Status"]).startswith("Exited"))
   270  
   271          r = requests.delete(self.podman_url + f"/v1.40/containers/{container_id}")
   272          self.assertEqual(r.status_code, 204, r.text)
   273  
   274      def test_top_no_stream(self):
   275          uri = self.uri(self.resolve_container("/containers/{}/top"))
   276          q = queue.Queue()
   277  
   278          def _impl(fifo):
   279              fifo.put(requests.get(uri, params={"stream": False}, timeout=2))
   280  
   281          top = threading.Thread(target=_impl, args=(q,))
   282          top.start()
   283          time.sleep(2)
   284          self.assertFalse(top.is_alive(), f"GET {uri} failed to return in 2s")
   285  
   286          qr = q.get(False)
   287          self.assertEqual(qr.status_code, 200, qr.text)
   288  
   289          qr.close()
   290          top.join()
   291  
   292      def test_top_stream(self):
   293          uri = self.uri(self.resolve_container("/containers/{}/top"))
   294          q = queue.Queue()
   295  
   296          stop_thread = False
   297  
   298          def _impl(fifo, stop):
   299              try:
   300                  with requests.get(uri, params={"stream": True, "delay": 1}, stream=True) as r:
   301                      r.raise_for_status()
   302                      fifo.put(r)
   303                      for buf in r.iter_lines(chunk_size=None):
   304                          if stop():
   305                              break
   306                          fifo.put(buf)
   307              except Exception:
   308                  pass
   309  
   310          top = threading.Thread(target=_impl, args=(q, (lambda: stop_thread)))
   311          top.start()
   312          time.sleep(4)
   313          self.assertTrue(top.is_alive(), f"GET {uri} exited too soon")
   314          stop_thread = True
   315  
   316          for _ in range(10):
   317              try:
   318                  qr = q.get_nowait()
   319                  if qr is not None:
   320                      self.assertEqual(qr.status_code, 200)
   321                      qr.close()
   322                      break
   323              except queue.Empty:
   324                  pass
   325              finally:
   326                  time.sleep(1)
   327          else:
   328              self.fail("Server failed to respond in 10s")
   329          top.join()
   330  
   331      def test_memory(self):
   332          r = requests.post(
   333              self.podman_url + "/v1.4.0/libpod/containers/create",
   334              json={
   335                  "Name": "memory",
   336                  "Cmd": ["top"],
   337                  "Image": "alpine:latest",
   338                  "Resource_Limits": {
   339                      "Memory":{
   340                          "Limit": 1000,
   341                      },
   342                      "CPU":{
   343                          "Shares": 200,
   344                      },
   345                  },
   346              },
   347          )
   348          self.assertEqual(r.status_code, 201, r.text)
   349          payload = r.json()
   350          container_id = payload["Id"]
   351          self.assertIsNotNone(container_id)
   352  
   353          r = requests.get(self.podman_url + f"/v1.40/containers/{container_id}/json")
   354          self.assertEqual(r.status_code, 200, r.text)
   355          self.assertId(r.content)
   356          out = r.json()
   357          self.assertEqual(2000, out["HostConfig"]["MemorySwap"])
   358          self.assertEqual(1000, out["HostConfig"]["Memory"])
   359  
   360  
   361  if __name__ == "__main__":
   362      unittest.main()