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> = self
24 .get(&ApiPaths::tenant_status(tenant_id.as_str()))
25 .await?;
26 Ok(response.data)
27 }
28
29 pub async fn get_registry_token(&self, tenant_id: &TenantId) -> CloudResult<RegistryToken> {
30 let response: ApiResponse<RegistryToken> = self
31 .get(&ApiPaths::tenant_registry_token(tenant_id.as_str()))
32 .await?;
33 Ok(response.data)
34 }
35
36 pub async fn deploy(&self, tenant_id: &TenantId, image: &str) -> CloudResult<DeployResponse> {
37 let request = DeployRequest {
38 image: image.to_string(),
39 };
40 let response: ApiResponse<DeployResponse> = self
41 .post(&ApiPaths::tenant_deploy(tenant_id.as_str()), &request)
42 .await?;
43 Ok(response.data)
44 }
45
46 pub async fn fetch_secrets(&self, secrets_url: &str) -> CloudResult<TenantSecrets> {
47 let path = secrets_url
48 .strip_prefix(&self.api_url)
49 .unwrap_or(secrets_url);
50 self.get(path).await
51 }
52
53 pub async fn delete_tenant(&self, tenant_id: &TenantId) -> CloudResult<()> {
54 self.delete(&ApiPaths::tenant(tenant_id.as_str())).await
55 }
56
57 pub async fn restart_tenant(&self, tenant_id: &TenantId) -> CloudResult<StatusResponse> {
58 self.post_empty(&ApiPaths::tenant_restart(tenant_id.as_str()))
59 .await
60 }
61
62 pub async fn retry_provision(&self, tenant_id: &TenantId) -> CloudResult<StatusResponse> {
63 self.post_empty(&ApiPaths::tenant_retry_provision(tenant_id.as_str()))
64 .await
65 }
66
67 pub async fn set_secrets(
68 &self,
69 tenant_id: &TenantId,
70 secrets: std::collections::HashMap<String, String>,
71 ) -> CloudResult<Vec<String>> {
72 let keys: Vec<String> = secrets.keys().cloned().collect();
73 let request = SetSecretsRequest { secrets };
74 self.put_no_content(&ApiPaths::tenant_secrets(tenant_id.as_str()), &request)
75 .await?;
76 Ok(keys)
77 }
78
79 pub async fn unset_secret(&self, tenant_id: &TenantId, key: &str) -> CloudResult<()> {
80 let path = format!("{}/{}", ApiPaths::tenant_secrets(tenant_id.as_str()), key);
81 self.delete(&path).await
82 }
83
84 pub async fn set_external_db_access(
85 &self,
86 tenant_id: &TenantId,
87 enabled: bool,
88 ) -> CloudResult<ExternalDbAccessResponse> {
89 let request = SetExternalDbAccessRequest { enabled };
90 let response: ApiResponse<ExternalDbAccessResponse> = self
91 .put(
92 &ApiPaths::tenant_external_db_access(tenant_id.as_str()),
93 &request,
94 )
95 .await?;
96 Ok(response.data)
97 }
98
99 pub async fn rotate_credentials(
100 &self,
101 tenant_id: &TenantId,
102 ) -> CloudResult<RotateCredentialsResponse> {
103 self.post_empty(&ApiPaths::tenant_rotate_credentials(tenant_id.as_str()))
104 .await
105 }
106
107 pub async fn rotate_sync_token(
108 &self,
109 tenant_id: &TenantId,
110 ) -> CloudResult<RotateSyncTokenResponse> {
111 let response: ApiResponse<RotateSyncTokenResponse> = self
112 .post_empty(&ApiPaths::tenant_rotate_sync_token(tenant_id.as_str()))
113 .await?;
114 Ok(response.data)
115 }
116
117 pub async fn list_secrets(&self, tenant_id: &TenantId) -> CloudResult<ListSecretsResponse> {
118 self.get(&ApiPaths::tenant_secrets(tenant_id.as_str()))
119 .await
120 }
121
122 pub async fn set_custom_domain(
123 &self,
124 tenant_id: &TenantId,
125 domain: &str,
126 ) -> CloudResult<CustomDomainResponse> {
127 let request = SetCustomDomainRequest {
128 domain: domain.to_string(),
129 };
130 let response: ApiResponse<CustomDomainResponse> = self
131 .post(
132 &ApiPaths::tenant_custom_domain(tenant_id.as_str()),
133 &request,
134 )
135 .await?;
136 Ok(response.data)
137 }
138
139 pub async fn get_custom_domain(
140 &self,
141 tenant_id: &TenantId,
142 ) -> CloudResult<CustomDomainResponse> {
143 let response: ApiResponse<CustomDomainResponse> = self
144 .get(&ApiPaths::tenant_custom_domain(tenant_id.as_str()))
145 .await?;
146 Ok(response.data)
147 }
148
149 pub async fn delete_custom_domain(&self, tenant_id: &TenantId) -> CloudResult<()> {
150 self.delete(&ApiPaths::tenant_custom_domain(tenant_id.as_str()))
151 .await
152 }
153
154 pub async fn cancel_subscription(&self, tenant_id: &TenantId) -> CloudResult<()> {
155 self.post_empty(&ApiPaths::tenant_subscription_cancel(tenant_id.as_str()))
156 .await
157 }
158}