systemprompt_cloud/api_client/
tenant_api.rs1use anyhow::Result;
2use serde::Serialize;
3use systemprompt_models::modules::ApiPaths;
4
5use super::types::{
6 ApiResponse, CustomDomainResponse, DeployResponse, ExternalDbAccessResponse,
7 ListSecretsResponse, RegistryToken, RotateCredentialsResponse, RotateSyncTokenResponse,
8 SetCustomDomainRequest, SetExternalDbAccessRequest, SetSecretsRequest, StatusResponse,
9 TenantSecrets, TenantStatus,
10};
11use super::CloudApiClient;
12
13#[derive(Serialize)]
14struct DeployRequest {
15 image: String,
16}
17
18impl CloudApiClient {
19 pub async fn get_tenant_status(&self, tenant_id: &str) -> Result<TenantStatus> {
20 let response: ApiResponse<TenantStatus> =
21 self.get(&ApiPaths::tenant_status(tenant_id)).await?;
22 Ok(response.data)
23 }
24
25 pub async fn get_registry_token(&self, tenant_id: &str) -> Result<RegistryToken> {
26 let response: ApiResponse<RegistryToken> = self
27 .get(&ApiPaths::tenant_registry_token(tenant_id))
28 .await?;
29 Ok(response.data)
30 }
31
32 pub async fn deploy(&self, tenant_id: &str, image: &str) -> Result<DeployResponse> {
33 let request = DeployRequest {
34 image: image.to_string(),
35 };
36 let response: ApiResponse<DeployResponse> = self
37 .post(&ApiPaths::tenant_deploy(tenant_id), &request)
38 .await?;
39 Ok(response.data)
40 }
41
42 pub async fn fetch_secrets(&self, secrets_url: &str) -> Result<TenantSecrets> {
43 let path = secrets_url
44 .strip_prefix(&self.api_url)
45 .unwrap_or(secrets_url);
46 self.get(path).await
47 }
48
49 pub async fn delete_tenant(&self, tenant_id: &str) -> Result<()> {
50 self.delete(&ApiPaths::tenant(tenant_id)).await
51 }
52
53 pub async fn restart_tenant(&self, tenant_id: &str) -> Result<StatusResponse> {
54 self.post_empty(&ApiPaths::tenant_restart(tenant_id)).await
55 }
56
57 pub async fn retry_provision(&self, tenant_id: &str) -> Result<StatusResponse> {
58 self.post_empty(&ApiPaths::tenant_retry_provision(tenant_id))
59 .await
60 }
61
62 pub async fn set_secrets(
63 &self,
64 tenant_id: &str,
65 secrets: std::collections::HashMap<String, String>,
66 ) -> Result<Vec<String>> {
67 let keys: Vec<String> = secrets.keys().cloned().collect();
68 let request = SetSecretsRequest { secrets };
69 self.put_no_content(&ApiPaths::tenant_secrets(tenant_id), &request)
70 .await?;
71 Ok(keys)
72 }
73
74 pub async fn unset_secret(&self, tenant_id: &str, key: &str) -> Result<()> {
75 let path = format!("{}/{}", ApiPaths::tenant_secrets(tenant_id), key);
76 self.delete(&path).await
77 }
78
79 pub async fn set_external_db_access(
80 &self,
81 tenant_id: &str,
82 enabled: bool,
83 ) -> Result<ExternalDbAccessResponse> {
84 let request = SetExternalDbAccessRequest { enabled };
85 let response: ApiResponse<ExternalDbAccessResponse> = self
86 .put(&ApiPaths::tenant_external_db_access(tenant_id), &request)
87 .await?;
88 Ok(response.data)
89 }
90
91 pub async fn rotate_credentials(&self, tenant_id: &str) -> Result<RotateCredentialsResponse> {
92 self.post_empty(&ApiPaths::tenant_rotate_credentials(tenant_id))
93 .await
94 }
95
96 pub async fn rotate_sync_token(&self, tenant_id: &str) -> Result<RotateSyncTokenResponse> {
97 let response: ApiResponse<RotateSyncTokenResponse> = self
98 .post_empty(&ApiPaths::tenant_rotate_sync_token(tenant_id))
99 .await?;
100 Ok(response.data)
101 }
102
103 pub async fn list_secrets(&self, tenant_id: &str) -> Result<ListSecretsResponse> {
104 self.get(&ApiPaths::tenant_secrets(tenant_id)).await
105 }
106
107 pub async fn set_custom_domain(
108 &self,
109 tenant_id: &str,
110 domain: &str,
111 ) -> Result<CustomDomainResponse> {
112 let request = SetCustomDomainRequest {
113 domain: domain.to_string(),
114 };
115 let response: ApiResponse<CustomDomainResponse> = self
116 .post(&ApiPaths::tenant_custom_domain(tenant_id), &request)
117 .await?;
118 Ok(response.data)
119 }
120
121 pub async fn get_custom_domain(&self, tenant_id: &str) -> Result<CustomDomainResponse> {
122 let response: ApiResponse<CustomDomainResponse> =
123 self.get(&ApiPaths::tenant_custom_domain(tenant_id)).await?;
124 Ok(response.data)
125 }
126
127 pub async fn delete_custom_domain(&self, tenant_id: &str) -> Result<()> {
128 self.delete(&ApiPaths::tenant_custom_domain(tenant_id))
129 .await
130 }
131
132 pub async fn cancel_subscription(&self, tenant_id: &str) -> Result<()> {
133 self.post_empty(&ApiPaths::tenant_subscription_cancel(tenant_id))
134 .await
135 }
136}