github.com/containers/podman/v5@v5.1.0-rc1/test/apiv2/python/rest_api/test_v2_0_0_image.py (about)

     1  import json
     2  import unittest
     3  from multiprocessing import Process
     4  
     5  import requests
     6  from dateutil.parser import parse
     7  from .fixtures import APITestCase
     8  
     9  
    10  class ImageTestCase(APITestCase):
    11      def test_list(self):
    12          r = requests.get(self.podman_url + "/v1.40/images/json")
    13          self.assertEqual(r.status_code, 200, r.text)
    14  
    15          # See https://docs.docker.com/engine/api/v1.40/#operation/ImageList
    16          required_keys = (
    17              "Id",
    18              "ParentId",
    19              "RepoTags",
    20              "RepoDigests",
    21              "Created",
    22              "Size",
    23              "SharedSize",
    24              "VirtualSize",
    25              "Labels",
    26              "Containers",
    27          )
    28          images = r.json()
    29          self.assertIsInstance(images, list)
    30          for item in images:
    31              self.assertIsInstance(item, dict)
    32              for k in required_keys:
    33                  self.assertIn(k, item)
    34  
    35              # Id should be prefixed with sha256: (#11645)
    36              self.assertIn("sha256:",item['Id'])
    37  
    38      def test_inspect(self):
    39          r = requests.get(self.podman_url + "/v1.40/images/alpine/json")
    40          self.assertEqual(r.status_code, 200, r.text)
    41  
    42          # See https://docs.docker.com/engine/api/v1.40/#operation/ImageInspect
    43          required_keys = (
    44              "Id",
    45              "Parent",
    46              "Comment",
    47              "Created",
    48              "Container",
    49              "DockerVersion",
    50              "Author",
    51              "Architecture",
    52              "Os",
    53              "Size",
    54              "VirtualSize",
    55              "GraphDriver",
    56              "RootFS",
    57              "Metadata",
    58          )
    59  
    60          image = r.json()
    61          self.assertIsInstance(image, dict)
    62          for item in required_keys:
    63              self.assertIn(item, image)
    64          _ = parse(image["Created"])
    65          # Id should be prefixed with sha256: (#11645)
    66          self.assertIn("sha256:",image['Id'])
    67  
    68      def test_delete(self):
    69          r = requests.delete(self.podman_url + "/v1.40/images/alpine?force=true")
    70          self.assertEqual(r.status_code, 200, r.text)
    71          self.assertIsInstance(r.json(), list)
    72  
    73      def test_pull(self):
    74          r = requests.post(self.uri("/images/pull?reference=alpine"), timeout=15)
    75          self.assertEqual(r.status_code, 200, r.status_code)
    76          text = r.text
    77          keys = {
    78              "error": False,
    79              "id": False,
    80              "images": False,
    81              "stream": False,
    82          }
    83          # Read and record stanza's from pull
    84          for line in str.splitlines(text):
    85              obj = json.loads(line)
    86              key_list = list(obj.keys())
    87              for k in key_list:
    88                  keys[k] = True
    89  
    90          self.assertFalse(keys["error"], "Expected no errors")
    91          self.assertTrue(keys["id"], "Expected to find id stanza")
    92          self.assertTrue(keys["images"], "Expected to find images stanza")
    93          self.assertTrue(keys["stream"], "Expected to find stream progress stanza's")
    94  
    95          r = requests.post(self.uri("/images/pull?reference=alpine&quiet=true"), timeout=15)
    96          self.assertEqual(r.status_code, 200, r.status_code)
    97          text = r.text
    98          keys = {
    99              "error": False,
   100              "id": False,
   101              "images": False,
   102              "stream": False,
   103          }
   104          # Read and record stanza's from pull
   105          for line in str.splitlines(text):
   106              obj = json.loads(line)
   107              key_list = list(obj.keys())
   108              for k in key_list:
   109                  keys[k] = True
   110  
   111          self.assertFalse(keys["error"], "Expected no errors")
   112          self.assertTrue(keys["id"], "Expected to find id stanza")
   113          self.assertTrue(keys["images"], "Expected to find images stanza")
   114          self.assertFalse(keys["stream"], "Expected to find stream progress stanza's")
   115  
   116      def test_create(self):
   117          r = requests.post(
   118              self.podman_url + "/v1.40/images/create?fromImage=alpine&platform=linux/amd64/v8",
   119              timeout=15,
   120          )
   121          self.assertEqual(r.status_code, 200, r.text)
   122          r = requests.post(
   123              self.podman_url
   124              + "/v1.40/images/create?fromSrc=-&repo=fedora&message=testing123&platform=linux/amd64",
   125              timeout=15,
   126          )
   127          self.assertEqual(r.status_code, 200, r.text)
   128  
   129      def test_search_compat(self):
   130          url = self.podman_url + "/v1.40/images/search"
   131  
   132          # Had issues with this test hanging when repositories not happy
   133          def do_search1():
   134              payload = {"term": "alpine"}
   135              r = requests.get(url, params=payload, timeout=5)
   136              self.assertEqual(r.status_code, 200, f"#1: {r.text}")
   137              self.assertIsInstance(r.json(), list)
   138  
   139          def do_search2():
   140              payload = {"term": "alpine", "limit": 1}
   141              r = requests.get(url, params=payload, timeout=5)
   142              self.assertEqual(r.status_code, 200, f"#2: {r.text}")
   143  
   144              results = r.json()
   145              self.assertIsInstance(results, list)
   146              self.assertEqual(len(results), 1)
   147  
   148          def do_search3():
   149              # FIXME: Research if quay.io supports is-official and which image is "official"
   150              return
   151              payload = {"term": "thanos", "filters": '{"is-official":["true"]}'}
   152              r = requests.get(url, params=payload, timeout=5)
   153              self.assertEqual(r.status_code, 200, f"#3: {r.text}")
   154  
   155              results = r.json()
   156              self.assertIsInstance(results, list)
   157  
   158              # There should be only one official image
   159              self.assertEqual(len(results), 1)
   160  
   161          def do_search4():
   162              headers = {"X-Registry-Auth": "null"}
   163              payload = {"term": "alpine"}
   164              r = requests.get(url, params=payload, headers=headers, timeout=5)
   165              self.assertEqual(r.status_code, 200, f"#4: {r.text}")
   166  
   167          def do_search5():
   168              headers = {"X-Registry-Auth": "invalid value"}
   169              payload = {"term": "alpine"}
   170              r = requests.get(url, params=payload, headers=headers, timeout=5)
   171              self.assertEqual(r.status_code, 400, f"#5: {r.text}")
   172  
   173          i = 1
   174          for fn in [do_search1, do_search2, do_search3, do_search4, do_search5]:
   175              with self.subTest(i=i):
   176                  search = Process(target=fn)
   177                  search.start()
   178                  search.join(timeout=10)
   179                  self.assertFalse(search.is_alive(), f"#{i} /images/search took too long")
   180  
   181          # search_methods = [do_search1, do_search2, do_search3, do_search4, do_search5]
   182          # for search_method in search_methods:
   183          #     search = Process(target=search_method)
   184          #     search.start()
   185          #     search.join(timeout=10)
   186          #     self.assertFalse(search.is_alive(), "/images/search took too long")
   187  
   188      def test_history(self):
   189          r = requests.get(self.podman_url + "/v1.40/images/alpine/history")
   190          self.assertEqual(r.status_code, 200, r.text)
   191  
   192          # See https://docs.docker.com/engine/api/v1.40/#operation/ImageHistory
   193          required_keys = ("Id", "Created", "CreatedBy", "Tags", "Size", "Comment")
   194  
   195          changes = r.json()
   196          self.assertIsInstance(changes, list)
   197          for change in changes:
   198              self.assertIsInstance(change, dict)
   199              for k in required_keys:
   200                  self.assertIn(k, change)
   201  
   202      def test_tree(self):
   203          r = requests.get(self.uri("/images/alpine/tree"))
   204          self.assertEqual(r.status_code, 200, r.text)
   205          tree = r.json()
   206          self.assertTrue(tree["Tree"].startswith("Image ID:"), r.text)
   207  
   208  
   209  if __name__ == "__main__":
   210      unittest.main()