Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ e7fcdb1a8f1e48c564717f1ccd0fa654d182aa73

# Move the Query API out of client.rs into client/query.rs (#1173)
8db8f19a0b69ff505c33188414efb85dc50dfd0e

# Split client/organizations.rs into byoc, invitations, members and rbac (#1173)
9e20dd888a937f5f0b610b22a71aef4ff70b9357
4 changes: 4 additions & 0 deletions crates/clickhouse-cloud-api/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ use crate::error::Error;
mod activity;
mod api_keys;
mod backups;
mod byoc;
mod clickpipes;
mod clickstack;
mod invitations;
mod members;
mod organizations;
mod postgres;
mod query;
mod query_api_endpoints;
mod rbac;
mod saved_queries;
mod services;
mod udfs;
Expand Down
212 changes: 212 additions & 0 deletions crates/clickhouse-cloud-api/src/client/byoc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
use super::Client;
use crate::error::Error;
use crate::models::*;

impl Client {
/// Create BYOC Infrastructure
pub async fn organization_byoc_infrastructure_create(
&self,
organization_id: &str,
body: &ByocInfrastructurePostRequest,
) -> Result<ApiResponse<ByocConfig>, Error> {
let path = format!("/v1/organizations/{organization_id}/byocInfrastructure");
let mut req = self.request(reqwest::Method::POST, &path);
req = req.json(body);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Validate BYOC infrastructure prerequisites
///
/// Preflight-checks the cloud account's permissions without creating infrastructure.
pub async fn organization_byoc_infrastructure_validate(
&self,
organization_id: &str,
body: &ByocInfrastructureValidatePostRequest,
) -> Result<ApiResponse<ByocInfrastructureValidation>, Error> {
let path = format!("/v1/organizations/{organization_id}/byocInfrastructure/validate");
let mut req = self.request(reqwest::Method::POST, &path);
req = req.json(body);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Get BYOC infrastructure details
pub async fn organization_byoc_infrastructure_get(
&self,
organization_id: &str,
byoc_infrastructure_id: &str,
) -> Result<ApiResponse<ByocInfrastructureDetails>, Error> {
let path = format!(
"/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}"
);
let req = self.request(reqwest::Method::GET, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Get BYOC infrastructure provisioning progress
pub async fn organization_byoc_infrastructure_progress_get(
&self,
organization_id: &str,
byoc_infrastructure_id: &str,
) -> Result<ApiResponse<ByocInfrastructureProgress>, Error> {
let path = format!(
"/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}/progress"
);
let req = self.request(reqwest::Method::GET, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Get BYOC infrastructure private endpoint configuration
///
/// For BYOC organizations this replaces the deprecated organization-level
/// `organization_private_endpoint_config_get_list`.
pub async fn organization_byoc_infrastructure_private_endpoint_config_get(
&self,
organization_id: &str,
byoc_infrastructure_id: &str,
) -> Result<ApiResponse<ByocInfrastructurePrivateEndpointConfig>, Error> {
let path = format!(
"/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}/privateEndpointConfig"
);
let req = self.request(reqwest::Method::GET, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Get BYOC infrastructure tags
///
/// Tags are replaced as a whole through `organization_byoc_infrastructure_update`.
pub async fn organization_byoc_infrastructure_tags_get(
&self,
organization_id: &str,
byoc_infrastructure_id: &str,
) -> Result<ApiResponse<ByocInfrastructureTagsResponse>, Error> {
let path = format!(
"/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}/tags"
);
let req = self.request(reqwest::Method::GET, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Remove a BYOC infrastructure
pub async fn organization_byoc_infrastructure_delete(
&self,
organization_id: &str,
byoc_infrastructure_id: &str,
) -> Result<ApiResponse<serde_json::Value>, Error> {
let path = format!(
"/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}"
);
let req = self.request(reqwest::Method::DELETE, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Update BYOC Infrastructure
pub async fn organization_byoc_infrastructure_update(
&self,
organization_id: &str,
byoc_infrastructure_id: &str,
body: &ByocInfrastructurePatchRequest,
) -> Result<ApiResponse<ByocConfig>, Error> {
let path = format!(
"/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}"
);
let mut req = self.request(reqwest::Method::PATCH, &path);
req = req.json(body);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}
}
97 changes: 97 additions & 0 deletions crates/clickhouse-cloud-api/src/client/invitations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use super::Client;
use crate::error::Error;
use crate::models::*;

impl Client {
/// List all invitations
pub async fn invitation_get_list(
&self,
organization_id: &str,
) -> Result<ApiResponse<Vec<Invitation>>, Error> {
let path = format!("/v1/organizations/{organization_id}/invitations");
let req = self.request(reqwest::Method::GET, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Create an invitation
pub async fn invitation_create(
&self,
organization_id: &str,
body: &InvitationPostRequest,
) -> Result<ApiResponse<Invitation>, Error> {
let path = format!("/v1/organizations/{organization_id}/invitations");
let mut req = self.request(reqwest::Method::POST, &path);
req = req.json(body);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Get invitation details
pub async fn invitation_get(
&self,
organization_id: &str,
invitation_id: &str,
) -> Result<ApiResponse<Invitation>, Error> {
let path = format!("/v1/organizations/{organization_id}/invitations/{invitation_id}");
let req = self.request(reqwest::Method::GET, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}

/// Delete organization invitation
pub async fn invitation_delete(
&self,
organization_id: &str,
invitation_id: &str,
) -> Result<ApiResponse<serde_json::Value>, Error> {
let path = format!("/v1/organizations/{organization_id}/invitations/{invitation_id}");
let req = self.request(reqwest::Method::DELETE, &path);
let resp = req.send().await?;
let status = resp.status();
let body_text = resp.text().await?;
if !status.is_success() {
return Err(Error::Api {
status: status.as_u16(),
message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
.ok()
.and_then(|r| r.error)
.unwrap_or(body_text.clone()),
});
}
Ok(serde_json::from_str(&body_text)?)
}
}
Loading
Loading