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