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 committed Jun 26, 2023
1 parent 0a1ce01 commit 682e103
Show file tree
Hide file tree
Showing 2 changed files with 240 additions and 0 deletions.
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
239 changes: 239 additions & 0 deletions tests/test_oci_features.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
#!/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 ctypes
from tests_utils import *

def is_systemd_enabled():
try:
subprocess.check_output(["systemctl", "status"])
return True
except subprocess.CalledProcessError:
return False

def is_seccomp_enabled():
try:
with open('/proc/self/status', 'r') as status_file:
for line in status_file:
if line.startswith('Seccomp:'):
value = line.split(':')[1].strip()
return int(value) > 0
except IOError:
pass

return False
def get_libseccomp_version():
# Load the libseccomp library using ctypes
libseccomp = ctypes.CDLL('libseccomp.so')

# Define the required C function signature
libseccomp.seccomp_version.argtypes = []
libseccomp.seccomp_version.restype = ctypes.c_uint32

# Call the seccomp_version function to get the version
version = libseccomp.seccomp_version()

# Extract the major, minor, and micro version numbers
major = (version >> 16) & 0xff
minor = (version >> 8) & 0xff
micro = version & 0xff

# Return the version as a string
return f'{major}.{minor}.{micro}'

def get_crun_info():
try:
# Get crun commit
commit = subprocess.check_output(["crun", "--version"]).decode().strip()

# Get crun version
version = subprocess.check_output(["crun", "--commit"]).decode().strip()

return commit, version
except subprocess.CalledProcessError:
# Handle error if crun command fails
return None, None

def test_crun_features():
try:
output = run_crun_command(["features"])
features = json.loads(output)
print("Complete features dictionary:", features)
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.crun.checkpoint.enabled": True,
}
}

systemd_enabled = is_systemd_enabled()
seccomp_enabled = is_seccomp_enabled()

if seccomp_enabled:
expected_features["linux"]["seccomp"]["enabled"] = True
expected_features["annotations"]["io.github.seccomp.libseccomp.version"] = get_libseccomp_version()
crun_commit, crun_version = get_crun_info()
expected_features["io.github.containers.crun.commit"] = crun_commit
expected_features["io.github.containers.crun.version"] = crun_version


# 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 not in features or features[key] != value:
print(f"Mismatch in feature: {key}")
print(f"Expected: {value}")
print(f"Actual: {features.get(key)}")
return -1

print("All features matched partially!")
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 682e103

Please sign in to comment.