github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/test/apiv2/rest_api/v1_test_rest_v1_0_0.py (about)

     1  import json
     2  import os
     3  import shlex
     4  import signal
     5  import string
     6  import subprocess
     7  import sys
     8  import time
     9  import unittest
    10  from collections.abc import Iterable
    11  from multiprocessing import Process
    12  
    13  import requests
    14  from dateutil.parser import parse
    15  
    16  PODMAN_URL = "http://localhost:8080"
    17  
    18  
    19  def _url(path):
    20      return PODMAN_URL + "/v1.0.0/libpod" + path
    21  
    22  
    23  def podman():
    24      binary = os.getenv("PODMAN_BINARY")
    25      if binary is None:
    26          binary = "bin/podman"
    27      return binary
    28  
    29  
    30  def ctnr(path):
    31      r = requests.get(_url("/containers/json?all=true"))
    32      try:
    33          ctnrs = json.loads(r.text)
    34      except Exception as e:
    35          sys.stderr.write("Bad container response: {}/{}".format(r.text, e))
    36          raise e
    37      return path.format(ctnrs[0]["Id"])
    38  
    39  
    40  class TestApi(unittest.TestCase):
    41      podman = None
    42  
    43      def setUp(self):
    44          super().setUp()
    45          if TestApi.podman.poll() is not None:
    46              sys.stderr.write("podman service returned {}", TestApi.podman.returncode)
    47              sys.exit(2)
    48          requests.get(_url("/images/create?fromSrc=docker.io%2Falpine%3Alatest"))
    49          # calling out to podman is easier than the API for running a container
    50          subprocess.run(
    51              [podman(), "run", "alpine", "/bin/ls"],
    52              check=True,
    53              stdout=subprocess.DEVNULL,
    54              stderr=subprocess.DEVNULL,
    55          )
    56  
    57      @classmethod
    58      def setUpClass(cls):
    59          super().setUpClass()
    60  
    61          TestApi.podman = subprocess.Popen(
    62              [
    63                  podman(),
    64                  "system",
    65                  "service",
    66                  "tcp:localhost:8080",
    67                  "--log-level=debug",
    68                  "--time=0",
    69              ],
    70              shell=False,
    71              stdin=subprocess.DEVNULL,
    72              stdout=subprocess.DEVNULL,
    73              stderr=subprocess.DEVNULL,
    74          )
    75          time.sleep(2)
    76  
    77      @classmethod
    78      def tearDownClass(cls):
    79          TestApi.podman.terminate()
    80          stdout, stderr = TestApi.podman.communicate(timeout=0.5)
    81          if stdout:
    82              print("\nService Stdout:\n" + stdout.decode("utf-8"))
    83          if stderr:
    84              print("\nService Stderr:\n" + stderr.decode("utf-8"))
    85  
    86          if TestApi.podman.returncode > 0:
    87              sys.stderr.write("podman exited with error code {}\n".format(TestApi.podman.returncode))
    88              sys.exit(2)
    89  
    90          return super().tearDownClass()
    91  
    92      def test_info(self):
    93          r = requests.get(_url("/info"))
    94          self.assertEqual(r.status_code, 200)
    95          self.assertIsNotNone(r.content)
    96          _ = json.loads(r.text)
    97  
    98      def test_events(self):
    99          r = requests.get(_url("/events?stream=false"))
   100          self.assertEqual(r.status_code, 200, r.text)
   101          self.assertIsNotNone(r.content)
   102          for line in r.text.splitlines():
   103              obj = json.loads(line)
   104              # Actor.ID is uppercase for compatibility
   105              _ = obj["Actor"]["ID"]
   106  
   107      def test_containers(self):
   108          r = requests.get(_url("/containers/json"), timeout=5)
   109          self.assertEqual(r.status_code, 200, r.text)
   110          obj = json.loads(r.text)
   111          self.assertEqual(len(obj), 0)
   112  
   113      def test_containers_all(self):
   114          r = requests.get(_url("/containers/json?all=true"))
   115          self.assertEqual(r.status_code, 200, r.text)
   116          self.validateObjectFields(r.text)
   117  
   118      def test_inspect_container(self):
   119          r = requests.get(_url(ctnr("/containers/{}/json")))
   120          self.assertEqual(r.status_code, 200, r.text)
   121          obj = self.validateObjectFields(r.content)
   122          _ = parse(obj["Created"])
   123  
   124      def test_stats(self):
   125          r = requests.get(_url(ctnr("/containers/{}/stats?stream=false")))
   126          self.assertIn(r.status_code, (200, 409), r.text)
   127          if r.status_code == 200:
   128              self.validateObjectFields(r.text)
   129  
   130      def test_delete_containers(self):
   131          r = requests.delete(_url(ctnr("/containers/{}")))
   132          self.assertEqual(r.status_code, 204, r.text)
   133  
   134      def test_stop_containers(self):
   135          r = requests.post(_url(ctnr("/containers/{}/start")))
   136          self.assertIn(r.status_code, (204, 304), r.text)
   137  
   138          r = requests.post(_url(ctnr("/containers/{}/stop")))
   139          self.assertIn(r.status_code, (204, 304), r.text)
   140  
   141      def test_start_containers(self):
   142          r = requests.post(_url(ctnr("/containers/{}/stop")))
   143          self.assertIn(r.status_code, (204, 304), r.text)
   144  
   145          r = requests.post(_url(ctnr("/containers/{}/start")))
   146          self.assertIn(r.status_code, (204, 304), r.text)
   147  
   148      def test_restart_containers(self):
   149          r = requests.post(_url(ctnr("/containers/{}/start")))
   150          self.assertIn(r.status_code, (204, 304), r.text)
   151  
   152          r = requests.post(_url(ctnr("/containers/{}/restart")), timeout=5)
   153          self.assertEqual(r.status_code, 204, r.text)
   154  
   155      def test_resize(self):
   156          r = requests.post(_url(ctnr("/containers/{}/resize?h=43&w=80")))
   157          self.assertIn(r.status_code, (200, 409), r.text)
   158          if r.status_code == 200:
   159              self.assertIsNone(r.text)
   160  
   161      def test_attach_containers(self):
   162          r = requests.post(_url(ctnr("/containers/{}/attach")))
   163          self.assertIn(r.status_code, (101, 409), r.text)
   164  
   165      def test_logs_containers(self):
   166          r = requests.get(_url(ctnr("/containers/{}/logs?stdout=true")))
   167          self.assertEqual(r.status_code, 200, r.text)
   168  
   169      def test_post_create(self):
   170          self.skipTest("TODO: create request body")
   171          r = requests.post(_url("/containers/create?args=True"))
   172          self.assertEqual(r.status_code, 200, r.text)
   173          json.loads(r.text)
   174  
   175      def test_commit(self):
   176          r = requests.post(_url(ctnr("/commit?container={}")))
   177          self.assertEqual(r.status_code, 200, r.text)
   178          self.validateObjectFields(r.text)
   179  
   180      def test_images(self):
   181          r = requests.get(_url("/images/json"))
   182          self.assertEqual(r.status_code, 200, r.text)
   183          self.validateObjectFields(r.content)
   184  
   185      def test_inspect_image(self):
   186          r = requests.get(_url("/images/alpine/json"))
   187          self.assertEqual(r.status_code, 200, r.text)
   188          obj = self.validateObjectFields(r.content)
   189          _ = parse(obj["Created"])
   190  
   191      def test_delete_image(self):
   192          r = requests.delete(_url("/images/alpine?force=true"))
   193          self.assertEqual(r.status_code, 200, r.text)
   194          json.loads(r.text)
   195  
   196      def test_pull(self):
   197          r = requests.post(_url("/images/pull?reference=alpine"), timeout=5)
   198          self.assertEqual(r.status_code, 200, r.text)
   199          json.loads(r.text)
   200  
   201      def test_search(self):
   202          # Had issues with this test hanging when repositories not happy
   203          def do_search():
   204              r = requests.get(_url("/images/search?term=alpine"), timeout=5)
   205              self.assertEqual(r.status_code, 200, r.text)
   206              json.loads(r.text)
   207  
   208          search = Process(target=do_search)
   209          search.start()
   210          search.join(timeout=10)
   211          self.assertFalse(search.is_alive(), "/images/search took too long")
   212  
   213      def test_ping(self):
   214          r = requests.get(PODMAN_URL + "/_ping")
   215          self.assertEqual(r.status_code, 200, r.text)
   216  
   217          r = requests.head(PODMAN_URL + "/_ping")
   218          self.assertEqual(r.status_code, 200, r.text)
   219  
   220          r = requests.get(_url("/_ping"))
   221          self.assertEqual(r.status_code, 200, r.text)
   222  
   223          r = requests.get(_url("/_ping"))
   224          self.assertEqual(r.status_code, 200, r.text)
   225  
   226  
   227  def validateObjectFields(self, buffer):
   228      objs = json.loads(buffer)
   229      if not isinstance(objs, dict):
   230          for o in objs:
   231              _ = o["Id"]
   232      else:
   233          _ = objs["Id"]
   234      return objs
   235  
   236  
   237  if __name__ == "__main__":
   238      unittest.main()