Skip to content

Commit

Permalink
Add udev DH e2e tests (#637)
Browse files Browse the repository at this point in the history
This commit introduces a new testsuite that ensures the udev Discover
Handler is able to discover a basic device, and a grouped device (if
any available).

Signed-off-by: Nicolas Belouin <[email protected]>
  • Loading branch information
diconico07 authored Sep 25, 2023
1 parent 981ea22 commit f01f161
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 12 deletions.
39 changes: 27 additions & 12 deletions test/e2e/helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import time

import kubernetes
from pathlib import Path

Expand Down Expand Up @@ -117,17 +119,26 @@ def assert_akri_instances_present(
):
version = f'v{akri_version.split(".")[0]}'
v1_custom = kubernetes.client.CustomObjectsApi()
instances = v1_custom.list_namespaced_custom_object(
"akri.sh", version, "default", "instances"
)
resource_version = instances["metadata"]["resourceVersion"]
instances = {
instance["metadata"]["name"]
for instance in instances["items"]
if instance["spec"]["configurationName"] == config_name
}

def get_instances():
instances = v1_custom.list_namespaced_custom_object(
"akri.sh", version, "default", "instances"
)
resource_version = instances["metadata"]["resourceVersion"]
instances = {
instance["metadata"]["name"]
for instance in instances["items"]
if instance["spec"]["configurationName"] == config_name
}
return instances, resource_version

instances, resource_version = get_instances()
if len(instances) == count:
return
# Check it is not a transient state
time.sleep(1)
instances, resource_version = get_instances()
if len(instances) == count:
return
w = kubernetes.watch.Watch()
for e in w.stream(
v1_custom.list_namespaced_custom_object,
Expand All @@ -145,6 +156,10 @@ def assert_akri_instances_present(
else:
instances.add(e["raw_object"]["metadata"]["name"])
if len(instances) == count:
w.stop()
return
# Check it is not a transient state
time.sleep(1)
instances, _ = get_instances()
if len(instances) == count:
w.stop()
return
raise AssertionError(f"{count} != {len(instances)}")
86 changes: 86 additions & 0 deletions test/e2e/test_udev.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from pathlib import Path
import time

import yaml
import pytest
import kubernetes
from helpers import assert_akri_instances_present, check_akri_is_healthy


discovery_handlers = ["udev"]


@pytest.fixture
def dev_null_config(akri_version):
with open(Path(__file__).parent / "yaml/udevDevNullConfiguration.yaml") as f:
body = yaml.safe_load(f)
client = kubernetes.client.CustomObjectsApi()
version = f'v{akri_version.split(".")[0]}'
client.create_namespaced_custom_object(
"akri.sh", version, "default", "configurations", body
)

yield body["metadata"]["name"]

client.delete_namespaced_custom_object(
"akri.sh", version, "default", "configurations", body["metadata"]["name"]
)


def test_dev_null_config(akri_version, dev_null_config):
check_akri_is_healthy(discovery_handlers)
assert_akri_instances_present(akri_version, dev_null_config, 1)


@pytest.fixture
def grouped_config(akri_version):
v1_core = kubernetes.client.CoreV1Api()
pods = v1_core.list_namespaced_pod(
"default",
label_selector=f"app.kubernetes.io/name=akri-udev-discovery",
field_selector="status.phase=Running",
).items
base_command = ["/bin/sh", "-c"]
# This command will get the ID_PATH to use to get a device with many "subdevices"
command = "grep -hr ID_PATH= /run/udev/data | sort | uniq -cd | sort -h | tail -1 | cut -d '=' -f 2"
paths = set()
# Get the ID_PATH we can use
for pod in pods:
resp = kubernetes.stream.stream(
v1_core.connect_get_namespaced_pod_exec,
pod.metadata.name,
"default",
command=base_command + [command],
stdout=True,
stdin=False,
stderr=True,
tty=False,
_preload_content=False,
)
try:
paths.add(resp.readline_stdout(timeout=3).strip())
except:
pytest.skip("No udev ?")
if len(paths) == 0:
pytest.skip("No groupable devices found")
path = paths.pop()

with open(Path(__file__).parent / "yaml/udevGroupedConfiguration.yaml") as f:
body = yaml.safe_load(f)
body["spec"]["discoveryHandler"]["discoveryDetails"] = body["spec"][
"discoveryHandler"
]["discoveryDetails"].format(path)
client = kubernetes.client.CustomObjectsApi()
version = f'v{akri_version.split(".")[0]}'
client.create_namespaced_custom_object(
"akri.sh", version, "default", "configurations", body
)
yield body["metadata"]["name"]
client.delete_namespaced_custom_object(
"akri.sh", version, "default", "configurations", body["metadata"]["name"]
)


def test_grouped_config(akri_version, grouped_config):
check_akri_is_healthy(discovery_handlers)
assert_akri_instances_present(akri_version, grouped_config, 1)
10 changes: 10 additions & 0 deletions test/e2e/yaml/udevDevNullConfiguration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: akri.sh/v0
kind: Configuration
metadata:
name: akri-udev-dev-null
spec:
discoveryHandler:
name: udev
discoveryDetails: |+
udevRules:
- KERNEL=="null"
11 changes: 11 additions & 0 deletions test/e2e/yaml/udevGroupedConfiguration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: akri.sh/v0
kind: Configuration
metadata:
name: akri-udev-grouped
spec:
discoveryHandler:
name: udev
discoveryDetails: |+
groupRecursive: true
udevRules:
- ENV{{ID_PATH}}=="{}"

0 comments on commit f01f161

Please sign in to comment.