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()