diff options
Diffstat (limited to 'test/apiv2')
-rw-r--r-- | test/apiv2/10-images.at | 29 | ||||
-rw-r--r-- | test/apiv2/40-pods.at | 4 | ||||
-rw-r--r-- | test/apiv2/rest_api/__init__.py | 0 | ||||
-rw-r--r-- | test/apiv2/rest_api/test_rest_v1_0_0.py | 219 | ||||
-rwxr-xr-x | test/apiv2/test-apiv2 | 21 |
5 files changed, 262 insertions, 11 deletions
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index 1c8da0c2f..1c7ba8948 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -7,15 +7,15 @@ podman pull -q $IMAGE t GET libpod/images/json 200 \ - .[0].ID~[0-9a-f]\\{64\\} -iid=$(jq -r '.[0].ID' <<<"$output") + .[0].Id~[0-9a-f]\\{64\\} +iid=$(jq -r '.[0].Id' <<<"$output") t GET libpod/images/$iid/exists 204 t GET libpod/images/$PODMAN_TEST_IMAGE_NAME/exists 204 # FIXME: compare to actual podman info t GET libpod/images/json 200 \ - .[0].ID=${iid} + .[0].Id=${iid} t GET libpod/images/$iid/json 200 \ .Id=$iid \ @@ -33,4 +33,27 @@ t GET images/$iid/json 200 \ #t POST images/create fromImage=alpine 201 foo +# Display the image history +t GET libpod/images/nonesuch/history 404 + +for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME; do + t GET libpod/images/$i/history 200 \ + .[0].Id=$iid \ + .[0].Created~[0-9]\\{10\\} \ + .[0].Tags=null \ + .[0].Size=0 \ + .[0].Comment= +done + +# Export an image on the local +t GET libpod/images/nonesuch/get 404 +t GET libpod/images/$iid/get?format=foo 500 +t GET libpod/images/$PODMAN_TEST_IMAGE_NAME/get?compress=bar 400 + +for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME; do + t GET "libpod/images/$i/get" 200 '[POSIX tar archive]' + t GET "libpod/images/$i/get?compress=true" 200 '[POSIX tar archive]' + t GET "libpod/images/$i/get?compress=false" 200 '[POSIX tar archive]' +done + # vim: filetype=sh diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at index 26877a102..2dea1918a 100644 --- a/test/apiv2/40-pods.at +++ b/test/apiv2/40-pods.at @@ -5,8 +5,8 @@ t GET "libpod/pods/json (clean slate at start)" 200 null -t POST libpod/pods/create name=foo 201 .id~[0-9a-f]\\{64\\} -pod_id=$(jq -r .id <<<"$output") +t POST libpod/pods/create name=foo 201 .Id~[0-9a-f]\\{64\\} +pod_id=$(jq -r .Id <<<"$output") t GET libpod/pods/foo/exists 204 t GET libpod/pods/$pod_id/exists 204 t GET libpod/pods/notfoo/exists 404 diff --git a/test/apiv2/rest_api/__init__.py b/test/apiv2/rest_api/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/test/apiv2/rest_api/__init__.py diff --git a/test/apiv2/rest_api/test_rest_v1_0_0.py b/test/apiv2/rest_api/test_rest_v1_0_0.py new file mode 100644 index 000000000..7c53623cb --- /dev/null +++ b/test/apiv2/rest_api/test_rest_v1_0_0.py @@ -0,0 +1,219 @@ +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 + + +def _url(path): + return "http://localhost:8080/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=docker.io%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 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() diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index 1af76b4be..7a3518df2 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -207,13 +207,21 @@ function t() { fi cat $WORKDIR/curl.headers.out >>$LOG 2>/dev/null || true - output=$(< $WORKDIR/curl.result.out) - # Log results. If JSON, filter through jq for readability - if egrep -qi '^Content-Type: application/json' $WORKDIR/curl.headers.out; then - jq . <<<"$output" >>$LOG - else + # Log results, if text. If JSON, filter through jq for readability. + content_type=$(sed -ne 's/^Content-Type:[ ]\+//pi' <$WORKDIR/curl.headers.out) + + if [[ $content_type =~ /octet ]]; then + output="[$(file --brief $WORKDIR/curl.result.out)]" echo "$output" >>$LOG + else + output=$(< $WORKDIR/curl.result.out) + + if [[ $content_type =~ application/json ]]; then + jq . <<<"$output" >>$LOG + else + echo "$output" >>$LOG + fi fi # Test return code @@ -232,6 +240,7 @@ function t() { return fi + local i for i; do case "$i" in # Exact match on json field @@ -270,7 +279,7 @@ function start_service() { die "Cannot start service on non-localhost ($HOST)" fi - $PODMAN_BIN --root $WORKDIR system service --timeout 15 tcp:127.0.0.1:$PORT \ + $PODMAN_BIN --root $WORKDIR system service --time 15 tcp:127.0.0.1:$PORT \ &> $WORKDIR/server.log & service_pid=$! |