use anyhow::Result;
use libcontainer::oci_spec::runtime::{
ApparmorBuilder, CgroupBuilder, FeaturesBuilder, IDMapBuilder, IntelRdtBuilder,
LinuxFeatureBuilder, LinuxNamespaceType, MountExtensionsBuilder, SelinuxBuilder, VERSION,
};
use libcontainer::syscall::linux::MountOption;
use liboci_cli::Features;
fn query_caps() -> Result<Vec<String>> {
Ok(caps::all().iter().map(|cap| format!("{:?}", cap)).collect())
}
fn query_supported_namespaces() -> Result<Vec<LinuxNamespaceType>> {
Ok(vec![
LinuxNamespaceType::Pid,
LinuxNamespaceType::Network,
LinuxNamespaceType::Uts,
LinuxNamespaceType::Ipc,
LinuxNamespaceType::Mount,
LinuxNamespaceType::User,
LinuxNamespaceType::Cgroup,
LinuxNamespaceType::Time,
])
}
fn known_hooks() -> Vec<String> {
[
"prestart",
"createRuntime",
"createContainer",
"startContainer",
"poststart",
"poststop",
]
.iter()
.map(|s| s.to_string())
.collect()
}
pub fn features(_: Features) -> Result<()> {
let namespaces = match query_supported_namespaces() {
Ok(ns) => ns,
Err(e) => {
eprintln!("Error querying supported namespaces: {}", e);
Vec::new()
}
};
let capabilities = match query_caps() {
Ok(caps) => caps,
Err(e) => {
eprintln!("Error querying available capabilities: {}", e);
Vec::new()
}
};
let linux = LinuxFeatureBuilder::default()
.namespaces(namespaces)
.capabilities(capabilities)
.cgroup(
CgroupBuilder::default()
.v1(cfg!(feature = "v1"))
.v2(cfg!(feature = "v2"))
.systemd(cfg!(feature = "systemd"))
.systemd_user(cfg!(feature = "systemd"))
.rdma(false)
.build()
.unwrap(),
)
.apparmor(ApparmorBuilder::default().enabled(true).build().unwrap())
.mount_extensions(
MountExtensionsBuilder::default()
.idmap(IDMapBuilder::default().enabled(false).build().unwrap())
.build()
.unwrap(),
)
.selinux(SelinuxBuilder::default().enabled(false).build().unwrap())
.intel_rdt(IntelRdtBuilder::default().enabled(true).build().unwrap())
.build()
.unwrap();
let features = FeaturesBuilder::default()
.oci_version_max(VERSION)
.oci_version_min(String::from("1.0.0"))
.hooks(known_hooks())
.mount_options(MountOption::known_options())
.linux(linux)
.build()
.unwrap();
let pretty_json_str = serde_json::to_string_pretty(&features)?;
println!("{}", pretty_json_str);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_features() {
let features = Features {};
assert!(crate::commands::features::features(features).is_ok());
}
}