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