clawft_kernel/workload_runtime/
seed_client.rs1use std::time::Duration;
6
7use serde_json::Value;
8
9use super::seed::SeedApiRuntime;
10use super::seed_http::Method;
11use super::seed_types::{API_TIMEOUT, InstalledCog, backend};
12use super::types::RuntimeError;
13use crate::workload_pkg::manifest::valid_cog_id;
14
15fn cog_path(id: &str, op: &str) -> Result<String, RuntimeError> {
16 if !valid_cog_id(id) {
17 return Err(RuntimeError::InvalidConfig(format!("bad cog id {id:?}")));
18 }
19 Ok(format!("/api/v1/apps/{id}/{op}"))
20}
21
22impl SeedApiRuntime {
23 pub(super) async fn api(
25 &self,
26 method: Method,
27 path: &str,
28 body: Option<&Value>,
29 timeout: Duration,
30 ) -> Result<Value, RuntimeError> {
31 let token = self.creds.get(&self.cfg.node_id)?;
32 let (status, v) = self
33 .transport
34 .request(method, path, body, &token, timeout)
35 .await?;
36 if !(200..300).contains(&status) {
37 return Err(backend(path, status, &v));
38 }
39 Ok(v)
40 }
41
42 pub async fn installed(&self) -> Result<Vec<InstalledCog>, RuntimeError> {
44 let v = self
45 .api(Method::Get, "/api/v1/apps", None, API_TIMEOUT)
46 .await?;
47 let list = v
48 .get("installed")
49 .and_then(Value::as_array)
50 .ok_or_else(|| RuntimeError::Backend("seed /api/v1/apps: no installed list".into()))?;
51 Ok(list
52 .iter()
53 .filter_map(|a| {
54 Some(InstalledCog {
55 id: a.get("id")?.as_str()?.to_string(),
56 version: a
57 .get("version")
58 .and_then(Value::as_str)
59 .unwrap_or("")
60 .to_string(),
61 running: a.get("running").and_then(Value::as_bool).unwrap_or(false),
62 })
63 })
64 .collect())
65 }
66
67 pub async fn stop_cog(&self, id: &str) -> Result<(), RuntimeError> {
69 self.api(Method::Post, &cog_path(id, "stop")?, None, API_TIMEOUT)
70 .await
71 .map(|_| ())
72 }
73
74 pub async fn start_cog(&self, id: &str) -> Result<(), RuntimeError> {
76 self.api(Method::Post, &cog_path(id, "start")?, None, API_TIMEOUT)
77 .await
78 .map(|_| ())
79 }
80}