From ec4c1b1d703e1232984caf8ab34ec121ba99f564 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 6 Feb 2024 20:22:30 +0100 Subject: [PATCH] test/case: new test, basic container test - New helper class for container testing - New helper class to urllib, Furl Due to extremely weak Python-fu in the undersigned, this patch changes the __init__.py file to add new helper classes for container tests. Signed-off-by: Joachim Wiberg --- test/case/all.yaml | 3 + test/case/infix_containers/all.yaml | 3 + test/case/infix_containers/container_basic.py | 58 +++++++++++++++++++ test/infamy/__init__.py | 2 + test/infamy/container.py | 44 ++++++++++++++ test/infamy/furl.py | 24 ++++++++ 6 files changed, 134 insertions(+) create mode 100644 test/case/infix_containers/all.yaml create mode 100755 test/case/infix_containers/container_basic.py create mode 100644 test/infamy/container.py create mode 100644 test/infamy/furl.py diff --git a/test/case/all.yaml b/test/case/all.yaml index 1e6dd78e..12edc8c2 100644 --- a/test/case/all.yaml +++ b/test/case/all.yaml @@ -16,6 +16,9 @@ - name: ietf-routing suite: ietf_routing/all.yaml +- name: infix-containers + suite: infix_containers/all.yaml + - name: infix-dhcp suite: infix_dhcp/all.yaml diff --git a/test/case/infix_containers/all.yaml b/test/case/infix_containers/all.yaml new file mode 100644 index 00000000..c4fb342d --- /dev/null +++ b/test/case/infix_containers/all.yaml @@ -0,0 +1,3 @@ +--- + +- case: container_basic.py diff --git a/test/case/infix_containers/container_basic.py b/test/case/infix_containers/container_basic.py new file mode 100755 index 00000000..7c8ae5e6 --- /dev/null +++ b/test/case/infix_containers/container_basic.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# +# Verify that a simple web server container can be configured to run +# with host networking, on port 80. Operation is verified using a +# simple GET request for index.html and checking for a key phrase. +# +# The RPC actions: stop + start, and restart are also verified. +# + +import infamy +from infamy.util import until + +def _verify(server): + url = infamy.Furl(f"http://[{server}]/index.html") + return url.check("It works") + +with infamy.Test() as test: + NAME = "web" + IMAGE = "curios-httpd-edge.tar.gz" + + with test.step("Set up topology and attach to target DUT"): + env = infamy.Env(infamy.std_topology("1x2")) + target = env.attach("target", "mgmt") + addr = target.address() + + with test.step(f"Create {NAME} container from bundled OCI image"): + target.put_config_dict("infix-containers", { + "containers": { + "container": [ + { + "name": f"{NAME}", + "image": f"oci-archive:{IMAGE}", + "network": { + "host": True + } + } + ] + } + }) + + with test.step(f"Verify {NAME} continer has started"): + c = infamy.Container(target) + until(lambda: c.running(NAME), attempts=10) + + with test.step(f"Verify {NAME} container responds"): + until(lambda: _verify(addr), attempts=10) + + with test.step(f"Verify {NAME} container can be stopped and restarted"): + c = infamy.Container(target) + c.action(NAME, "stop") + until(lambda: not c.running(NAME), attempts=10) + c.action(NAME, "restart") + + with test.step(f"Verify {NAME} container still responds"): + # Wait for it to restart and respond, or fail + until(lambda: _verify(addr), attempts=10) + + test.succeed() diff --git a/test/infamy/__init__.py b/test/infamy/__init__.py index cd89e4c8..ba217045 100644 --- a/test/infamy/__init__.py +++ b/test/infamy/__init__.py @@ -1,6 +1,8 @@ import os +from .container import Container from .env import Env +from .furl import Furl from .netns import IsolatedMacVlan from .sniffer import Sniffer from .tap import Test diff --git a/test/infamy/container.py b/test/infamy/container.py new file mode 100644 index 00000000..7332dd93 --- /dev/null +++ b/test/infamy/container.py @@ -0,0 +1,44 @@ +"""Manage Infix containers""" + +class Container: + """Helper methods""" + + def __init__(self, target): + self.system = target + + def _find(self, name): + oper = self.system.get_data("/infix-containers:containers/container") + if not oper: + return None + + for container in oper["containers"]["container"]: + if container["name"] == name: + return container + return None + + def exists(self, name): + """Check if container {name} runs on target.""" + container = self._find(name) + if not container: + return False + return True + + def running(self, name): + """Check if container {name} exists and is running.""" + container = self._find(name) + if container and container["running"]: + return True + return False + + def action(self, name, act): + """Call NETCONF action 'type' on container 'name'""" + return self.system.call_action_dict("infix-containers", { + "containers": { + "container": [ + { + "name": f"{name}", + f"{act}": {} + } + ] + } + }) diff --git a/test/infamy/furl.py b/test/infamy/furl.py new file mode 100644 index 00000000..3f7c8a96 --- /dev/null +++ b/test/infamy/furl.py @@ -0,0 +1,24 @@ +"""Fugly URL fetcher""" + +import urllib.error +import urllib.request + +class Furl: + """Furl wraps urllib in a way similar to curl""" + def __init__(self, url): + """Create new URL checker""" + self.url = urllib.parse.quote(url, safe='/:') + + def check(self, needle): + """Connect to web server URL, fetch body and check for needle""" + try: + with urllib.request.urlopen(self.url) as response: + text = response.read().decode('utf-8') + #print(text) + return needle in text + except urllib.error.URLError as _: + return False + + def nscheck(self, netns, needle): + """"Call check() from netns""" + return netns.call(lambda: self.check(needle))