rustyclaw_core/runtime/
mod.rs1pub mod docker;
11pub mod native;
12pub mod traits;
13
14pub use docker::{DockerRuntime, DockerRuntimeConfig};
15pub use native::NativeRuntime;
16pub use traits::RuntimeAdapter;
17
18use serde::{Deserialize, Serialize};
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct RuntimeConfig {
23 #[serde(default = "default_runtime_kind")]
25 pub kind: String,
26 #[serde(default)]
28 pub docker: DockerRuntimeConfig,
29}
30
31fn default_runtime_kind() -> String {
32 "native".to_string()
33}
34
35impl Default for RuntimeConfig {
36 fn default() -> Self {
37 Self {
38 kind: default_runtime_kind(),
39 docker: DockerRuntimeConfig::default(),
40 }
41 }
42}
43
44pub fn create_runtime(config: &RuntimeConfig) -> anyhow::Result<Box<dyn RuntimeAdapter>> {
46 match config.kind.as_str() {
47 "native" => Ok(Box::new(NativeRuntime::new())),
48 "docker" => Ok(Box::new(DockerRuntime::new(config.docker.clone()))),
49 other if other.trim().is_empty() => {
50 anyhow::bail!("runtime.kind cannot be empty. Supported values: native, docker")
51 }
52 other => anyhow::bail!("Unknown runtime kind '{other}'. Supported values: native, docker"),
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn factory_native() {
62 let cfg = RuntimeConfig {
63 kind: "native".into(),
64 ..RuntimeConfig::default()
65 };
66 let rt = create_runtime(&cfg).unwrap();
67 assert_eq!(rt.name(), "native");
68 assert!(rt.has_shell_access());
69 }
70
71 #[test]
72 fn factory_docker() {
73 let cfg = RuntimeConfig {
74 kind: "docker".into(),
75 ..RuntimeConfig::default()
76 };
77 let rt = create_runtime(&cfg).unwrap();
78 assert_eq!(rt.name(), "docker");
79 assert!(rt.has_shell_access());
80 }
81
82 #[test]
83 fn factory_unknown_errors() {
84 let cfg = RuntimeConfig {
85 kind: "wasm-edge-unknown".into(),
86 ..RuntimeConfig::default()
87 };
88 match create_runtime(&cfg) {
89 Err(err) => assert!(err.to_string().contains("Unknown runtime kind")),
90 Ok(_) => panic!("unknown runtime should error"),
91 }
92 }
93
94 #[test]
95 fn factory_empty_errors() {
96 let cfg = RuntimeConfig {
97 kind: String::new(),
98 ..RuntimeConfig::default()
99 };
100 match create_runtime(&cfg) {
101 Err(err) => assert!(err.to_string().contains("cannot be empty")),
102 Ok(_) => panic!("empty runtime should error"),
103 }
104 }
105}