diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2021-05-18 13:22:57 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-18 13:22:57 -0400 |
commit | 353f04b53cd0a7c89ac8b2eb836eeb9c0dfa7b6a (patch) | |
tree | ca7183d0ad42e7499e75eca685edc9a1afd1b3be /test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py | |
parent | d1d21f069a51fd51bc4ecdc1e003add4eea6c9a6 (diff) | |
parent | 98955bedbcb3256d63f12716332000586eb6fe31 (diff) | |
download | podman-353f04b53cd0a7c89ac8b2eb836eeb9c0dfa7b6a.tar.gz podman-353f04b53cd0a7c89ac8b2eb836eeb9c0dfa7b6a.tar.bz2 podman-353f04b53cd0a7c89ac8b2eb836eeb9c0dfa7b6a.zip |
Merge pull request #10372 from jwhonce/issues/9238
Break up python APIv2 tests
Diffstat (limited to 'test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py')
-rw-r--r-- | test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py b/test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py new file mode 100644 index 000000000..905c29683 --- /dev/null +++ b/test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py @@ -0,0 +1,238 @@ +import json +import os +import shlex +import signal +import string +import subprocess +import sys +import time +import unittest +from collections.abc import Iterable +from multiprocessing import Process + +import requests +from dateutil.parser import parse + +PODMAN_URL = "http://localhost:8080" + + +def _url(path): + return PODMAN_URL + "/v1.0.0/libpod" + path + + +def podman(): + binary = os.getenv("PODMAN_BINARY") + if binary is None: + binary = "bin/podman" + return binary + + +def ctnr(path): + r = requests.get(_url("/containers/json?all=true")) + try: + ctnrs = json.loads(r.text) + except Exception as e: + sys.stderr.write("Bad container response: {}/{}".format(r.text, e)) + raise e + return path.format(ctnrs[0]["Id"]) + + +class TestApi(unittest.TestCase): + podman = None + + def setUp(self): + super().setUp() + if TestApi.podman.poll() is not None: + sys.stderr.write("podman service returned {}", TestApi.podman.returncode) + sys.exit(2) + requests.get(_url("/images/create?fromSrc=quay.io%2Flibpod%2Falpine%3Alatest")) + # calling out to podman is easier than the API for running a container + subprocess.run( + [podman(), "run", "alpine", "/bin/ls"], + check=True, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + + @classmethod + def setUpClass(cls): + super().setUpClass() + + TestApi.podman = subprocess.Popen( + [ + podman(), + "system", + "service", + "tcp:localhost:8080", + "--log-level=debug", + "--time=0", + ], + shell=False, + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + time.sleep(2) + + @classmethod + def tearDownClass(cls): + TestApi.podman.terminate() + stdout, stderr = TestApi.podman.communicate(timeout=0.5) + if stdout: + print("\nService Stdout:\n" + stdout.decode("utf-8")) + if stderr: + print("\nService Stderr:\n" + stderr.decode("utf-8")) + + if TestApi.podman.returncode > 0: + sys.stderr.write("podman exited with error code {}\n".format(TestApi.podman.returncode)) + sys.exit(2) + + return super().tearDownClass() + + def test_info(self): + r = requests.get(_url("/info")) + self.assertEqual(r.status_code, 200) + self.assertIsNotNone(r.content) + _ = json.loads(r.text) + + def test_events(self): + r = requests.get(_url("/events?stream=false")) + self.assertEqual(r.status_code, 200, r.text) + self.assertIsNotNone(r.content) + for line in r.text.splitlines(): + obj = json.loads(line) + # Actor.ID is uppercase for compatibility + _ = obj["Actor"]["ID"] + + def test_containers(self): + r = requests.get(_url("/containers/json"), timeout=5) + self.assertEqual(r.status_code, 200, r.text) + obj = json.loads(r.text) + self.assertEqual(len(obj), 0) + + def test_containers_all(self): + r = requests.get(_url("/containers/json?all=true")) + self.assertEqual(r.status_code, 200, r.text) + self.validateObjectFields(r.text) + + def test_inspect_container(self): + r = requests.get(_url(ctnr("/containers/{}/json"))) + self.assertEqual(r.status_code, 200, r.text) + obj = self.validateObjectFields(r.content) + _ = parse(obj["Created"]) + + def test_stats(self): + r = requests.get(_url(ctnr("/containers/{}/stats?stream=false"))) + self.assertIn(r.status_code, (200, 409), r.text) + if r.status_code == 200: + self.validateObjectFields(r.text) + + def test_delete_containers(self): + r = requests.delete(_url(ctnr("/containers/{}"))) + self.assertEqual(r.status_code, 204, r.text) + + def test_stop_containers(self): + r = requests.post(_url(ctnr("/containers/{}/start"))) + self.assertIn(r.status_code, (204, 304), r.text) + + r = requests.post(_url(ctnr("/containers/{}/stop"))) + self.assertIn(r.status_code, (204, 304), r.text) + + def test_start_containers(self): + r = requests.post(_url(ctnr("/containers/{}/stop"))) + self.assertIn(r.status_code, (204, 304), r.text) + + r = requests.post(_url(ctnr("/containers/{}/start"))) + self.assertIn(r.status_code, (204, 304), r.text) + + def test_restart_containers(self): + r = requests.post(_url(ctnr("/containers/{}/start"))) + self.assertIn(r.status_code, (204, 304), r.text) + + r = requests.post(_url(ctnr("/containers/{}/restart")), timeout=5) + self.assertEqual(r.status_code, 204, r.text) + + def test_resize(self): + r = requests.post(_url(ctnr("/containers/{}/resize?h=43&w=80"))) + self.assertIn(r.status_code, (200, 409), r.text) + if r.status_code == 200: + self.assertIsNone(r.text) + + def test_attach_containers(self): + r = requests.post(_url(ctnr("/containers/{}/attach"))) + self.assertIn(r.status_code, (101, 409), r.text) + + def test_logs_containers(self): + r = requests.get(_url(ctnr("/containers/{}/logs?stdout=true"))) + self.assertEqual(r.status_code, 200, r.text) + + def test_post_create(self): + self.skipTest("TODO: create request body") + r = requests.post(_url("/containers/create?args=True")) + self.assertEqual(r.status_code, 200, r.text) + json.loads(r.text) + + def test_commit(self): + r = requests.post(_url(ctnr("/commit?container={}"))) + self.assertEqual(r.status_code, 200, r.text) + self.validateObjectFields(r.text) + + def test_images(self): + r = requests.get(_url("/images/json")) + self.assertEqual(r.status_code, 200, r.text) + self.validateObjectFields(r.content) + + def test_inspect_image(self): + r = requests.get(_url("/images/alpine/json")) + self.assertEqual(r.status_code, 200, r.text) + obj = self.validateObjectFields(r.content) + _ = parse(obj["Created"]) + + def test_delete_image(self): + r = requests.delete(_url("/images/alpine?force=true")) + self.assertEqual(r.status_code, 200, r.text) + json.loads(r.text) + + def test_pull(self): + r = requests.post(_url("/images/pull?reference=alpine"), timeout=5) + self.assertEqual(r.status_code, 200, r.text) + json.loads(r.text) + + def test_search(self): + # Had issues with this test hanging when repositories not happy + def do_search(): + r = requests.get(_url("/images/search?term=alpine"), timeout=5) + self.assertEqual(r.status_code, 200, r.text) + json.loads(r.text) + + search = Process(target=do_search) + search.start() + search.join(timeout=10) + self.assertFalse(search.is_alive(), "/images/search took too long") + + def test_ping(self): + r = requests.get(PODMAN_URL + "/_ping") + self.assertEqual(r.status_code, 200, r.text) + + r = requests.head(PODMAN_URL + "/_ping") + self.assertEqual(r.status_code, 200, r.text) + + r = requests.get(_url("/_ping")) + self.assertEqual(r.status_code, 200, r.text) + + r = requests.get(_url("/_ping")) + self.assertEqual(r.status_code, 200, r.text) + + +def validateObjectFields(self, buffer): + objs = json.loads(buffer) + if not isinstance(objs, dict): + for o in objs: + _ = o["Id"] + else: + _ = objs["Id"] + return objs + + +if __name__ == "__main__": + unittest.main() |