1use std::fmt::Debug;
2use std::fmt::Write;
3
4pub type RawPid = i32;
6
7mod cmd;
8mod command;
9mod containerd;
10mod docker;
11mod errors;
12mod kubernetes;
13mod lxc;
14mod lxd;
15mod nspawn;
16mod podman;
17mod process_id;
18
19pub use errors::Error;
20
21pub trait Container: Debug {
22 fn lookup(&self, id: &str) -> Result<RawPid, Error>;
23 fn check_required_tools(&self) -> Result<(), Error>;
24}
25
26pub const AVAILABLE_CONTAINER_TYPES: &[&str] = &[
27 "process_id",
28 "podman",
29 "docker",
30 "nspawn",
31 "lxc",
32 "lxd",
33 "command",
34 "containerd",
35 "kubernetes",
36];
37
38fn default_order() -> Vec<Box<dyn Container>> {
39 let containers: Vec<Box<dyn Container>> = vec![
40 Box::new(process_id::ProcessId {}),
41 Box::new(podman::Podman {}),
42 Box::new(docker::Docker {}),
43 Box::new(nspawn::Nspawn {}),
44 Box::new(lxc::Lxc {}),
45 Box::new(lxd::Lxd {}),
46 Box::new(containerd::Containerd {}),
47 Box::new(kubernetes::Kubernetes {}),
48 ];
49 containers
50 .into_iter()
51 .filter(|c| c.check_required_tools().is_ok())
52 .collect()
53}
54
55pub fn lookup_container_type(name: &str) -> Option<Box<dyn Container>> {
56 Some(match name {
57 "process_id" => Box::new(process_id::ProcessId {}),
58 "podman" => Box::new(podman::Podman {}),
59 "docker" => Box::new(docker::Docker {}),
60 "nspawn" => Box::new(nspawn::Nspawn {}),
61 "lxc" => Box::new(lxc::Lxc {}),
62 "lxd" => Box::new(lxd::Lxd {}),
63 "containerd" => Box::new(containerd::Containerd {}),
64 "command" => Box::new(command::Command {}),
65 "kubernetes" => Box::new(kubernetes::Kubernetes {}),
66 _ => return None,
67 })
68}
69
70pub fn lookup_container_pid(
71 container_id: &str,
72 container_types: &[Box<dyn Container>],
73) -> Result<RawPid, Error> {
74 for c in container_types {
75 c.check_required_tools()?;
76 }
77 let fallback: Vec<Box<dyn Container>> = default_order();
78 let types = if container_types.is_empty() {
79 fallback.as_slice()
80 } else {
81 container_types
82 };
83
84 let mut tried = String::new();
85 for t in types {
86 match t.lookup(container_id) {
87 Ok(pid) => return Ok(pid),
88 Err(e) => {
89 let _ = write!(tried, "\n - {:?}: {}", t, errors::format_chain(&e));
90 }
91 };
92 }
93
94 Err(Error::NoRuntimeMatched {
95 container: container_id.to_string(),
96 tried,
97 })
98}