1use crate::error::Error;
6use crate::models::*;
7
8#[derive(Debug, Clone)]
10enum Auth {
11 Basic { key_id: String, key_secret: String },
12 Bearer { token: String },
13}
14
15enum QueryAuth<'a> {
18 Basic {
19 key_id: &'a str,
20 key_secret: &'a str,
21 },
22 Bearer {
23 token: &'a str,
24 },
25}
26
27#[derive(Debug, Clone)]
31pub struct Client {
32 http: reqwest::Client,
33 base_url: String,
34 auth: Auth,
35 query_host: Option<String>,
37}
38
39fn derive_query_host(base_url: &str) -> Option<String> {
52 let parsed = url::Url::parse(base_url).ok()?;
53 let rest = parsed.host_str()?.strip_prefix("api.")?;
54 let rest = rest.strip_prefix("control-plane.").unwrap_or(rest);
55 let port = parsed
56 .port()
57 .map(|p| format!(":{p}"))
58 .unwrap_or_default();
59 Some(format!("{}://queries.{}{}", parsed.scheme(), rest, port))
60}
61
62impl Client {
63 pub fn new(key_id: impl Into<String>, key_secret: impl Into<String>) -> Self {
65 Self::with_base_url("https://api.clickhouse.cloud", key_id, key_secret)
66 }
67
68 pub fn with_base_url(
70 base_url: impl Into<String>,
71 key_id: impl Into<String>,
72 key_secret: impl Into<String>,
73 ) -> Self {
74 Self {
75 http: reqwest::Client::new(),
76 base_url: base_url.into().trim_end_matches('/').to_string(),
77 auth: Auth::Basic {
78 key_id: key_id.into(),
79 key_secret: key_secret.into(),
80 },
81 query_host: None,
82 }
83 }
84
85 pub fn with_bearer_token(
87 base_url: impl Into<String>,
88 token: impl Into<String>,
89 ) -> Self {
90 Self {
91 http: reqwest::Client::new(),
92 base_url: base_url.into().trim_end_matches('/').to_string(),
93 auth: Auth::Bearer {
94 token: token.into(),
95 },
96 query_host: None,
97 }
98 }
99
100 pub fn with_http_client(
105 http: reqwest::Client,
106 base_url: impl Into<String>,
107 key_id: impl Into<String>,
108 key_secret: impl Into<String>,
109 ) -> Self {
110 Self {
111 http,
112 base_url: base_url.into().trim_end_matches('/').to_string(),
113 auth: Auth::Basic {
114 key_id: key_id.into(),
115 key_secret: key_secret.into(),
116 },
117 query_host: None,
118 }
119 }
120
121 pub fn with_http_client_bearer(
126 http: reqwest::Client,
127 base_url: impl Into<String>,
128 token: impl Into<String>,
129 ) -> Self {
130 Self {
131 http,
132 base_url: base_url.into().trim_end_matches('/').to_string(),
133 auth: Auth::Bearer {
134 token: token.into(),
135 },
136 query_host: None,
137 }
138 }
139
140 pub fn set_bearer_token(&mut self, token: impl Into<String>) -> Result<(), Error> {
145 match &mut self.auth {
146 Auth::Bearer { token: t } => {
147 *t = token.into();
148 Ok(())
149 }
150 Auth::Basic { .. } => Err(Error::AuthMismatch(
151 "set_bearer_token called on a Basic-auth client".into(),
152 )),
153 }
154 }
155
156 pub fn with_query_host(mut self, host: impl Into<String>) -> Self {
164 self.query_host = Some(host.into().trim_end_matches('/').to_string());
165 self
166 }
167
168 fn resolved_query_host(&self) -> String {
171 if let Some(host) = &self.query_host {
172 return host.clone();
173 }
174 if let Ok(host) = std::env::var("CLICKHOUSE_CLOUD_QUERY_HOST") {
175 return host;
176 }
177 derive_query_host(&self.base_url)
178 .unwrap_or_else(|| "https://queries.clickhouse.cloud".to_string())
179 }
180
181 fn request(&self, method: reqwest::Method, path: &str) -> reqwest::RequestBuilder {
182 let builder = self
183 .http
184 .request(method, format!("{}{}", self.base_url, path));
185 match &self.auth {
186 Auth::Basic { key_id, key_secret } => builder.basic_auth(key_id, Some(key_secret)),
187 Auth::Bearer { token } => builder.bearer_auth(token),
188 }
189 }
190
191 #[allow(clippy::too_many_arguments)]
206 pub async fn run_query(
207 &self,
208 service_id: &str,
209 key_id: &str,
210 key_secret: &str,
211 sql: &str,
212 database: Option<&str>,
213 format: &str,
214 wake_service: bool,
215 ) -> Result<reqwest::Response, Error> {
216 self.run_query_with(
217 QueryAuth::Basic { key_id, key_secret },
218 service_id,
219 sql,
220 database,
221 format,
222 wake_service,
223 )
224 .await
225 }
226
227 pub async fn run_query_bearer(
240 &self,
241 service_id: &str,
242 sql: &str,
243 database: Option<&str>,
244 format: &str,
245 wake_service: bool,
246 ) -> Result<reqwest::Response, Error> {
247 let token = match &self.auth {
248 Auth::Bearer { token } => token,
249 Auth::Basic { .. } => {
250 return Err(Error::AuthMismatch(
251 "run_query_bearer called on a Basic-auth client".into(),
252 ));
253 }
254 };
255 self.run_query_with(
256 QueryAuth::Bearer { token },
257 service_id,
258 sql,
259 database,
260 format,
261 wake_service,
262 )
263 .await
264 }
265
266 async fn run_query_with(
267 &self,
268 auth: QueryAuth<'_>,
269 service_id: &str,
270 sql: &str,
271 database: Option<&str>,
272 format: &str,
273 wake_service: bool,
274 ) -> Result<reqwest::Response, Error> {
275 #[derive(serde::Serialize)]
276 #[serde(rename_all = "camelCase")]
277 struct RunQueryBody<'a> {
278 run_id: String,
279 sql: &'a str,
280 #[serde(skip_serializing_if = "Option::is_none")]
281 database: Option<&'a str>,
282 }
283
284 let url = format!(
285 "{}/service/{}/run",
286 self.resolved_query_host().trim_end_matches('/'),
287 service_id,
288 );
289
290 let body = RunQueryBody {
291 run_id: uuid::Uuid::new_v4().to_string(),
292 sql,
293 database,
294 };
295
296 let request = self
297 .http
298 .post(url)
299 .query(&[("format", format)])
300 .header("content-type", "text/plain;charset=UTF-8")
301 .header("x-service-type", "clickhouse");
302 let request = if wake_service {
306 request.header("wake-service", "true")
307 } else {
308 request
309 };
310 let request = match auth {
314 QueryAuth::Basic { key_id, key_secret } => request
315 .basic_auth(key_id, Some(key_secret))
316 .header("auth-provider", "custom"),
317 QueryAuth::Bearer { token } => request.bearer_auth(token),
318 };
319
320 let response = request.json(&body).send().await?;
321
322 let status = response.status();
323 if status.as_u16() == 206 {
328 let body_text = response.text().await.unwrap_or_default();
329 #[derive(serde::Deserialize)]
330 struct StateBody {
331 data: Option<String>,
332 }
333 let data = serde_json::from_str::<StateBody>(&body_text)
334 .ok()
335 .and_then(|b| b.data);
336 return Err(match data.as_deref() {
337 Some("Confirm wake service") => Error::ServiceIdle,
338 Some("Service is stopped") => Error::ServiceStopped,
339 _ => Error::Api {
340 status: 206,
341 message: body_text,
342 },
343 });
344 }
345 if !status.is_success() {
346 let body_text = response.text().await.unwrap_or_default();
347 return Err(Error::Api {
348 status: status.as_u16(),
349 message: if body_text.is_empty() {
350 format!("Query API returned {status}")
351 } else {
352 body_text
353 },
354 });
355 }
356
357 Ok(response)
358 }
359
360 pub async fn organization_get_list(
362 &self,
363 ) -> Result<ApiResponse<Vec<Organization>>, Error> {
364 let path = "/v1/organizations".to_string();
365 let req = self.request(reqwest::Method::GET, &path);
366 let resp = req.send().await?;
367 let status = resp.status();
368 let body_text = resp.text().await?;
369 if !status.is_success() {
370 return Err(Error::Api {
371 status: status.as_u16(),
372 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
373 .ok()
374 .and_then(|r| r.error)
375 .unwrap_or(body_text.clone()),
376 });
377 }
378 Ok(serde_json::from_str(&body_text)?)
379 }
380
381 pub async fn organization_get(
383 &self,
384 organization_id: &str,
385 ) -> Result<ApiResponse<Organization>, Error> {
386 let path = format!("/v1/organizations/{organization_id}");
387 let req = self.request(reqwest::Method::GET, &path);
388 let resp = req.send().await?;
389 let status = resp.status();
390 let body_text = resp.text().await?;
391 if !status.is_success() {
392 return Err(Error::Api {
393 status: status.as_u16(),
394 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
395 .ok()
396 .and_then(|r| r.error)
397 .unwrap_or(body_text.clone()),
398 });
399 }
400 Ok(serde_json::from_str(&body_text)?)
401 }
402
403 pub async fn organization_update(
405 &self,
406 organization_id: &str,
407 body: &OrganizationPatchRequest,
408 ) -> Result<ApiResponse<Organization>, Error> {
409 let path = format!("/v1/organizations/{organization_id}");
410 let mut req = self.request(reqwest::Method::PATCH, &path);
411 req = req.json(body);
412 let resp = req.send().await?;
413 let status = resp.status();
414 let body_text = resp.text().await?;
415 if !status.is_success() {
416 return Err(Error::Api {
417 status: status.as_u16(),
418 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
419 .ok()
420 .and_then(|r| r.error)
421 .unwrap_or(body_text.clone()),
422 });
423 }
424 Ok(serde_json::from_str(&body_text)?)
425 }
426
427 pub async fn activity_get_list(
429 &self,
430 organization_id: &str,
431 from_date: Option<&str>,
432 to_date: Option<&str>,
433 ) -> Result<ApiResponse<Vec<Activity>>, Error> {
434 let path = format!("/v1/organizations/{organization_id}/activities");
435 let mut req = self.request(reqwest::Method::GET, &path);
436 if let Some(v) = from_date {
437 req = req.query(&[("from_date", v)]);
438 }
439 if let Some(v) = to_date {
440 req = req.query(&[("to_date", v)]);
441 }
442 let resp = req.send().await?;
443 let status = resp.status();
444 let body_text = resp.text().await?;
445 if !status.is_success() {
446 return Err(Error::Api {
447 status: status.as_u16(),
448 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
449 .ok()
450 .and_then(|r| r.error)
451 .unwrap_or(body_text.clone()),
452 });
453 }
454 Ok(serde_json::from_str(&body_text)?)
455 }
456
457 pub async fn activity_get(
459 &self,
460 organization_id: &str,
461 activity_id: &str,
462 ) -> Result<ApiResponse<Activity>, Error> {
463 let path = format!("/v1/organizations/{organization_id}/activities/{activity_id}");
464 let req = self.request(reqwest::Method::GET, &path);
465 let resp = req.send().await?;
466 let status = resp.status();
467 let body_text = resp.text().await?;
468 if !status.is_success() {
469 return Err(Error::Api {
470 status: status.as_u16(),
471 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
472 .ok()
473 .and_then(|r| r.error)
474 .unwrap_or(body_text.clone()),
475 });
476 }
477 Ok(serde_json::from_str(&body_text)?)
478 }
479
480 pub async fn organization_byoc_infrastructure_create(
482 &self,
483 organization_id: &str,
484 body: &ByocInfrastructurePostRequest,
485 ) -> Result<ApiResponse<ByocConfig>, Error> {
486 let path = format!("/v1/organizations/{organization_id}/byocInfrastructure");
487 let mut req = self.request(reqwest::Method::POST, &path);
488 req = req.json(body);
489 let resp = req.send().await?;
490 let status = resp.status();
491 let body_text = resp.text().await?;
492 if !status.is_success() {
493 return Err(Error::Api {
494 status: status.as_u16(),
495 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
496 .ok()
497 .and_then(|r| r.error)
498 .unwrap_or(body_text.clone()),
499 });
500 }
501 Ok(serde_json::from_str(&body_text)?)
502 }
503
504 pub async fn organization_byoc_infrastructure_delete(
506 &self,
507 organization_id: &str,
508 byoc_infrastructure_id: &str,
509 ) -> Result<ApiResponse<serde_json::Value>, Error> {
510 let path = format!("/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}");
511 let req = self.request(reqwest::Method::DELETE, &path);
512 let resp = req.send().await?;
513 let status = resp.status();
514 let body_text = resp.text().await?;
515 if !status.is_success() {
516 return Err(Error::Api {
517 status: status.as_u16(),
518 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
519 .ok()
520 .and_then(|r| r.error)
521 .unwrap_or(body_text.clone()),
522 });
523 }
524 Ok(serde_json::from_str(&body_text)?)
525 }
526
527 pub async fn organization_byoc_infrastructure_update(
529 &self,
530 organization_id: &str,
531 byoc_infrastructure_id: &str,
532 body: &ByocInfrastructurePatchRequest,
533 ) -> Result<ApiResponse<ByocConfig>, Error> {
534 let path = format!("/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}");
535 let mut req = self.request(reqwest::Method::PATCH, &path);
536 req = req.json(body);
537 let resp = req.send().await?;
538 let status = resp.status();
539 let body_text = resp.text().await?;
540 if !status.is_success() {
541 return Err(Error::Api {
542 status: status.as_u16(),
543 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
544 .ok()
545 .and_then(|r| r.error)
546 .unwrap_or(body_text.clone()),
547 });
548 }
549 Ok(serde_json::from_str(&body_text)?)
550 }
551
552 pub async fn invitation_get_list(
554 &self,
555 organization_id: &str,
556 ) -> Result<ApiResponse<Vec<Invitation>>, Error> {
557 let path = format!("/v1/organizations/{organization_id}/invitations");
558 let req = self.request(reqwest::Method::GET, &path);
559 let resp = req.send().await?;
560 let status = resp.status();
561 let body_text = resp.text().await?;
562 if !status.is_success() {
563 return Err(Error::Api {
564 status: status.as_u16(),
565 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
566 .ok()
567 .and_then(|r| r.error)
568 .unwrap_or(body_text.clone()),
569 });
570 }
571 Ok(serde_json::from_str(&body_text)?)
572 }
573
574 pub async fn invitation_create(
576 &self,
577 organization_id: &str,
578 body: &InvitationPostRequest,
579 ) -> Result<ApiResponse<Invitation>, Error> {
580 let path = format!("/v1/organizations/{organization_id}/invitations");
581 let mut req = self.request(reqwest::Method::POST, &path);
582 req = req.json(body);
583 let resp = req.send().await?;
584 let status = resp.status();
585 let body_text = resp.text().await?;
586 if !status.is_success() {
587 return Err(Error::Api {
588 status: status.as_u16(),
589 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
590 .ok()
591 .and_then(|r| r.error)
592 .unwrap_or(body_text.clone()),
593 });
594 }
595 Ok(serde_json::from_str(&body_text)?)
596 }
597
598 pub async fn invitation_get(
600 &self,
601 organization_id: &str,
602 invitation_id: &str,
603 ) -> Result<ApiResponse<Invitation>, Error> {
604 let path = format!("/v1/organizations/{organization_id}/invitations/{invitation_id}");
605 let req = self.request(reqwest::Method::GET, &path);
606 let resp = req.send().await?;
607 let status = resp.status();
608 let body_text = resp.text().await?;
609 if !status.is_success() {
610 return Err(Error::Api {
611 status: status.as_u16(),
612 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
613 .ok()
614 .and_then(|r| r.error)
615 .unwrap_or(body_text.clone()),
616 });
617 }
618 Ok(serde_json::from_str(&body_text)?)
619 }
620
621 pub async fn invitation_delete(
623 &self,
624 organization_id: &str,
625 invitation_id: &str,
626 ) -> Result<ApiResponse<serde_json::Value>, Error> {
627 let path = format!("/v1/organizations/{organization_id}/invitations/{invitation_id}");
628 let req = self.request(reqwest::Method::DELETE, &path);
629 let resp = req.send().await?;
630 let status = resp.status();
631 let body_text = resp.text().await?;
632 if !status.is_success() {
633 return Err(Error::Api {
634 status: status.as_u16(),
635 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
636 .ok()
637 .and_then(|r| r.error)
638 .unwrap_or(body_text.clone()),
639 });
640 }
641 Ok(serde_json::from_str(&body_text)?)
642 }
643
644 pub async fn openapi_key_get_list(
646 &self,
647 organization_id: &str,
648 ) -> Result<ApiResponse<Vec<ApiKey>>, Error> {
649 let path = format!("/v1/organizations/{organization_id}/keys");
650 let req = self.request(reqwest::Method::GET, &path);
651 let resp = req.send().await?;
652 let status = resp.status();
653 let body_text = resp.text().await?;
654 if !status.is_success() {
655 return Err(Error::Api {
656 status: status.as_u16(),
657 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
658 .ok()
659 .and_then(|r| r.error)
660 .unwrap_or(body_text.clone()),
661 });
662 }
663 Ok(serde_json::from_str(&body_text)?)
664 }
665
666 pub async fn openapi_key_create(
668 &self,
669 organization_id: &str,
670 body: &ApiKeyPostRequest,
671 ) -> Result<ApiResponse<ApiKeyPostResponse>, Error> {
672 let path = format!("/v1/organizations/{organization_id}/keys");
673 let mut req = self.request(reqwest::Method::POST, &path);
674 req = req.json(body);
675 let resp = req.send().await?;
676 let status = resp.status();
677 let body_text = resp.text().await?;
678 if !status.is_success() {
679 return Err(Error::Api {
680 status: status.as_u16(),
681 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
682 .ok()
683 .and_then(|r| r.error)
684 .unwrap_or(body_text.clone()),
685 });
686 }
687 Ok(serde_json::from_str(&body_text)?)
688 }
689
690 pub async fn openapi_key_get(
692 &self,
693 organization_id: &str,
694 key_id: &str,
695 ) -> Result<ApiResponse<ApiKey>, Error> {
696 let path = format!("/v1/organizations/{organization_id}/keys/{key_id}");
697 let req = self.request(reqwest::Method::GET, &path);
698 let resp = req.send().await?;
699 let status = resp.status();
700 let body_text = resp.text().await?;
701 if !status.is_success() {
702 return Err(Error::Api {
703 status: status.as_u16(),
704 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
705 .ok()
706 .and_then(|r| r.error)
707 .unwrap_or(body_text.clone()),
708 });
709 }
710 Ok(serde_json::from_str(&body_text)?)
711 }
712
713 pub async fn openapi_key_update(
715 &self,
716 organization_id: &str,
717 key_id: &str,
718 body: &ApiKeyPatchRequest,
719 ) -> Result<ApiResponse<ApiKey>, Error> {
720 let path = format!("/v1/organizations/{organization_id}/keys/{key_id}");
721 let mut req = self.request(reqwest::Method::PATCH, &path);
722 req = req.json(body);
723 let resp = req.send().await?;
724 let status = resp.status();
725 let body_text = resp.text().await?;
726 if !status.is_success() {
727 return Err(Error::Api {
728 status: status.as_u16(),
729 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
730 .ok()
731 .and_then(|r| r.error)
732 .unwrap_or(body_text.clone()),
733 });
734 }
735 Ok(serde_json::from_str(&body_text)?)
736 }
737
738 pub async fn openapi_key_delete(
740 &self,
741 organization_id: &str,
742 key_id: &str,
743 ) -> Result<ApiResponse<serde_json::Value>, Error> {
744 let path = format!("/v1/organizations/{organization_id}/keys/{key_id}");
745 let req = self.request(reqwest::Method::DELETE, &path);
746 let resp = req.send().await?;
747 let status = resp.status();
748 let body_text = resp.text().await?;
749 if !status.is_success() {
750 return Err(Error::Api {
751 status: status.as_u16(),
752 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
753 .ok()
754 .and_then(|r| r.error)
755 .unwrap_or(body_text.clone()),
756 });
757 }
758 Ok(serde_json::from_str(&body_text)?)
759 }
760
761 pub async fn member_get_list(
763 &self,
764 organization_id: &str,
765 ) -> Result<ApiResponse<Vec<Member>>, Error> {
766 let path = format!("/v1/organizations/{organization_id}/members");
767 let req = self.request(reqwest::Method::GET, &path);
768 let resp = req.send().await?;
769 let status = resp.status();
770 let body_text = resp.text().await?;
771 if !status.is_success() {
772 return Err(Error::Api {
773 status: status.as_u16(),
774 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
775 .ok()
776 .and_then(|r| r.error)
777 .unwrap_or(body_text.clone()),
778 });
779 }
780 Ok(serde_json::from_str(&body_text)?)
781 }
782
783 pub async fn member_get(
785 &self,
786 organization_id: &str,
787 user_id: &str,
788 ) -> Result<ApiResponse<Member>, Error> {
789 let path = format!("/v1/organizations/{organization_id}/members/{user_id}");
790 let req = self.request(reqwest::Method::GET, &path);
791 let resp = req.send().await?;
792 let status = resp.status();
793 let body_text = resp.text().await?;
794 if !status.is_success() {
795 return Err(Error::Api {
796 status: status.as_u16(),
797 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
798 .ok()
799 .and_then(|r| r.error)
800 .unwrap_or(body_text.clone()),
801 });
802 }
803 Ok(serde_json::from_str(&body_text)?)
804 }
805
806 pub async fn member_update(
808 &self,
809 organization_id: &str,
810 user_id: &str,
811 body: &MemberPatchRequest,
812 ) -> Result<ApiResponse<Member>, Error> {
813 let path = format!("/v1/organizations/{organization_id}/members/{user_id}");
814 let mut req = self.request(reqwest::Method::PATCH, &path);
815 req = req.json(body);
816 let resp = req.send().await?;
817 let status = resp.status();
818 let body_text = resp.text().await?;
819 if !status.is_success() {
820 return Err(Error::Api {
821 status: status.as_u16(),
822 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
823 .ok()
824 .and_then(|r| r.error)
825 .unwrap_or(body_text.clone()),
826 });
827 }
828 Ok(serde_json::from_str(&body_text)?)
829 }
830
831 pub async fn member_delete(
833 &self,
834 organization_id: &str,
835 user_id: &str,
836 ) -> Result<ApiResponse<serde_json::Value>, Error> {
837 let path = format!("/v1/organizations/{organization_id}/members/{user_id}");
838 let req = self.request(reqwest::Method::DELETE, &path);
839 let resp = req.send().await?;
840 let status = resp.status();
841 let body_text = resp.text().await?;
842 if !status.is_success() {
843 return Err(Error::Api {
844 status: status.as_u16(),
845 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
846 .ok()
847 .and_then(|r| r.error)
848 .unwrap_or(body_text.clone()),
849 });
850 }
851 Ok(serde_json::from_str(&body_text)?)
852 }
853
854 pub async fn organization_roles_get_list(
856 &self,
857 organization_id: &str,
858 ) -> Result<ApiResponse<Vec<RBACRole>>, Error> {
859 let path = format!("/v1/organizations/{organization_id}/roles");
860 let req = self.request(reqwest::Method::GET, &path);
861 let resp = req.send().await?;
862 let status = resp.status();
863 let body_text = resp.text().await?;
864 if !status.is_success() {
865 return Err(Error::Api {
866 status: status.as_u16(),
867 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
868 .ok()
869 .and_then(|r| r.error)
870 .unwrap_or(body_text.clone()),
871 });
872 }
873 Ok(serde_json::from_str(&body_text)?)
874 }
875
876 pub async fn organization_role_post(
878 &self,
879 organization_id: &str,
880 body: &RoleCreateRequest,
881 ) -> Result<ApiResponse<RBACRole>, Error> {
882 let path = format!("/v1/organizations/{organization_id}/roles");
883 let mut req = self.request(reqwest::Method::POST, &path);
884 req = req.json(body);
885 let resp = req.send().await?;
886 let status = resp.status();
887 let body_text = resp.text().await?;
888 if !status.is_success() {
889 return Err(Error::Api {
890 status: status.as_u16(),
891 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
892 .ok()
893 .and_then(|r| r.error)
894 .unwrap_or(body_text.clone()),
895 });
896 }
897 Ok(serde_json::from_str(&body_text)?)
898 }
899
900 pub async fn organization_role_get(
902 &self,
903 organization_id: &str,
904 role_id: &str,
905 ) -> Result<ApiResponse<RBACRole>, Error> {
906 let path = format!("/v1/organizations/{organization_id}/roles/{role_id}");
907 let req = self.request(reqwest::Method::GET, &path);
908 let resp = req.send().await?;
909 let status = resp.status();
910 let body_text = resp.text().await?;
911 if !status.is_success() {
912 return Err(Error::Api {
913 status: status.as_u16(),
914 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
915 .ok()
916 .and_then(|r| r.error)
917 .unwrap_or(body_text.clone()),
918 });
919 }
920 Ok(serde_json::from_str(&body_text)?)
921 }
922
923 pub async fn organization_role_patch(
925 &self,
926 organization_id: &str,
927 role_id: &str,
928 body: &RoleUpdateRequest,
929 ) -> Result<ApiResponse<RBACRole>, Error> {
930 let path = format!("/v1/organizations/{organization_id}/roles/{role_id}");
931 let mut req = self.request(reqwest::Method::PATCH, &path);
932 req = req.json(body);
933 let resp = req.send().await?;
934 let status = resp.status();
935 let body_text = resp.text().await?;
936 if !status.is_success() {
937 return Err(Error::Api {
938 status: status.as_u16(),
939 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
940 .ok()
941 .and_then(|r| r.error)
942 .unwrap_or(body_text.clone()),
943 });
944 }
945 Ok(serde_json::from_str(&body_text)?)
946 }
947
948 pub async fn organization_role_delete(
950 &self,
951 organization_id: &str,
952 role_id: &str,
953 ) -> Result<ApiResponse<serde_json::Value>, Error> {
954 let path = format!("/v1/organizations/{organization_id}/roles/{role_id}");
955 let req = self.request(reqwest::Method::DELETE, &path);
956 let resp = req.send().await?;
957 let status = resp.status();
958 let body_text = resp.text().await?;
959 if !status.is_success() {
960 return Err(Error::Api {
961 status: status.as_u16(),
962 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
963 .ok()
964 .and_then(|r| r.error)
965 .unwrap_or(body_text.clone()),
966 });
967 }
968 Ok(serde_json::from_str(&body_text)?)
969 }
970
971 pub async fn postgres_service_create(
973 &self,
974 organization_id: &str,
975 body: &PostgresServicePostRequest,
976 ) -> Result<ApiResponse<PostgresService>, Error> {
977 let path = format!("/v1/organizations/{organization_id}/postgres");
978 let mut req = self.request(reqwest::Method::POST, &path);
979 req = req.json(body);
980 let resp = req.send().await?;
981 let status = resp.status();
982 let body_text = resp.text().await?;
983 if !status.is_success() {
984 return Err(Error::Api {
985 status: status.as_u16(),
986 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
987 .ok()
988 .and_then(|r| r.error)
989 .unwrap_or(body_text.clone()),
990 });
991 }
992 Ok(serde_json::from_str(&body_text)?)
993 }
994
995 pub async fn postgres_service_get_list(
997 &self,
998 organization_id: &str,
999 ) -> Result<ApiResponse<Vec<PostgresServiceListItem>>, Error> {
1000 let path = format!("/v1/organizations/{organization_id}/postgres");
1001 let req = self.request(reqwest::Method::GET, &path);
1002 let resp = req.send().await?;
1003 let status = resp.status();
1004 let body_text = resp.text().await?;
1005 if !status.is_success() {
1006 return Err(Error::Api {
1007 status: status.as_u16(),
1008 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1009 .ok()
1010 .and_then(|r| r.error)
1011 .unwrap_or(body_text.clone()),
1012 });
1013 }
1014 Ok(serde_json::from_str(&body_text)?)
1015 }
1016
1017 pub async fn postgres_service_get(
1019 &self,
1020 organization_id: &str,
1021 postgres_id: &str,
1022 ) -> Result<ApiResponse<PostgresService>, Error> {
1023 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}");
1024 let req = self.request(reqwest::Method::GET, &path);
1025 let resp = req.send().await?;
1026 let status = resp.status();
1027 let body_text = resp.text().await?;
1028 if !status.is_success() {
1029 return Err(Error::Api {
1030 status: status.as_u16(),
1031 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1032 .ok()
1033 .and_then(|r| r.error)
1034 .unwrap_or(body_text.clone()),
1035 });
1036 }
1037 Ok(serde_json::from_str(&body_text)?)
1038 }
1039
1040 pub async fn postgres_service_delete(
1042 &self,
1043 organization_id: &str,
1044 postgres_id: &str,
1045 ) -> Result<ApiResponse<serde_json::Value>, Error> {
1046 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}");
1047 let req = self.request(reqwest::Method::DELETE, &path);
1048 let resp = req.send().await?;
1049 let status = resp.status();
1050 let body_text = resp.text().await?;
1051 if !status.is_success() {
1052 return Err(Error::Api {
1053 status: status.as_u16(),
1054 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1055 .ok()
1056 .and_then(|r| r.error)
1057 .unwrap_or(body_text.clone()),
1058 });
1059 }
1060 Ok(serde_json::from_str(&body_text)?)
1061 }
1062
1063 pub async fn postgres_service_patch(
1065 &self,
1066 organization_id: &str,
1067 postgres_id: &str,
1068 body: &PostgresServicePatchRequest,
1069 ) -> Result<ApiResponse<PostgresService>, Error> {
1070 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}");
1071 let mut req = self.request(reqwest::Method::PATCH, &path);
1072 req = req.json(body);
1073 let resp = req.send().await?;
1074 let status = resp.status();
1075 let body_text = resp.text().await?;
1076 if !status.is_success() {
1077 return Err(Error::Api {
1078 status: status.as_u16(),
1079 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1080 .ok()
1081 .and_then(|r| r.error)
1082 .unwrap_or(body_text.clone()),
1083 });
1084 }
1085 Ok(serde_json::from_str(&body_text)?)
1086 }
1087
1088 pub async fn postgres_service_certs_get(
1090 &self,
1091 organization_id: &str,
1092 postgres_id: &str,
1093 ) -> Result<String, Error> {
1094 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/caCertificates");
1095 let req = self.request(reqwest::Method::GET, &path);
1096 let resp = req.send().await?;
1097 let status = resp.status();
1098 let body_text = resp.text().await?;
1099 if !status.is_success() {
1100 return Err(Error::Api {
1101 status: status.as_u16(),
1102 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1103 .ok()
1104 .and_then(|r| r.error)
1105 .unwrap_or(body_text.clone()),
1106 });
1107 }
1108 Ok(body_text)
1109 }
1110
1111 pub async fn postgres_instance_config_get(
1113 &self,
1114 organization_id: &str,
1115 postgres_id: &str,
1116 ) -> Result<ApiResponse<PostgresInstanceConfig>, Error> {
1117 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/config");
1118 let req = self.request(reqwest::Method::GET, &path);
1119 let resp = req.send().await?;
1120 let status = resp.status();
1121 let body_text = resp.text().await?;
1122 if !status.is_success() {
1123 return Err(Error::Api {
1124 status: status.as_u16(),
1125 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1126 .ok()
1127 .and_then(|r| r.error)
1128 .unwrap_or(body_text.clone()),
1129 });
1130 }
1131 Ok(serde_json::from_str(&body_text)?)
1132 }
1133
1134 pub async fn postgres_instance_config_post(
1136 &self,
1137 organization_id: &str,
1138 postgres_id: &str,
1139 body: &PostgresInstanceConfig,
1140 ) -> Result<ApiResponse<PostgresInstanceUpdateConfigResponse>, Error> {
1141 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/config");
1142 let mut req = self.request(reqwest::Method::POST, &path);
1143 req = req.json(body);
1144 let resp = req.send().await?;
1145 let status = resp.status();
1146 let body_text = resp.text().await?;
1147 if !status.is_success() {
1148 return Err(Error::Api {
1149 status: status.as_u16(),
1150 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1151 .ok()
1152 .and_then(|r| r.error)
1153 .unwrap_or(body_text.clone()),
1154 });
1155 }
1156 Ok(serde_json::from_str(&body_text)?)
1157 }
1158
1159 pub async fn postgres_instance_config_patch(
1161 &self,
1162 organization_id: &str,
1163 postgres_id: &str,
1164 body: &PostgresInstanceConfig,
1165 ) -> Result<ApiResponse<PostgresInstanceUpdateConfigResponse>, Error> {
1166 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/config");
1167 let mut req = self.request(reqwest::Method::PATCH, &path);
1168 req = req.json(body);
1169 let resp = req.send().await?;
1170 let status = resp.status();
1171 let body_text = resp.text().await?;
1172 if !status.is_success() {
1173 return Err(Error::Api {
1174 status: status.as_u16(),
1175 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1176 .ok()
1177 .and_then(|r| r.error)
1178 .unwrap_or(body_text.clone()),
1179 });
1180 }
1181 Ok(serde_json::from_str(&body_text)?)
1182 }
1183
1184 pub async fn postgres_service_set_password(
1186 &self,
1187 organization_id: &str,
1188 postgres_id: &str,
1189 body: &PostgresServiceSetPassword,
1190 ) -> Result<ApiResponse<PostgresServicePasswordResource>, Error> {
1191 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/password");
1192 let mut req = self.request(reqwest::Method::PATCH, &path);
1193 req = req.json(body);
1194 let resp = req.send().await?;
1195 let status = resp.status();
1196 let body_text = resp.text().await?;
1197 if !status.is_success() {
1198 return Err(Error::Api {
1199 status: status.as_u16(),
1200 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1201 .ok()
1202 .and_then(|r| r.error)
1203 .unwrap_or(body_text.clone()),
1204 });
1205 }
1206 Ok(serde_json::from_str(&body_text)?)
1207 }
1208
1209 pub async fn postgres_instance_create_read_replica(
1211 &self,
1212 organization_id: &str,
1213 postgres_id: &str,
1214 body: &PostgresServiceReadReplicaRequest,
1215 ) -> Result<ApiResponse<PostgresService>, Error> {
1216 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/readReplica");
1217 let mut req = self.request(reqwest::Method::POST, &path);
1218 req = req.json(body);
1219 let resp = req.send().await?;
1220 let status = resp.status();
1221 let body_text = resp.text().await?;
1222 if !status.is_success() {
1223 return Err(Error::Api {
1224 status: status.as_u16(),
1225 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1226 .ok()
1227 .and_then(|r| r.error)
1228 .unwrap_or(body_text.clone()),
1229 });
1230 }
1231 Ok(serde_json::from_str(&body_text)?)
1232 }
1233
1234 pub async fn postgres_instance_prometheus_get(
1236 &self,
1237 organization_id: &str,
1238 postgres_id: &str,
1239 ) -> Result<String, Error> {
1240 let path =
1241 format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/prometheus");
1242 let req = self.request(reqwest::Method::GET, &path);
1243 let resp = req.send().await?;
1244 let status = resp.status();
1245 if !status.is_success() {
1246 let body_text = resp.text().await?;
1247 return Err(Error::Api {
1248 status: status.as_u16(),
1249 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1250 .ok()
1251 .and_then(|r| r.error)
1252 .unwrap_or(body_text),
1253 });
1254 }
1255 Ok(resp.text().await?)
1256 }
1257
1258 pub async fn postgres_org_prometheus_get(
1260 &self,
1261 organization_id: &str,
1262 ) -> Result<String, Error> {
1263 let path = format!("/v1/organizations/{organization_id}/postgres/prometheus");
1264 let req = self.request(reqwest::Method::GET, &path);
1265 let resp = req.send().await?;
1266 let status = resp.status();
1267 if !status.is_success() {
1268 let body_text = resp.text().await?;
1269 return Err(Error::Api {
1270 status: status.as_u16(),
1271 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1272 .ok()
1273 .and_then(|r| r.error)
1274 .unwrap_or(body_text),
1275 });
1276 }
1277 Ok(resp.text().await?)
1278 }
1279
1280 pub async fn postgres_instance_restore(
1282 &self,
1283 organization_id: &str,
1284 postgres_id: &str,
1285 body: &PostgresServiceRestoreRequest,
1286 ) -> Result<ApiResponse<PostgresService>, Error> {
1287 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/restoredService");
1288 let mut req = self.request(reqwest::Method::POST, &path);
1289 req = req.json(body);
1290 let resp = req.send().await?;
1291 let status = resp.status();
1292 let body_text = resp.text().await?;
1293 if !status.is_success() {
1294 return Err(Error::Api {
1295 status: status.as_u16(),
1296 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1297 .ok()
1298 .and_then(|r| r.error)
1299 .unwrap_or(body_text.clone()),
1300 });
1301 }
1302 Ok(serde_json::from_str(&body_text)?)
1303 }
1304
1305 pub async fn postgres_service_patch_state(
1307 &self,
1308 organization_id: &str,
1309 postgres_id: &str,
1310 body: &PostgresServiceSetState,
1311 ) -> Result<ApiResponse<PostgresService>, Error> {
1312 let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/state");
1313 let mut req = self.request(reqwest::Method::PATCH, &path);
1314 req = req.json(body);
1315 let resp = req.send().await?;
1316 let status = resp.status();
1317 let body_text = resp.text().await?;
1318 if !status.is_success() {
1319 return Err(Error::Api {
1320 status: status.as_u16(),
1321 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1322 .ok()
1323 .and_then(|r| r.error)
1324 .unwrap_or(body_text.clone()),
1325 });
1326 }
1327 Ok(serde_json::from_str(&body_text)?)
1328 }
1329
1330 #[deprecated]
1332 #[allow(deprecated)]
1333 pub async fn organization_private_endpoint_config_get_list(
1334 &self,
1335 organization_id: &str,
1336 cloud_provider: &str,
1337 region_id: &str,
1338 ) -> Result<ApiResponse<OrganizationCloudRegionPrivateEndpointConfig>, Error> {
1339 let path = format!("/v1/organizations/{organization_id}/privateEndpointConfig");
1340 let mut req = self.request(reqwest::Method::GET, &path);
1341 req = req.query(&[("cloud_provider", cloud_provider)]);
1342 req = req.query(&[("region_id", region_id)]);
1343 let resp = req.send().await?;
1344 let status = resp.status();
1345 let body_text = resp.text().await?;
1346 if !status.is_success() {
1347 return Err(Error::Api {
1348 status: status.as_u16(),
1349 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1350 .ok()
1351 .and_then(|r| r.error)
1352 .unwrap_or(body_text.clone()),
1353 });
1354 }
1355 Ok(serde_json::from_str(&body_text)?)
1356 }
1357
1358 pub async fn organization_prometheus_get(
1360 &self,
1361 organization_id: &str,
1362 filtered_metrics: Option<&str>,
1363 ) -> Result<String, Error> {
1364 let path = format!("/v1/organizations/{organization_id}/prometheus");
1365 let mut req = self.request(reqwest::Method::GET, &path);
1366 if let Some(v) = filtered_metrics {
1367 req = req.query(&[("filtered_metrics", v)]);
1368 }
1369 let resp = req.send().await?;
1370 let status = resp.status();
1371 if !status.is_success() {
1372 let body_text = resp.text().await?;
1373 return Err(Error::Api {
1374 status: status.as_u16(),
1375 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1376 .ok()
1377 .and_then(|r| r.error)
1378 .unwrap_or(body_text),
1379 });
1380 }
1381 Ok(resp.text().await?)
1382 }
1383
1384 pub async fn instance_get_list(
1386 &self,
1387 organization_id: &str,
1388 filters: &[&str],
1389 ) -> Result<ApiResponse<Vec<Service>>, Error> {
1390 let path = format!("/v1/organizations/{organization_id}/services");
1391 let mut req = self.request(reqwest::Method::GET, &path);
1392 for f in filters {
1393 req = req.query(&[("filter", f)]);
1394 }
1395 let resp = req.send().await?;
1396 let status = resp.status();
1397 let body_text = resp.text().await?;
1398 if !status.is_success() {
1399 return Err(Error::Api {
1400 status: status.as_u16(),
1401 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1402 .ok()
1403 .and_then(|r| r.error)
1404 .unwrap_or(body_text.clone()),
1405 });
1406 }
1407 Ok(serde_json::from_str(&body_text)?)
1408 }
1409
1410 pub async fn instance_create(
1412 &self,
1413 organization_id: &str,
1414 body: &ServicePostRequest,
1415 ) -> Result<ApiResponse<ServicePostResponse>, Error> {
1416 let path = format!("/v1/organizations/{organization_id}/services");
1417 let mut req = self.request(reqwest::Method::POST, &path);
1418 req = req.json(body);
1419 let resp = req.send().await?;
1420 let status = resp.status();
1421 let body_text = resp.text().await?;
1422 if !status.is_success() {
1423 return Err(Error::Api {
1424 status: status.as_u16(),
1425 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1426 .ok()
1427 .and_then(|r| r.error)
1428 .unwrap_or(body_text.clone()),
1429 });
1430 }
1431 Ok(serde_json::from_str(&body_text)?)
1432 }
1433
1434 pub async fn instance_get(
1436 &self,
1437 organization_id: &str,
1438 service_id: &str,
1439 ) -> Result<ApiResponse<Service>, Error> {
1440 let path = format!("/v1/organizations/{organization_id}/services/{service_id}");
1441 let req = self.request(reqwest::Method::GET, &path);
1442 let resp = req.send().await?;
1443 let status = resp.status();
1444 let body_text = resp.text().await?;
1445 if !status.is_success() {
1446 return Err(Error::Api {
1447 status: status.as_u16(),
1448 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1449 .ok()
1450 .and_then(|r| r.error)
1451 .unwrap_or(body_text.clone()),
1452 });
1453 }
1454 Ok(serde_json::from_str(&body_text)?)
1455 }
1456
1457 pub async fn instance_update(
1459 &self,
1460 organization_id: &str,
1461 service_id: &str,
1462 body: &ServicePatchRequest,
1463 ) -> Result<ApiResponse<Service>, Error> {
1464 let path = format!("/v1/organizations/{organization_id}/services/{service_id}");
1465 let mut req = self.request(reqwest::Method::PATCH, &path);
1466 req = req.json(body);
1467 let resp = req.send().await?;
1468 let status = resp.status();
1469 let body_text = resp.text().await?;
1470 if !status.is_success() {
1471 return Err(Error::Api {
1472 status: status.as_u16(),
1473 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1474 .ok()
1475 .and_then(|r| r.error)
1476 .unwrap_or(body_text.clone()),
1477 });
1478 }
1479 Ok(serde_json::from_str(&body_text)?)
1480 }
1481
1482 pub async fn instance_delete(
1484 &self,
1485 organization_id: &str,
1486 service_id: &str,
1487 ) -> Result<ApiResponse<serde_json::Value>, Error> {
1488 let path = format!("/v1/organizations/{organization_id}/services/{service_id}");
1489 let req = self.request(reqwest::Method::DELETE, &path);
1490 let resp = req.send().await?;
1491 let status = resp.status();
1492 let body_text = resp.text().await?;
1493 if !status.is_success() {
1494 return Err(Error::Api {
1495 status: status.as_u16(),
1496 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1497 .ok()
1498 .and_then(|r| r.error)
1499 .unwrap_or(body_text.clone()),
1500 });
1501 }
1502 Ok(serde_json::from_str(&body_text)?)
1503 }
1504
1505 pub async fn backup_bucket_get(
1507 &self,
1508 organization_id: &str,
1509 service_id: &str,
1510 ) -> Result<ApiResponse<BackupBucket>, Error> {
1511 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1512 let req = self.request(reqwest::Method::GET, &path);
1513 let resp = req.send().await?;
1514 let status = resp.status();
1515 let body_text = resp.text().await?;
1516 if !status.is_success() {
1517 return Err(Error::Api {
1518 status: status.as_u16(),
1519 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1520 .ok()
1521 .and_then(|r| r.error)
1522 .unwrap_or(body_text.clone()),
1523 });
1524 }
1525 Ok(serde_json::from_str(&body_text)?)
1526 }
1527
1528 pub async fn backup_bucket_create(
1530 &self,
1531 organization_id: &str,
1532 service_id: &str,
1533 body: &BackupBucketPostRequest,
1534 ) -> Result<ApiResponse<BackupBucket>, Error> {
1535 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1536 let mut req = self.request(reqwest::Method::POST, &path);
1537 req = req.json(body);
1538 let resp = req.send().await?;
1539 let status = resp.status();
1540 let body_text = resp.text().await?;
1541 if !status.is_success() {
1542 return Err(Error::Api {
1543 status: status.as_u16(),
1544 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1545 .ok()
1546 .and_then(|r| r.error)
1547 .unwrap_or(body_text.clone()),
1548 });
1549 }
1550 Ok(serde_json::from_str(&body_text)?)
1551 }
1552
1553 pub async fn backup_bucket_update(
1555 &self,
1556 organization_id: &str,
1557 service_id: &str,
1558 body: &BackupBucketPatchRequest,
1559 ) -> Result<ApiResponse<BackupBucket>, Error> {
1560 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1561 let mut req = self.request(reqwest::Method::PATCH, &path);
1562 req = req.json(body);
1563 let resp = req.send().await?;
1564 let status = resp.status();
1565 let body_text = resp.text().await?;
1566 if !status.is_success() {
1567 return Err(Error::Api {
1568 status: status.as_u16(),
1569 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1570 .ok()
1571 .and_then(|r| r.error)
1572 .unwrap_or(body_text.clone()),
1573 });
1574 }
1575 Ok(serde_json::from_str(&body_text)?)
1576 }
1577
1578 pub async fn backup_bucket_delete(
1580 &self,
1581 organization_id: &str,
1582 service_id: &str,
1583 ) -> Result<ApiResponse<serde_json::Value>, Error> {
1584 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1585 let req = self.request(reqwest::Method::DELETE, &path);
1586 let resp = req.send().await?;
1587 let status = resp.status();
1588 let body_text = resp.text().await?;
1589 if !status.is_success() {
1590 return Err(Error::Api {
1591 status: status.as_u16(),
1592 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1593 .ok()
1594 .and_then(|r| r.error)
1595 .unwrap_or(body_text.clone()),
1596 });
1597 }
1598 Ok(serde_json::from_str(&body_text)?)
1599 }
1600
1601 pub async fn backup_configuration_get(
1603 &self,
1604 organization_id: &str,
1605 service_id: &str,
1606 ) -> Result<ApiResponse<BackupConfiguration>, Error> {
1607 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupConfiguration");
1608 let req = self.request(reqwest::Method::GET, &path);
1609 let resp = req.send().await?;
1610 let status = resp.status();
1611 let body_text = resp.text().await?;
1612 if !status.is_success() {
1613 return Err(Error::Api {
1614 status: status.as_u16(),
1615 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1616 .ok()
1617 .and_then(|r| r.error)
1618 .unwrap_or(body_text.clone()),
1619 });
1620 }
1621 Ok(serde_json::from_str(&body_text)?)
1622 }
1623
1624 pub async fn backup_configuration_update(
1626 &self,
1627 organization_id: &str,
1628 service_id: &str,
1629 body: &BackupConfigurationPatchRequest,
1630 ) -> Result<ApiResponse<BackupConfiguration>, Error> {
1631 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupConfiguration");
1632 let mut req = self.request(reqwest::Method::PATCH, &path);
1633 req = req.json(body);
1634 let resp = req.send().await?;
1635 let status = resp.status();
1636 let body_text = resp.text().await?;
1637 if !status.is_success() {
1638 return Err(Error::Api {
1639 status: status.as_u16(),
1640 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1641 .ok()
1642 .and_then(|r| r.error)
1643 .unwrap_or(body_text.clone()),
1644 });
1645 }
1646 Ok(serde_json::from_str(&body_text)?)
1647 }
1648
1649 pub async fn backup_get_list(
1651 &self,
1652 organization_id: &str,
1653 service_id: &str,
1654 ) -> Result<ApiResponse<Vec<Backup>>, Error> {
1655 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backups");
1656 let req = self.request(reqwest::Method::GET, &path);
1657 let resp = req.send().await?;
1658 let status = resp.status();
1659 let body_text = resp.text().await?;
1660 if !status.is_success() {
1661 return Err(Error::Api {
1662 status: status.as_u16(),
1663 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1664 .ok()
1665 .and_then(|r| r.error)
1666 .unwrap_or(body_text.clone()),
1667 });
1668 }
1669 Ok(serde_json::from_str(&body_text)?)
1670 }
1671
1672 pub async fn backup_get(
1674 &self,
1675 organization_id: &str,
1676 service_id: &str,
1677 backup_id: &str,
1678 ) -> Result<ApiResponse<Backup>, Error> {
1679 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backups/{backup_id}");
1680 let req = self.request(reqwest::Method::GET, &path);
1681 let resp = req.send().await?;
1682 let status = resp.status();
1683 let body_text = resp.text().await?;
1684 if !status.is_success() {
1685 return Err(Error::Api {
1686 status: status.as_u16(),
1687 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1688 .ok()
1689 .and_then(|r| r.error)
1690 .unwrap_or(body_text.clone()),
1691 });
1692 }
1693 Ok(serde_json::from_str(&body_text)?)
1694 }
1695
1696 pub async fn click_pipe_get_list(
1698 &self,
1699 organization_id: &str,
1700 service_id: &str,
1701 ) -> Result<ApiResponse<Vec<ClickPipe>>, Error> {
1702 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes");
1703 let req = self.request(reqwest::Method::GET, &path);
1704 let resp = req.send().await?;
1705 let status = resp.status();
1706 let body_text = resp.text().await?;
1707 if !status.is_success() {
1708 return Err(Error::Api {
1709 status: status.as_u16(),
1710 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1711 .ok()
1712 .and_then(|r| r.error)
1713 .unwrap_or(body_text.clone()),
1714 });
1715 }
1716 Ok(serde_json::from_str(&body_text)?)
1717 }
1718
1719 pub async fn click_pipe_create(
1721 &self,
1722 organization_id: &str,
1723 service_id: &str,
1724 body: &ClickPipePostRequest,
1725 ) -> Result<ApiResponse<ClickPipe>, Error> {
1726 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes");
1727 let mut req = self.request(reqwest::Method::POST, &path);
1728 req = req.json(body);
1729 let resp = req.send().await?;
1730 let status = resp.status();
1731 let body_text = resp.text().await?;
1732 if !status.is_success() {
1733 return Err(Error::Api {
1734 status: status.as_u16(),
1735 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1736 .ok()
1737 .and_then(|r| r.error)
1738 .unwrap_or(body_text.clone()),
1739 });
1740 }
1741 Ok(serde_json::from_str(&body_text)?)
1742 }
1743
1744 pub async fn click_pipe_get(
1746 &self,
1747 organization_id: &str,
1748 service_id: &str,
1749 click_pipe_id: &str,
1750 ) -> Result<ApiResponse<ClickPipe>, Error> {
1751 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}");
1752 let req = self.request(reqwest::Method::GET, &path);
1753 let resp = req.send().await?;
1754 let status = resp.status();
1755 let body_text = resp.text().await?;
1756 if !status.is_success() {
1757 return Err(Error::Api {
1758 status: status.as_u16(),
1759 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1760 .ok()
1761 .and_then(|r| r.error)
1762 .unwrap_or(body_text.clone()),
1763 });
1764 }
1765 Ok(serde_json::from_str(&body_text)?)
1766 }
1767
1768 pub async fn click_pipe_update(
1770 &self,
1771 organization_id: &str,
1772 service_id: &str,
1773 click_pipe_id: &str,
1774 body: &ClickPipePatchRequest,
1775 ) -> Result<ApiResponse<ClickPipe>, Error> {
1776 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}");
1777 let mut req = self.request(reqwest::Method::PATCH, &path);
1778 req = req.json(body);
1779 let resp = req.send().await?;
1780 let status = resp.status();
1781 let body_text = resp.text().await?;
1782 if !status.is_success() {
1783 return Err(Error::Api {
1784 status: status.as_u16(),
1785 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1786 .ok()
1787 .and_then(|r| r.error)
1788 .unwrap_or(body_text.clone()),
1789 });
1790 }
1791 Ok(serde_json::from_str(&body_text)?)
1792 }
1793
1794 pub async fn click_pipe_delete(
1796 &self,
1797 organization_id: &str,
1798 service_id: &str,
1799 click_pipe_id: &str,
1800 ) -> Result<ApiResponse<serde_json::Value>, Error> {
1801 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}");
1802 let req = self.request(reqwest::Method::DELETE, &path);
1803 let resp = req.send().await?;
1804 let status = resp.status();
1805 let body_text = resp.text().await?;
1806 if !status.is_success() {
1807 return Err(Error::Api {
1808 status: status.as_u16(),
1809 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1810 .ok()
1811 .and_then(|r| r.error)
1812 .unwrap_or(body_text.clone()),
1813 });
1814 }
1815 Ok(serde_json::from_str(&body_text)?)
1816 }
1817
1818 pub async fn click_pipe_scaling_update(
1820 &self,
1821 organization_id: &str,
1822 service_id: &str,
1823 click_pipe_id: &str,
1824 body: &ClickPipeScalingPatchRequest,
1825 ) -> Result<ApiResponse<ClickPipe>, Error> {
1826 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/scaling");
1827 let mut req = self.request(reqwest::Method::PATCH, &path);
1828 req = req.json(body);
1829 let resp = req.send().await?;
1830 let status = resp.status();
1831 let body_text = resp.text().await?;
1832 if !status.is_success() {
1833 return Err(Error::Api {
1834 status: status.as_u16(),
1835 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1836 .ok()
1837 .and_then(|r| r.error)
1838 .unwrap_or(body_text.clone()),
1839 });
1840 }
1841 Ok(serde_json::from_str(&body_text)?)
1842 }
1843
1844 pub async fn click_pipe_settings_get(
1846 &self,
1847 organization_id: &str,
1848 service_id: &str,
1849 click_pipe_id: &str,
1850 ) -> Result<ApiResponse<ClickPipeSettings>, Error> {
1851 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/settings");
1852 let req = self.request(reqwest::Method::GET, &path);
1853 let resp = req.send().await?;
1854 let status = resp.status();
1855 let body_text = resp.text().await?;
1856 if !status.is_success() {
1857 return Err(Error::Api {
1858 status: status.as_u16(),
1859 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1860 .ok()
1861 .and_then(|r| r.error)
1862 .unwrap_or(body_text.clone()),
1863 });
1864 }
1865 Ok(serde_json::from_str(&body_text)?)
1866 }
1867
1868 pub async fn click_pipe_settings_update(
1870 &self,
1871 organization_id: &str,
1872 service_id: &str,
1873 click_pipe_id: &str,
1874 body: &ClickPipeSettingsPutRequest,
1875 ) -> Result<ApiResponse<ClickPipeSettings>, Error> {
1876 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/settings");
1877 let mut req = self.request(reqwest::Method::PUT, &path);
1878 req = req.json(body);
1879 let resp = req.send().await?;
1880 let status = resp.status();
1881 let body_text = resp.text().await?;
1882 if !status.is_success() {
1883 return Err(Error::Api {
1884 status: status.as_u16(),
1885 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1886 .ok()
1887 .and_then(|r| r.error)
1888 .unwrap_or(body_text.clone()),
1889 });
1890 }
1891 Ok(serde_json::from_str(&body_text)?)
1892 }
1893
1894 pub async fn click_pipe_state_update(
1896 &self,
1897 organization_id: &str,
1898 service_id: &str,
1899 click_pipe_id: &str,
1900 body: &ClickPipeStatePatchRequest,
1901 ) -> Result<ApiResponse<ClickPipe>, Error> {
1902 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/state");
1903 let mut req = self.request(reqwest::Method::PATCH, &path);
1904 req = req.json(body);
1905 let resp = req.send().await?;
1906 let status = resp.status();
1907 let body_text = resp.text().await?;
1908 if !status.is_success() {
1909 return Err(Error::Api {
1910 status: status.as_u16(),
1911 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1912 .ok()
1913 .and_then(|r| r.error)
1914 .unwrap_or(body_text.clone()),
1915 });
1916 }
1917 Ok(serde_json::from_str(&body_text)?)
1918 }
1919
1920 pub async fn click_pipe_cdc_scaling_get(
1922 &self,
1923 organization_id: &str,
1924 service_id: &str,
1925 ) -> Result<ApiResponse<ClickPipesCdcScaling>, Error> {
1926 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesCdcScaling");
1927 let req = self.request(reqwest::Method::GET, &path);
1928 let resp = req.send().await?;
1929 let status = resp.status();
1930 let body_text = resp.text().await?;
1931 if !status.is_success() {
1932 return Err(Error::Api {
1933 status: status.as_u16(),
1934 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1935 .ok()
1936 .and_then(|r| r.error)
1937 .unwrap_or(body_text.clone()),
1938 });
1939 }
1940 Ok(serde_json::from_str(&body_text)?)
1941 }
1942
1943 pub async fn click_pipe_cdc_scaling_update(
1945 &self,
1946 organization_id: &str,
1947 service_id: &str,
1948 body: &ClickPipesCdcScalingPatchRequest,
1949 ) -> Result<ApiResponse<ClickPipesCdcScaling>, Error> {
1950 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesCdcScaling");
1951 let mut req = self.request(reqwest::Method::PATCH, &path);
1952 req = req.json(body);
1953 let resp = req.send().await?;
1954 let status = resp.status();
1955 let body_text = resp.text().await?;
1956 if !status.is_success() {
1957 return Err(Error::Api {
1958 status: status.as_u16(),
1959 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1960 .ok()
1961 .and_then(|r| r.error)
1962 .unwrap_or(body_text.clone()),
1963 });
1964 }
1965 Ok(serde_json::from_str(&body_text)?)
1966 }
1967
1968 pub async fn click_pipe_reverse_private_endpoint_get_list(
1970 &self,
1971 organization_id: &str,
1972 service_id: &str,
1973 ) -> Result<ApiResponse<Vec<ReversePrivateEndpoint>>, Error> {
1974 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints");
1975 let req = self.request(reqwest::Method::GET, &path);
1976 let resp = req.send().await?;
1977 let status = resp.status();
1978 let body_text = resp.text().await?;
1979 if !status.is_success() {
1980 return Err(Error::Api {
1981 status: status.as_u16(),
1982 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1983 .ok()
1984 .and_then(|r| r.error)
1985 .unwrap_or(body_text.clone()),
1986 });
1987 }
1988 Ok(serde_json::from_str(&body_text)?)
1989 }
1990
1991 pub async fn click_pipe_reverse_private_endpoint_create(
1993 &self,
1994 organization_id: &str,
1995 service_id: &str,
1996 body: &CreateReversePrivateEndpoint,
1997 ) -> Result<ApiResponse<ReversePrivateEndpoint>, Error> {
1998 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints");
1999 let mut req = self.request(reqwest::Method::POST, &path);
2000 req = req.json(body);
2001 let resp = req.send().await?;
2002 let status = resp.status();
2003 let body_text = resp.text().await?;
2004 if !status.is_success() {
2005 return Err(Error::Api {
2006 status: status.as_u16(),
2007 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2008 .ok()
2009 .and_then(|r| r.error)
2010 .unwrap_or(body_text.clone()),
2011 });
2012 }
2013 Ok(serde_json::from_str(&body_text)?)
2014 }
2015
2016 pub async fn click_pipe_reverse_private_endpoint_get(
2018 &self,
2019 organization_id: &str,
2020 service_id: &str,
2021 reverse_private_endpoint_id: &str,
2022 ) -> Result<ApiResponse<ReversePrivateEndpoint>, Error> {
2023 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints/{reverse_private_endpoint_id}");
2024 let req = self.request(reqwest::Method::GET, &path);
2025 let resp = req.send().await?;
2026 let status = resp.status();
2027 let body_text = resp.text().await?;
2028 if !status.is_success() {
2029 return Err(Error::Api {
2030 status: status.as_u16(),
2031 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2032 .ok()
2033 .and_then(|r| r.error)
2034 .unwrap_or(body_text.clone()),
2035 });
2036 }
2037 Ok(serde_json::from_str(&body_text)?)
2038 }
2039
2040 pub async fn click_pipe_reverse_private_endpoint_delete(
2042 &self,
2043 organization_id: &str,
2044 service_id: &str,
2045 reverse_private_endpoint_id: &str,
2046 ) -> Result<ApiResponse<serde_json::Value>, Error> {
2047 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints/{reverse_private_endpoint_id}");
2048 let req = self.request(reqwest::Method::DELETE, &path);
2049 let resp = req.send().await?;
2050 let status = resp.status();
2051 let body_text = resp.text().await?;
2052 if !status.is_success() {
2053 return Err(Error::Api {
2054 status: status.as_u16(),
2055 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2056 .ok()
2057 .and_then(|r| r.error)
2058 .unwrap_or(body_text.clone()),
2059 });
2060 }
2061 Ok(serde_json::from_str(&body_text)?)
2062 }
2063
2064 pub async fn click_stack_list_alerts(
2066 &self,
2067 organization_id: &str,
2068 service_id: &str,
2069 ) -> Result<ApiResponse<Vec<ClickStackAlertResponse>>, Error> {
2070 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts");
2071 let req = self.request(reqwest::Method::GET, &path);
2072 let resp = req.send().await?;
2073 let status = resp.status();
2074 let body_text = resp.text().await?;
2075 if !status.is_success() {
2076 return Err(Error::Api {
2077 status: status.as_u16(),
2078 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2079 .ok()
2080 .and_then(|r| r.error)
2081 .unwrap_or(body_text.clone()),
2082 });
2083 }
2084 Ok(serde_json::from_str(&body_text)?)
2085 }
2086
2087 pub async fn click_stack_create_alert(
2089 &self,
2090 organization_id: &str,
2091 service_id: &str,
2092 body: &ClickStackCreateAlertRequest,
2093 ) -> Result<ApiResponse<ClickStackAlertResponse>, Error> {
2094 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts");
2095 let mut req = self.request(reqwest::Method::POST, &path);
2096 req = req.json(body);
2097 let resp = req.send().await?;
2098 let status = resp.status();
2099 let body_text = resp.text().await?;
2100 if !status.is_success() {
2101 return Err(Error::Api {
2102 status: status.as_u16(),
2103 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2104 .ok()
2105 .and_then(|r| r.error)
2106 .unwrap_or(body_text.clone()),
2107 });
2108 }
2109 Ok(serde_json::from_str(&body_text)?)
2110 }
2111
2112 pub async fn click_stack_get_alert(
2114 &self,
2115 organization_id: &str,
2116 service_id: &str,
2117 click_stack_alert_id: &str,
2118 ) -> Result<ApiResponse<ClickStackAlertResponse>, Error> {
2119 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts/{click_stack_alert_id}");
2120 let req = self.request(reqwest::Method::GET, &path);
2121 let resp = req.send().await?;
2122 let status = resp.status();
2123 let body_text = resp.text().await?;
2124 if !status.is_success() {
2125 return Err(Error::Api {
2126 status: status.as_u16(),
2127 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2128 .ok()
2129 .and_then(|r| r.error)
2130 .unwrap_or(body_text.clone()),
2131 });
2132 }
2133 Ok(serde_json::from_str(&body_text)?)
2134 }
2135
2136 pub async fn click_stack_update_alert(
2138 &self,
2139 organization_id: &str,
2140 service_id: &str,
2141 click_stack_alert_id: &str,
2142 body: &ClickStackUpdateAlertRequest,
2143 ) -> Result<ApiResponse<ClickStackAlertResponse>, Error> {
2144 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts/{click_stack_alert_id}");
2145 let mut req = self.request(reqwest::Method::PUT, &path);
2146 req = req.json(body);
2147 let resp = req.send().await?;
2148 let status = resp.status();
2149 let body_text = resp.text().await?;
2150 if !status.is_success() {
2151 return Err(Error::Api {
2152 status: status.as_u16(),
2153 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2154 .ok()
2155 .and_then(|r| r.error)
2156 .unwrap_or(body_text.clone()),
2157 });
2158 }
2159 Ok(serde_json::from_str(&body_text)?)
2160 }
2161
2162 pub async fn click_stack_delete_alert(
2164 &self,
2165 organization_id: &str,
2166 service_id: &str,
2167 click_stack_alert_id: &str,
2168 ) -> Result<ApiResponse<serde_json::Value>, Error> {
2169 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts/{click_stack_alert_id}");
2170 let req = self.request(reqwest::Method::DELETE, &path);
2171 let resp = req.send().await?;
2172 let status = resp.status();
2173 let body_text = resp.text().await?;
2174 if !status.is_success() {
2175 return Err(Error::Api {
2176 status: status.as_u16(),
2177 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2178 .ok()
2179 .and_then(|r| r.error)
2180 .unwrap_or(body_text.clone()),
2181 });
2182 }
2183 Ok(serde_json::from_str(&body_text)?)
2184 }
2185
2186 pub async fn click_stack_list_dashboards(
2188 &self,
2189 organization_id: &str,
2190 service_id: &str,
2191 ) -> Result<ApiResponse<Vec<ClickStackDashboardResponse>>, Error> {
2192 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards");
2193 let req = self.request(reqwest::Method::GET, &path);
2194 let resp = req.send().await?;
2195 let status = resp.status();
2196 let body_text = resp.text().await?;
2197 if !status.is_success() {
2198 return Err(Error::Api {
2199 status: status.as_u16(),
2200 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2201 .ok()
2202 .and_then(|r| r.error)
2203 .unwrap_or(body_text.clone()),
2204 });
2205 }
2206 Ok(serde_json::from_str(&body_text)?)
2207 }
2208
2209 pub async fn click_stack_create_dashboard(
2211 &self,
2212 organization_id: &str,
2213 service_id: &str,
2214 body: &ClickStackCreateDashboardRequest,
2215 ) -> Result<ApiResponse<ClickStackDashboardResponse>, Error> {
2216 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards");
2217 let mut req = self.request(reqwest::Method::POST, &path);
2218 req = req.json(body);
2219 let resp = req.send().await?;
2220 let status = resp.status();
2221 let body_text = resp.text().await?;
2222 if !status.is_success() {
2223 return Err(Error::Api {
2224 status: status.as_u16(),
2225 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2226 .ok()
2227 .and_then(|r| r.error)
2228 .unwrap_or(body_text.clone()),
2229 });
2230 }
2231 Ok(serde_json::from_str(&body_text)?)
2232 }
2233
2234 pub async fn click_stack_get_dashboard(
2236 &self,
2237 organization_id: &str,
2238 service_id: &str,
2239 click_stack_dashboard_id: &str,
2240 ) -> Result<ApiResponse<ClickStackDashboardResponse>, Error> {
2241 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards/{click_stack_dashboard_id}");
2242 let req = self.request(reqwest::Method::GET, &path);
2243 let resp = req.send().await?;
2244 let status = resp.status();
2245 let body_text = resp.text().await?;
2246 if !status.is_success() {
2247 return Err(Error::Api {
2248 status: status.as_u16(),
2249 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2250 .ok()
2251 .and_then(|r| r.error)
2252 .unwrap_or(body_text.clone()),
2253 });
2254 }
2255 Ok(serde_json::from_str(&body_text)?)
2256 }
2257
2258 pub async fn click_stack_update_dashboard(
2260 &self,
2261 organization_id: &str,
2262 service_id: &str,
2263 click_stack_dashboard_id: &str,
2264 body: &ClickStackUpdateDashboardRequest,
2265 ) -> Result<ApiResponse<ClickStackDashboardResponse>, Error> {
2266 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards/{click_stack_dashboard_id}");
2267 let mut req = self.request(reqwest::Method::PUT, &path);
2268 req = req.json(body);
2269 let resp = req.send().await?;
2270 let status = resp.status();
2271 let body_text = resp.text().await?;
2272 if !status.is_success() {
2273 return Err(Error::Api {
2274 status: status.as_u16(),
2275 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2276 .ok()
2277 .and_then(|r| r.error)
2278 .unwrap_or(body_text.clone()),
2279 });
2280 }
2281 Ok(serde_json::from_str(&body_text)?)
2282 }
2283
2284 pub async fn click_stack_delete_dashboard(
2286 &self,
2287 organization_id: &str,
2288 service_id: &str,
2289 click_stack_dashboard_id: &str,
2290 ) -> Result<ApiResponse<serde_json::Value>, Error> {
2291 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards/{click_stack_dashboard_id}");
2292 let req = self.request(reqwest::Method::DELETE, &path);
2293 let resp = req.send().await?;
2294 let status = resp.status();
2295 let body_text = resp.text().await?;
2296 if !status.is_success() {
2297 return Err(Error::Api {
2298 status: status.as_u16(),
2299 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2300 .ok()
2301 .and_then(|r| r.error)
2302 .unwrap_or(body_text.clone()),
2303 });
2304 }
2305 Ok(serde_json::from_str(&body_text)?)
2306 }
2307
2308 pub async fn click_stack_list_sources(
2310 &self,
2311 organization_id: &str,
2312 service_id: &str,
2313 ) -> Result<ApiResponse<Vec<ClickStackSource>>, Error> {
2314 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/sources");
2315 let req = self.request(reqwest::Method::GET, &path);
2316 let resp = req.send().await?;
2317 let status = resp.status();
2318 let body_text = resp.text().await?;
2319 if !status.is_success() {
2320 return Err(Error::Api {
2321 status: status.as_u16(),
2322 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2323 .ok()
2324 .and_then(|r| r.error)
2325 .unwrap_or(body_text.clone()),
2326 });
2327 }
2328 Ok(serde_json::from_str(&body_text)?)
2329 }
2330
2331 pub async fn click_stack_list_webhooks(
2333 &self,
2334 organization_id: &str,
2335 service_id: &str,
2336 ) -> Result<ApiResponse<Vec<ClickStackWebhook>>, Error> {
2337 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/webhooks");
2338 let req = self.request(reqwest::Method::GET, &path);
2339 let resp = req.send().await?;
2340 let status = resp.status();
2341 let body_text = resp.text().await?;
2342 if !status.is_success() {
2343 return Err(Error::Api {
2344 status: status.as_u16(),
2345 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2346 .ok()
2347 .and_then(|r| r.error)
2348 .unwrap_or(body_text.clone()),
2349 });
2350 }
2351 Ok(serde_json::from_str(&body_text)?)
2352 }
2353
2354 pub async fn instance_password_update(
2356 &self,
2357 organization_id: &str,
2358 service_id: &str,
2359 body: &ServicePasswordPatchRequest,
2360 ) -> Result<ApiResponse<ServicePasswordPatchResponse>, Error> {
2361 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/password");
2362 let mut req = self.request(reqwest::Method::PATCH, &path);
2363 req = req.json(body);
2364 let resp = req.send().await?;
2365 let status = resp.status();
2366 let body_text = resp.text().await?;
2367 if !status.is_success() {
2368 return Err(Error::Api {
2369 status: status.as_u16(),
2370 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2371 .ok()
2372 .and_then(|r| r.error)
2373 .unwrap_or(body_text.clone()),
2374 });
2375 }
2376 Ok(serde_json::from_str(&body_text)?)
2377 }
2378
2379 pub async fn instance_private_endpoint_create(
2381 &self,
2382 organization_id: &str,
2383 service_id: &str,
2384 body: &ServicPrivateEndpointePostRequest,
2385 ) -> Result<ApiResponse<InstancePrivateEndpoint>, Error> {
2386 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/privateEndpoint");
2387 let mut req = self.request(reqwest::Method::POST, &path);
2388 req = req.json(body);
2389 let resp = req.send().await?;
2390 let status = resp.status();
2391 let body_text = resp.text().await?;
2392 if !status.is_success() {
2393 return Err(Error::Api {
2394 status: status.as_u16(),
2395 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2396 .ok()
2397 .and_then(|r| r.error)
2398 .unwrap_or(body_text.clone()),
2399 });
2400 }
2401 Ok(serde_json::from_str(&body_text)?)
2402 }
2403
2404 pub async fn instance_private_endpoint_config_get(
2406 &self,
2407 organization_id: &str,
2408 service_id: &str,
2409 ) -> Result<ApiResponse<PrivateEndpointConfig>, Error> {
2410 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/privateEndpointConfig");
2411 let req = self.request(reqwest::Method::GET, &path);
2412 let resp = req.send().await?;
2413 let status = resp.status();
2414 let body_text = resp.text().await?;
2415 if !status.is_success() {
2416 return Err(Error::Api {
2417 status: status.as_u16(),
2418 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2419 .ok()
2420 .and_then(|r| r.error)
2421 .unwrap_or(body_text.clone()),
2422 });
2423 }
2424 Ok(serde_json::from_str(&body_text)?)
2425 }
2426
2427 pub async fn instance_prometheus_get(
2429 &self,
2430 organization_id: &str,
2431 service_id: &str,
2432 filtered_metrics: Option<&str>,
2433 ) -> Result<String, Error> {
2434 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/prometheus");
2435 let mut req = self.request(reqwest::Method::GET, &path);
2436 if let Some(v) = filtered_metrics {
2437 req = req.query(&[("filtered_metrics", v)]);
2438 }
2439 let resp = req.send().await?;
2440 let status = resp.status();
2441 if !status.is_success() {
2442 let body_text = resp.text().await?;
2443 return Err(Error::Api {
2444 status: status.as_u16(),
2445 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2446 .ok()
2447 .and_then(|r| r.error)
2448 .unwrap_or(body_text),
2449 });
2450 }
2451 Ok(resp.text().await?)
2452 }
2453
2454 pub async fn instance_replica_scaling_update(
2456 &self,
2457 organization_id: &str,
2458 service_id: &str,
2459 body: &ServiceReplicaScalingPatchRequest,
2460 ) -> Result<ApiResponse<ServiceScalingPatchResponse>, Error> {
2461 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/replicaScaling");
2462 let mut req = self.request(reqwest::Method::PATCH, &path);
2463 req = req.json(body);
2464 let resp = req.send().await?;
2465 let status = resp.status();
2466 let body_text = resp.text().await?;
2467 if !status.is_success() {
2468 return Err(Error::Api {
2469 status: status.as_u16(),
2470 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2471 .ok()
2472 .and_then(|r| r.error)
2473 .unwrap_or(body_text.clone()),
2474 });
2475 }
2476 Ok(serde_json::from_str(&body_text)?)
2477 }
2478
2479 #[deprecated]
2481 #[allow(deprecated)]
2482 pub async fn instance_scaling_update(
2483 &self,
2484 organization_id: &str,
2485 service_id: &str,
2486 body: &ServiceScalingPatchRequest,
2487 ) -> Result<ApiResponse<Service>, Error> {
2488 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scaling");
2489 let mut req = self.request(reqwest::Method::PATCH, &path);
2490 req = req.json(body);
2491 let resp = req.send().await?;
2492 let status = resp.status();
2493 let body_text = resp.text().await?;
2494 if !status.is_success() {
2495 return Err(Error::Api {
2496 status: status.as_u16(),
2497 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2498 .ok()
2499 .and_then(|r| r.error)
2500 .unwrap_or(body_text.clone()),
2501 });
2502 }
2503 Ok(serde_json::from_str(&body_text)?)
2504 }
2505
2506 pub async fn scaling_schedule_get(
2508 &self,
2509 organization_id: &str,
2510 service_id: &str,
2511 ) -> Result<ApiResponse<ScalingSchedule>, Error> {
2512 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scalingSchedule");
2513 let req = self.request(reqwest::Method::GET, &path);
2514 let resp = req.send().await?;
2515 let status = resp.status();
2516 let body_text = resp.text().await?;
2517 if !status.is_success() {
2518 return Err(Error::Api {
2519 status: status.as_u16(),
2520 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2521 .ok()
2522 .and_then(|r| r.error)
2523 .unwrap_or(body_text.clone()),
2524 });
2525 }
2526 Ok(serde_json::from_str(&body_text)?)
2527 }
2528
2529 pub async fn scaling_schedule_upsert(
2531 &self,
2532 organization_id: &str,
2533 service_id: &str,
2534 body: &ScalingSchedulePostRequest,
2535 ) -> Result<ApiResponse<ScalingSchedule>, Error> {
2536 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scalingSchedule");
2537 let mut req = self.request(reqwest::Method::POST, &path);
2538 req = req.json(body);
2539 let resp = req.send().await?;
2540 let status = resp.status();
2541 let body_text = resp.text().await?;
2542 if !status.is_success() {
2543 return Err(Error::Api {
2544 status: status.as_u16(),
2545 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2546 .ok()
2547 .and_then(|r| r.error)
2548 .unwrap_or(body_text.clone()),
2549 });
2550 }
2551 Ok(serde_json::from_str(&body_text)?)
2552 }
2553
2554 pub async fn scaling_schedule_delete(
2556 &self,
2557 organization_id: &str,
2558 service_id: &str,
2559 ) -> Result<ApiResponse<serde_json::Value>, Error> {
2560 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scalingSchedule");
2561 let req = self.request(reqwest::Method::DELETE, &path);
2562 let resp = req.send().await?;
2563 let status = resp.status();
2564 let body_text = resp.text().await?;
2565 if !status.is_success() {
2566 return Err(Error::Api {
2567 status: status.as_u16(),
2568 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2569 .ok()
2570 .and_then(|r| r.error)
2571 .unwrap_or(body_text.clone()),
2572 });
2573 }
2574 Ok(serde_json::from_str(&body_text)?)
2575 }
2576
2577 pub async fn upgrade_window_get(
2579 &self,
2580 organization_id: &str,
2581 service_id: &str,
2582 ) -> Result<ApiResponse<UpgradeWindow>, Error> {
2583 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/upgradeWindow");
2584 let req = self.request(reqwest::Method::GET, &path);
2585 let resp = req.send().await?;
2586 let status = resp.status();
2587 let body_text = resp.text().await?;
2588 if !status.is_success() {
2589 return Err(Error::Api {
2590 status: status.as_u16(),
2591 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2592 .ok()
2593 .and_then(|r| r.error)
2594 .unwrap_or(body_text.clone()),
2595 });
2596 }
2597 Ok(serde_json::from_str(&body_text)?)
2598 }
2599
2600 pub async fn upgrade_window_update(
2602 &self,
2603 organization_id: &str,
2604 service_id: &str,
2605 body: &UpgradeWindowPutRequest,
2606 ) -> Result<ApiResponse<UpgradeWindow>, Error> {
2607 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/upgradeWindow");
2608 let mut req = self.request(reqwest::Method::PUT, &path);
2609 req = req.json(body);
2610 let resp = req.send().await?;
2611 let status = resp.status();
2612 let body_text = resp.text().await?;
2613 if !status.is_success() {
2614 return Err(Error::Api {
2615 status: status.as_u16(),
2616 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2617 .ok()
2618 .and_then(|r| r.error)
2619 .unwrap_or(body_text.clone()),
2620 });
2621 }
2622 Ok(serde_json::from_str(&body_text)?)
2623 }
2624
2625 pub async fn upgrade_window_delete(
2627 &self,
2628 organization_id: &str,
2629 service_id: &str,
2630 ) -> Result<ApiResponse<serde_json::Value>, Error> {
2631 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/upgradeWindow");
2632 let req = self.request(reqwest::Method::DELETE, &path);
2633 let resp = req.send().await?;
2634 let status = resp.status();
2635 let body_text = resp.text().await?;
2636 if !status.is_success() {
2637 return Err(Error::Api {
2638 status: status.as_u16(),
2639 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2640 .ok()
2641 .and_then(|r| r.error)
2642 .unwrap_or(body_text.clone()),
2643 });
2644 }
2645 Ok(serde_json::from_str(&body_text)?)
2646 }
2647
2648 pub async fn instance_query_endpoint_get(
2650 &self,
2651 organization_id: &str,
2652 service_id: &str,
2653 ) -> Result<ApiResponse<ServiceQueryAPIEndpoint>, Error> {
2654 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/serviceQueryEndpoint");
2655 let req = self.request(reqwest::Method::GET, &path);
2656 let resp = req.send().await?;
2657 let status = resp.status();
2658 let body_text = resp.text().await?;
2659 if !status.is_success() {
2660 return Err(Error::Api {
2661 status: status.as_u16(),
2662 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2663 .ok()
2664 .and_then(|r| r.error)
2665 .unwrap_or(body_text.clone()),
2666 });
2667 }
2668 Ok(serde_json::from_str(&body_text)?)
2669 }
2670
2671 pub async fn instance_query_endpoint_delete(
2673 &self,
2674 organization_id: &str,
2675 service_id: &str,
2676 ) -> Result<ApiResponse<serde_json::Value>, Error> {
2677 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/serviceQueryEndpoint");
2678 let req = self.request(reqwest::Method::DELETE, &path);
2679 let resp = req.send().await?;
2680 let status = resp.status();
2681 let body_text = resp.text().await?;
2682 if !status.is_success() {
2683 return Err(Error::Api {
2684 status: status.as_u16(),
2685 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2686 .ok()
2687 .and_then(|r| r.error)
2688 .unwrap_or(body_text.clone()),
2689 });
2690 }
2691 Ok(serde_json::from_str(&body_text)?)
2692 }
2693
2694 pub async fn instance_query_endpoint_upsert(
2696 &self,
2697 organization_id: &str,
2698 service_id: &str,
2699 body: &InstanceServiceQueryApiEndpointsPostRequest,
2700 ) -> Result<ApiResponse<ServiceQueryAPIEndpoint>, Error> {
2701 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/serviceQueryEndpoint");
2702 let mut req = self.request(reqwest::Method::POST, &path);
2703 req = req.json(body);
2704 let resp = req.send().await?;
2705 let status = resp.status();
2706 let body_text = resp.text().await?;
2707 if !status.is_success() {
2708 return Err(Error::Api {
2709 status: status.as_u16(),
2710 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2711 .ok()
2712 .and_then(|r| r.error)
2713 .unwrap_or(body_text.clone()),
2714 });
2715 }
2716 Ok(serde_json::from_str(&body_text)?)
2717 }
2718
2719 pub async fn instance_state_update(
2721 &self,
2722 organization_id: &str,
2723 service_id: &str,
2724 body: &ServiceStatePatchRequest,
2725 ) -> Result<ApiResponse<Service>, Error> {
2726 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/state");
2727 let mut req = self.request(reqwest::Method::PATCH, &path);
2728 req = req.json(body);
2729 let resp = req.send().await?;
2730 let status = resp.status();
2731 let body_text = resp.text().await?;
2732 if !status.is_success() {
2733 return Err(Error::Api {
2734 status: status.as_u16(),
2735 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2736 .ok()
2737 .and_then(|r| r.error)
2738 .unwrap_or(body_text.clone()),
2739 });
2740 }
2741 Ok(serde_json::from_str(&body_text)?)
2742 }
2743
2744 pub async fn usage_cost_get(
2746 &self,
2747 organization_id: &str,
2748 from_date: &str,
2749 to_date: &str,
2750 filters: &[&str],
2751 ) -> Result<ApiResponse<UsageCost>, Error> {
2752 let path = format!("/v1/organizations/{organization_id}/usageCost");
2753 let mut req = self.request(reqwest::Method::GET, &path);
2754 req = req.query(&[("from_date", from_date)]);
2755 req = req.query(&[("to_date", to_date)]);
2756 for f in filters {
2757 req = req.query(&[("filter", f)]);
2758 }
2759 let resp = req.send().await?;
2760 let status = resp.status();
2761 let body_text = resp.text().await?;
2762 if !status.is_success() {
2763 return Err(Error::Api {
2764 status: status.as_u16(),
2765 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2766 .ok()
2767 .and_then(|r| r.error)
2768 .unwrap_or(body_text.clone()),
2769 });
2770 }
2771 Ok(serde_json::from_str(&body_text)?)
2772 }
2773
2774 pub async fn service_clickhouse_settings_list_get(
2776 &self,
2777 organization_id: &str,
2778 service_id: &str,
2779 ) -> Result<ApiResponse<ServiceClickhouseSettingsList>, Error> {
2780 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings");
2781 let req = self.request(reqwest::Method::GET, &path);
2782 let resp = req.send().await?;
2783 let status = resp.status();
2784 let body_text = resp.text().await?;
2785 if !status.is_success() {
2786 return Err(Error::Api {
2787 status: status.as_u16(),
2788 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2789 .ok()
2790 .and_then(|r| r.error)
2791 .unwrap_or(body_text.clone()),
2792 });
2793 }
2794 Ok(serde_json::from_str(&body_text)?)
2795 }
2796
2797 pub async fn service_clickhouse_settings_update(
2799 &self,
2800 organization_id: &str,
2801 service_id: &str,
2802 body: &ServiceClickhouseSettingsPatchRequest,
2803 ) -> Result<ApiResponse<ServiceClickhouseSettingsPatchResponse>, Error> {
2804 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings");
2805 let mut req = self.request(reqwest::Method::PATCH, &path);
2806 req = req.json(body);
2807 let resp = req.send().await?;
2808 let status = resp.status();
2809 let body_text = resp.text().await?;
2810 if !status.is_success() {
2811 return Err(Error::Api {
2812 status: status.as_u16(),
2813 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2814 .ok()
2815 .and_then(|r| r.error)
2816 .unwrap_or(body_text.clone()),
2817 });
2818 }
2819 Ok(serde_json::from_str(&body_text)?)
2820 }
2821
2822 pub async fn service_clickhouse_settings_schema_get(
2824 &self,
2825 organization_id: &str,
2826 service_id: &str,
2827 ) -> Result<ApiResponse<ServiceClickhouseSettingsSchema>, Error> {
2828 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings/schema");
2829 let req = self.request(reqwest::Method::GET, &path);
2830 let resp = req.send().await?;
2831 let status = resp.status();
2832 let body_text = resp.text().await?;
2833 if !status.is_success() {
2834 return Err(Error::Api {
2835 status: status.as_u16(),
2836 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2837 .ok()
2838 .and_then(|r| r.error)
2839 .unwrap_or(body_text.clone()),
2840 });
2841 }
2842 Ok(serde_json::from_str(&body_text)?)
2843 }
2844
2845 pub async fn service_clickhouse_setting_get(
2847 &self,
2848 organization_id: &str,
2849 service_id: &str,
2850 setting_name: &str,
2851 ) -> Result<ApiResponse<ServiceClickhouseSetting>, Error> {
2852 let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings/{setting_name}");
2853 let req = self.request(reqwest::Method::GET, &path);
2854 let resp = req.send().await?;
2855 let status = resp.status();
2856 let body_text = resp.text().await?;
2857 if !status.is_success() {
2858 return Err(Error::Api {
2859 status: status.as_u16(),
2860 message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2861 .ok()
2862 .and_then(|r| r.error)
2863 .unwrap_or(body_text.clone()),
2864 });
2865 }
2866 Ok(serde_json::from_str(&body_text)?)
2867 }
2868
2869}
2870
2871#[cfg(test)]
2872mod tests {
2873 use super::derive_query_host;
2874
2875 #[test]
2876 fn derive_query_host_prod() {
2877 assert_eq!(
2878 derive_query_host("https://api.clickhouse.cloud").as_deref(),
2879 Some("https://queries.clickhouse.cloud")
2880 );
2881 }
2882
2883 #[test]
2884 fn derive_query_host_staging() {
2885 assert_eq!(
2886 derive_query_host("https://api.control-plane.clickhouse-staging.com").as_deref(),
2887 Some("https://queries.clickhouse-staging.com")
2888 );
2889 }
2890
2891 #[test]
2892 fn derive_query_host_dev() {
2893 assert_eq!(
2894 derive_query_host("https://api.control-plane.clickhouse-dev.com").as_deref(),
2895 Some("https://queries.clickhouse-dev.com")
2896 );
2897 }
2898
2899 #[test]
2900 fn derive_query_host_plain_api_prefix_without_control_plane() {
2901 assert_eq!(
2902 derive_query_host("https://api.clickhouse-staging.com").as_deref(),
2903 Some("https://queries.clickhouse-staging.com")
2904 );
2905 }
2906
2907 #[test]
2908 fn derive_query_host_non_api_host_is_none() {
2909 assert_eq!(derive_query_host("http://127.0.0.1:8123"), None);
2910 assert_eq!(derive_query_host("https://example.com"), None);
2911 }
2912
2913 #[test]
2914 fn derive_query_host_invalid_url_is_none() {
2915 assert_eq!(derive_query_host("not a url"), None);
2916 }
2917
2918 #[test]
2919 fn derive_query_host_preserves_non_default_port() {
2920 assert_eq!(
2921 derive_query_host("https://api.mycorp.example.com:8443").as_deref(),
2922 Some("https://queries.mycorp.example.com:8443")
2923 );
2924 assert_eq!(
2927 derive_query_host("https://api.clickhouse.cloud:443").as_deref(),
2928 Some("https://queries.clickhouse.cloud")
2929 );
2930 }
2931}