feat(config): make config writes atomic with rollback-safe replacement (#190)
* feat(runtime): add Docker runtime MVP and runtime-aware command builder * feat(security): add shell risk classification, approval gates, and action throttling * feat(gateway): add per-endpoint rate limiting and webhook idempotency * feat(config): make config writes atomic with rollback-safe replacement --------- Co-authored-by: chumyin <chumyin@users.noreply.github.com>
This commit is contained in:
parent
f1e3b1166d
commit
b0e1e32819
11 changed files with 1202 additions and 67 deletions
|
|
@ -1,6 +1,8 @@
|
|||
pub mod docker;
|
||||
pub mod native;
|
||||
pub mod traits;
|
||||
|
||||
pub use docker::DockerRuntime;
|
||||
pub use native::NativeRuntime;
|
||||
pub use traits::RuntimeAdapter;
|
||||
|
||||
|
|
@ -10,18 +12,14 @@ use crate::config::RuntimeConfig;
|
|||
pub fn create_runtime(config: &RuntimeConfig) -> anyhow::Result<Box<dyn RuntimeAdapter>> {
|
||||
match config.kind.as_str() {
|
||||
"native" => Ok(Box::new(NativeRuntime::new())),
|
||||
"docker" => anyhow::bail!(
|
||||
"runtime.kind='docker' is not implemented yet. Use runtime.kind='native' until container runtime support lands."
|
||||
),
|
||||
"docker" => Ok(Box::new(DockerRuntime::new(config.docker.clone()))),
|
||||
"cloudflare" => anyhow::bail!(
|
||||
"runtime.kind='cloudflare' is not implemented yet. Use runtime.kind='native' for now."
|
||||
),
|
||||
other if other.trim().is_empty() => anyhow::bail!(
|
||||
"runtime.kind cannot be empty. Supported values: native"
|
||||
),
|
||||
other => anyhow::bail!(
|
||||
"Unknown runtime kind '{other}'. Supported values: native"
|
||||
),
|
||||
other if other.trim().is_empty() => {
|
||||
anyhow::bail!("runtime.kind cannot be empty. Supported values: native, docker")
|
||||
}
|
||||
other => anyhow::bail!("Unknown runtime kind '{other}'. Supported values: native, docker"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,6 +31,7 @@ mod tests {
|
|||
fn factory_native() {
|
||||
let cfg = RuntimeConfig {
|
||||
kind: "native".into(),
|
||||
..RuntimeConfig::default()
|
||||
};
|
||||
let rt = create_runtime(&cfg).unwrap();
|
||||
assert_eq!(rt.name(), "native");
|
||||
|
|
@ -40,20 +39,21 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn factory_docker_errors() {
|
||||
fn factory_docker() {
|
||||
let cfg = RuntimeConfig {
|
||||
kind: "docker".into(),
|
||||
..RuntimeConfig::default()
|
||||
};
|
||||
match create_runtime(&cfg) {
|
||||
Err(err) => assert!(err.to_string().contains("not implemented")),
|
||||
Ok(_) => panic!("docker runtime should error"),
|
||||
}
|
||||
let rt = create_runtime(&cfg).unwrap();
|
||||
assert_eq!(rt.name(), "docker");
|
||||
assert!(rt.has_shell_access());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn factory_cloudflare_errors() {
|
||||
let cfg = RuntimeConfig {
|
||||
kind: "cloudflare".into(),
|
||||
..RuntimeConfig::default()
|
||||
};
|
||||
match create_runtime(&cfg) {
|
||||
Err(err) => assert!(err.to_string().contains("not implemented")),
|
||||
|
|
@ -65,6 +65,7 @@ mod tests {
|
|||
fn factory_unknown_errors() {
|
||||
let cfg = RuntimeConfig {
|
||||
kind: "wasm-edge-unknown".into(),
|
||||
..RuntimeConfig::default()
|
||||
};
|
||||
match create_runtime(&cfg) {
|
||||
Err(err) => assert!(err.to_string().contains("Unknown runtime kind")),
|
||||
|
|
@ -76,6 +77,7 @@ mod tests {
|
|||
fn factory_empty_errors() {
|
||||
let cfg = RuntimeConfig {
|
||||
kind: String::new(),
|
||||
..RuntimeConfig::default()
|
||||
};
|
||||
match create_runtime(&cfg) {
|
||||
Err(err) => assert!(err.to_string().contains("cannot be empty")),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue