sdk: readable clients (no Empty wrapper, no unused error module), documented examples with tests

This commit is contained in:
2026-10-23 01:05:19 +01:00
parent edc2d1a63b
commit 0516158883
15 changed files with 426 additions and 81 deletions
+44
View File
@@ -2,6 +2,7 @@
//! Start `secrets.serve` as a detached boot service. Its memory lasts until process exit.
use sausage_plugin::{Ctx, Result, listen, rpc, schema};
use std::{cell::RefCell, collections::BTreeMap, rc::Rc};
/// The service entry point publishes one process-local vault.
struct Secrets;
#[rpc(endpoints(vault=Vault))]
impl Secrets {
@@ -10,8 +11,10 @@ impl Secrets {
listen("/run/secrets", Rc::new(Vault::default())).await
}
}
/// The endpoint owns secrets in memory, not on disk.
#[derive(Default)]
struct Vault {
/// Named values disappear when this process ends.
entries: RefCell<BTreeMap<String, String>>,
}
/// The name and value of a secret.
@@ -41,6 +44,47 @@ impl Vault {
Ok(self.entries.borrow().get(&p.name).cloned())
}
}
/// Start the SDK transport for the vault service.
fn main() {
sausage_plugin::run(Secrets)
}
/// Tests verify absent keys and process-local storage.
#[cfg(test)]
mod tests {
use super::*;
/// Missing names return null instead of an RPC error.
#[test]
fn absent_secret() {
assert_eq!(
Vault::default()
.get(GetParams {
name: "missing".into()
})
.unwrap(),
None
);
}
/// Store a value and retrieve it through the same process-local vault.
#[sausage_plugin::test]
async fn stores_secret() {
let vault = Vault::default();
vault
.put(
&Ctx::default(),
PutParams {
name: "token".into(),
value: "example".into(),
},
)
.unwrap();
assert_eq!(
vault
.get(GetParams {
name: "token".into()
})
.unwrap()
.as_deref(),
Some("example")
);
}
}