use std::{
fs,
path::{Path, PathBuf},
};
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use oci_spec::runtime::{Hooks, Spec};
use crate::utils;
const YOUKI_CONFIG_NAME: &str = "youki_config.json";
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct YoukiConfig {
pub hooks: Option<Hooks>,
pub cgroup_path: PathBuf,
}
impl<'a> YoukiConfig {
pub fn from_spec(spec: &'a Spec, container_id: &str, rootless: bool) -> Result<Self> {
Ok(YoukiConfig {
hooks: spec.hooks().clone(),
cgroup_path: utils::get_cgroup_path(
spec.linux()
.as_ref()
.context("no linux in spec")?
.cgroups_path(),
container_id,
rootless,
),
})
}
pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let file = fs::File::create(path.as_ref().join(YOUKI_CONFIG_NAME))?;
serde_json::to_writer(&file, self)?;
Ok(())
}
pub fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
let path = path.as_ref();
let file = fs::File::open(path.join(YOUKI_CONFIG_NAME))?;
let config = serde_json::from_reader(&file)
.with_context(|| format!("failed to load config from {:?}", path))?;
Ok(config)
}
}
#[cfg(test)]
mod tests {
use crate::utils::create_temp_dir;
use super::*;
use anyhow::Result;
#[test]
fn test_config_from_spec() -> Result<()> {
let container_id = "sample";
let spec = Spec::default();
let config = YoukiConfig::from_spec(&spec, container_id, false)?;
assert_eq!(&config.hooks, spec.hooks());
dbg!(&config.cgroup_path);
assert_eq!(config.cgroup_path, PathBuf::from(container_id));
Ok(())
}
#[test]
fn test_config_save_and_load() -> Result<()> {
let container_id = "sample";
let tmp = create_temp_dir("test_config_save_and_load").expect("create test directory");
let spec = Spec::default();
let config = YoukiConfig::from_spec(&spec, container_id, false)?;
config.save(&tmp)?;
let act = YoukiConfig::load(&tmp)?;
assert_eq!(act, config);
Ok(())
}
}