1use std::fs::create_dir_all;
2use std::path::PathBuf;
3use std::sync::Arc;
4
5use crate::{Cgroup, Mount, NetworkManager, UserMapper};
6
7pub type Error = Box<dyn std::error::Error + Send + Sync>;
8
9#[derive(Clone, Debug, Default)]
10pub struct ContainerOptions {
11 rootfs: Option<PathBuf>,
12 cgroup: Option<Cgroup>,
13 user_mapper: Option<Arc<dyn UserMapper>>,
14 network_manager: Option<Arc<dyn NetworkManager>>,
15 mounts: Vec<Arc<dyn Mount>>,
16 hostname: String,
17}
18
19impl ContainerOptions {
20 pub fn new() -> Self {
21 Default::default()
22 }
23
24 pub fn rootfs(mut self, rootfs: PathBuf) -> Self {
25 self.rootfs = Some(rootfs);
26 self
27 }
28
29 pub fn cgroup(mut self, cgroup: Cgroup) -> Self {
30 self.cgroup = Some(cgroup);
31 self
32 }
33
34 pub fn user_mapper<T: UserMapper + 'static>(mut self, user_mapper: T) -> Self {
35 self.user_mapper = Some(Arc::new(user_mapper));
36 self
37 }
38
39 pub fn network_manager<T: NetworkManager + 'static>(mut self, network_manager: T) -> Self {
40 self.network_manager = Some(Arc::new(network_manager));
41 self
42 }
43
44 pub fn add_mount<T: Mount + 'static>(mut self, mount: T) -> Self {
45 self.mounts.push(Arc::new(mount));
46 self
47 }
48
49 pub fn hostname<T: ToString>(mut self, hostname: T) -> Self {
50 self.hostname = hostname.to_string();
51 self
52 }
53
54 pub fn create(self) -> Result<Container, Error> {
55 let rootfs = self.rootfs.ok_or("Container rootfs should specified")?;
56 let cgroup = self.cgroup.ok_or("Container cgroup should specified")?;
57 let user_mapper = self
58 .user_mapper
59 .ok_or("Container user mapper should specified")?;
60 let network_manager = self.network_manager;
61 let mounts = self.mounts;
62 let hostname = self.hostname;
63 create_dir_all(&rootfs)?;
64 cgroup.create()?;
65 Ok(Container {
66 rootfs,
67 cgroup,
68 user_mapper,
69 network_manager,
70 mounts,
71 hostname,
72 })
73 }
74}
75
76pub struct Container {
77 pub(super) rootfs: PathBuf,
78 pub(super) cgroup: Cgroup,
79 pub(super) user_mapper: Arc<dyn UserMapper>,
80 pub(super) network_manager: Option<Arc<dyn NetworkManager>>,
81 pub(super) mounts: Vec<Arc<dyn Mount>>,
82 pub(super) hostname: String,
83}
84
85impl Container {
86 pub fn options() -> ContainerOptions {
87 ContainerOptions::new()
88 }
89}