Skip to content

Commit

Permalink
tests: add test for oci_features
Browse files Browse the repository at this point in the history
Signed-off-by: Sohan Kunkerkar <sohank2602@gmail.com>
  • Loading branch information
sohankunkerkar authored and giuseppe committed Jun 27, 2023
1 parent 366af73 commit 935f4fe
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ PYTHON_TESTS = tests/test_capabilities.py \
tests/test_devices.py \
tests/test_hostname.py \
tests/test_limits.py \
tests/test_oci_features.py \
tests/test_mounts.py \
tests/test_paths.py \
tests/test_pid.py \
Expand Down
2 changes: 1 addition & 1 deletion src/libcrun/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -3920,7 +3920,7 @@ libcrun_container_get_features (libcrun_context_t *context arg_unused, struct fe
}
#endif

#if HAVE_CRIU && HAVE_DLOPEN
#if HAVE_CRIU
(*info)->annotations.run_oci_crun_checkpoint_enabled = true;
#endif
(*info)->annotations.run_oci_crun_commit = GIT_VERSION;
Expand Down
220 changes: 220 additions & 0 deletions tests/test_oci_features.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
#!/bin/env python3
# crun - OCI runtime written in C
#
# crun is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# crun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with crun. If not, see <http://www.gnu.org/licenses/>.

import subprocess
import json
import re
from tests_utils import *

def is_systemd_enabled():
return 'SYSTEMD' in get_crun_feature_string()

def is_seccomp_enabled():
return 'SECCOMP' in get_crun_feature_string()

def get_crun_commit():
try:
output = subprocess.check_output(["./crun", "--version"]).decode()
commit_match = re.search(r"commit: ([\w]+)", output)

if commit_match:
return commit_match.group(1)
else:
raise ValueError("Commit information not found")

except (subprocess.CalledProcessError, ValueError) as e:
print(f"Error retrieving crun commit: {str(e)}")
return None

def test_crun_features():
try:
output = run_crun_command(["features"])
features = json.loads(output)
expected_features = {
"ociVersionMin": "1.0.0",
"ociVersionMax": "1.1.0-rc.3",
"hooks": [
"prestart",
"createRuntime",
"createContainer",
"startContainer",
"poststart",
"poststop"
],
"mountOptions": [
"rw",
"rrw",
"ro",
"rro",
"rdirsync",
"rdiratime",
"rnodev",
"rnorelatime",
"nodiratime",
"rnodiratime",
"diratime",
"rnoatime",
"rnomand",
"ratime",
"rmand",
"mand",
"idmap",
"noatime",
"nomand",
"dirsync",
"rnosuid",
"atime",
"rnoexec",
"nodev",
"rbind",
"norelatime",
"bind",
"rnostrictatime",
"strictatime",
"rstrictatime",
"rprivate",
"rsuid",
"remount",
"suid",
"nostrictatime",
"rrelatime",
"nosuid",
"noexec",
"rslave",
"dev",
"rdev",
"rsync",
"relatime",
"sync",
"shared",
"rshared",
"unbindable",
"runbindable",
"defaults",
"async",
"rasync",
"private",
"tmpcopyup",
"rexec",
"exec",
"slave"
],
"linux": {
"namespaces": [
"cgroup",
"ipc",
"mount",
"network",
"pid",
"user",
"uts"
],
"capabilities": [
],
"cgroup": {
"v1": True,
"v2": True,
},
"seccomp": {
"actions": [
"SCMP_ACT_ALLOW",
"SCMP_ACT_ERRNO",
"SCMP_ACT_KILL",
"SCMP_ACT_KILL_PROCESS",
"SCMP_ACT_KILL_THREAD",
"SCMP_ACT_LOG",
"SCMP_ACT_NOTIFY",
"SCMP_ACT_TRACE",
"SCMP_ACT_TRAP"
],
"operators": [
"SCMP_CMP_NE",
"SCMP_CMP_LT",
"SCMP_CMP_LE",
"SCMP_CMP_EQ",
"SCMP_CMP_GE",
"SCMP_CMP_GT",
"SCMP_CMP_MASKED_EQ"
]
},
"apparmor": {
"enabled": True
},
"selinux": {
"enabled": True
}
},
"annotations": {
"org.opencontainers.runc.checkpoint.enabled": True,
"run.oci.checkpoint.enabled": True,
"run.oci.commit": get_crun_commit(),
}
}

systemd_enabled = is_systemd_enabled()
seccomp_enabled = is_seccomp_enabled()

if seccomp_enabled:
expected_features["linux"]["seccomp"]["enabled"] = True

# Check if systemd is enabled and set systemdUser accordingly
if systemd_enabled:
expected_features["linux"]["cgroup"]["systemd"] = True
expected_features["linux"]["cgroup"]["systemdUser"] = True

for key, value in expected_features.items():
if key == "linux" and isinstance(value, dict) and "capabilities" in value:
if "capabilities" in features.get("linux", {}):
capabilities = features["linux"]["capabilities"]
if not ("CAP_SYS_ADMIN" in capabilities and "CAP_KILL" in capabilities and "CAP_NET_BIND_SERVICE" in capabilities):
return -1
continue

if key == "annotations":
if "annotations" not in features:
sys.stderr.write("Annotations section is missing\n")
return -1

annotations = features["annotations"]
if annotations.get("run.oci.crun.commit") != get_crun_commit():
sys.stderr.write("wrong value for run.oci.crun.commit\n")
return -1

if 'CRIU' in get_crun_feature_string():
if annotations.get("org.opencontainers.runc.checkpoint.enabled") is not True:
sys.stderr.write("wrong value for org.opencontainers.runc.checkpoint.enabled\n")
return -1
if annotations.get("run.oci.crun.checkpoint.enabled") is not True:
sys.stderr.write("wrong value for run.oci.crun.checkpoint.enabled\n")
return -1
else:
if key not in features or features[key] != value:
sys.stderr.write(f"Mismatch in feature: {key}\n")
sys.stderr.write(f"Expected: {value}\n")
sys.stderr.write(f"Actual: {features.get(key)}\n")
return -1
return 0

except Exception as e:
print("Error running crun features:", str(e))
return -1

all_tests = {
"crun-features" : test_crun_features,
}

if __name__ == "__main__":
tests_main(all_tests)

0 comments on commit 935f4fe

Please sign in to comment.