#[derive(Debug)]
pub enum TemplateError {
RequestFailure(reqwest::Error),
InvalidHeaderValue(reqwest::header::InvalidHeaderValue),
UnexpectedStatus(reqwest::StatusCode),
Status504,
Status404 {
message: String,
},
Status403 {
error: String,
},
Status400 {
errors: Vec<String>,
},
Status500 {
error: String,
},
Status401 {
error: String,
},
Status409 {
component_id: uuid::Uuid,
},
}
impl From<reqwest::Error> for TemplateError {
fn from(error: reqwest::Error) -> TemplateError {
TemplateError::RequestFailure(error)
}
}
impl From<reqwest::header::InvalidHeaderValue> for TemplateError {
fn from(error: reqwest::header::InvalidHeaderValue) -> TemplateError {
TemplateError::InvalidHeaderValue(error)
}
}
impl TemplateError {
pub fn to_template_endpoint_error(&self) -> Option<crate::model::TemplateEndpointError> {
match self {
TemplateError::Status500 { error } => Some(crate::model::TemplateEndpointError::InternalError { error: error.clone() }),
TemplateError::Status404 { message } => Some(crate::model::TemplateEndpointError::NotFound { message: message.clone() }),
TemplateError::Status504 => Some(crate::model::TemplateEndpointError::GatewayTimeout {}),
TemplateError::Status403 { error } => Some(crate::model::TemplateEndpointError::LimitExceeded { error: error.clone() }),
TemplateError::Status409 { component_id } => Some(crate::model::TemplateEndpointError::AlreadyExists { component_id: component_id.clone() }),
TemplateError::Status401 { error } => Some(crate::model::TemplateEndpointError::Unauthorized { error: error.clone() }),
TemplateError::Status400 { errors } => Some(crate::model::TemplateEndpointError::ArgValidationError { errors: errors.clone() }),
_ => None
}
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct TemplateEndpointErrorNotFoundPayload {
pub message: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct TemplateEndpointErrorLimitExceededPayload {
pub error: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct TemplateEndpointErrorArgValidationErrorPayload {
pub errors: Vec<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct TemplateEndpointErrorInternalErrorPayload {
pub error: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct TemplateEndpointErrorUnauthorizedPayload {
pub error: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct TemplateEndpointErrorAlreadyExistsPayload {
#[serde(rename = "componentId")]
pub component_id: uuid::Uuid,
}
#[async_trait::async_trait]
pub trait Template {
async fn get_template_by_id(&self, template_id: &str, authorization: &str) -> Result<Vec<crate::model::Template>, TemplateError>;
async fn update_template(&self, template_id: &str, template: impl Into<reqwest::Body> + Send, authorization: &str) -> Result<crate::model::Template, TemplateError>;
async fn get_all_templates(&self, project_id: Option<&str>, template_name: Option<&str>, authorization: &str) -> Result<Vec<crate::model::Template>, TemplateError>;
async fn upload_template(&self, field0: crate::model::TemplateQuery, template: impl Into<reqwest::Body> + Send, authorization: &str) -> Result<crate::model::Template, TemplateError>;
async fn download_template(&self, template_id: &str, version: &str, authorization: &str) -> Result<Box<dyn futures_core::Stream<Item = reqwest::Result<bytes::Bytes>> + Send + Sync + Unpin>, TemplateError>;
async fn get_latest_version(&self, template_id: &str, authorization: &str) -> Result<i32, TemplateError>;
}
#[derive(Clone, Debug)]
pub struct TemplateLive {
pub base_url: reqwest::Url,
pub allow_insecure: bool,
}
#[async_trait::async_trait]
impl Template for TemplateLive {
async fn get_template_by_id(&self, template_id: &str, authorization: &str) -> Result<Vec<crate::model::Template>, TemplateError> {
let mut url = self.base_url.clone();
url.path_segments_mut().unwrap()
.push("v1")
.push("templates")
.push(template_id);
let mut headers = reqwest::header::HeaderMap::new();
headers.append("authorization", reqwest::header::HeaderValue::from_str(&format!("{authorization}"))?);
{
let headers_vec: Vec<(&str, String)> = headers.iter().map(|(k, v)| crate::hide_authorization(k, v)).collect();
tracing::info!(method="get", url=url.to_string(), headers=?headers_vec, body="<no_body>", "get_template_by_id");
}
let mut builder = reqwest::Client::builder();
if self.allow_insecure {
builder = builder.danger_accept_invalid_certs(true);
}
let client = builder.build()?;
let result = client
.get(url)
.headers(headers)
.send()
.await?;
match result.status().as_u16() {
200 => {
let body = result.json::<Vec<crate::model::Template>>().await?;
Ok(body)
}
504 => Err(TemplateError::Status504),
404 => {
let body = result.json::<TemplateEndpointErrorNotFoundPayload>().await?;
Err(TemplateError::Status404 { message: body.message })
}
403 => {
let body = result.json::<TemplateEndpointErrorLimitExceededPayload>().await?;
Err(TemplateError::Status403 { error: body.error })
}
400 => {
let body = result.json::<TemplateEndpointErrorArgValidationErrorPayload>().await?;
Err(TemplateError::Status400 { errors: body.errors })
}
500 => {
let body = result.json::<TemplateEndpointErrorInternalErrorPayload>().await?;
Err(TemplateError::Status500 { error: body.error })
}
401 => {
let body = result.json::<TemplateEndpointErrorUnauthorizedPayload>().await?;
Err(TemplateError::Status401 { error: body.error })
}
409 => {
let body = result.json::<TemplateEndpointErrorAlreadyExistsPayload>().await?;
Err(TemplateError::Status409 { component_id: body.component_id })
}
_ => Err(TemplateError::UnexpectedStatus(result.status()))
}
}
async fn update_template(&self, template_id: &str, template: impl Into<reqwest::Body> + Send, authorization: &str) -> Result<crate::model::Template, TemplateError> {
let mut url = self.base_url.clone();
url.path_segments_mut().unwrap()
.push("v1")
.push("templates")
.push(template_id)
.push("upload");
let mut headers = reqwest::header::HeaderMap::new();
headers.append("authorization", reqwest::header::HeaderValue::from_str(&format!("{authorization}"))?);
{
let headers_vec: Vec<(&str, String)> = headers.iter().map(|(k, v)| crate::hide_authorization(k, v)).collect();
tracing::info!(method="put", url=url.to_string(), headers=?headers_vec, body="<custom>", "update_template");
}
let mut builder = reqwest::Client::builder();
if self.allow_insecure {
builder = builder.danger_accept_invalid_certs(true);
}
let client = builder.build()?;
let result = client
.put(url)
.headers(headers)
.body(template)
.send()
.await?;
match result.status().as_u16() {
200 => {
let body = result.json::<crate::model::Template>().await?;
Ok(body)
}
504 => Err(TemplateError::Status504),
404 => {
let body = result.json::<TemplateEndpointErrorNotFoundPayload>().await?;
Err(TemplateError::Status404 { message: body.message })
}
403 => {
let body = result.json::<TemplateEndpointErrorLimitExceededPayload>().await?;
Err(TemplateError::Status403 { error: body.error })
}
400 => {
let body = result.json::<TemplateEndpointErrorArgValidationErrorPayload>().await?;
Err(TemplateError::Status400 { errors: body.errors })
}
500 => {
let body = result.json::<TemplateEndpointErrorInternalErrorPayload>().await?;
Err(TemplateError::Status500 { error: body.error })
}
401 => {
let body = result.json::<TemplateEndpointErrorUnauthorizedPayload>().await?;
Err(TemplateError::Status401 { error: body.error })
}
409 => {
let body = result.json::<TemplateEndpointErrorAlreadyExistsPayload>().await?;
Err(TemplateError::Status409 { component_id: body.component_id })
}
_ => Err(TemplateError::UnexpectedStatus(result.status()))
}
}
async fn get_all_templates(&self, project_id: Option<&str>, template_name: Option<&str>, authorization: &str) -> Result<Vec<crate::model::Template>, TemplateError> {
let mut url = self.base_url.clone();
url.path_segments_mut().unwrap()
.push("v1")
.push("templates");
if let Some(value) = project_id {
url.query_pairs_mut().append_pair("project-id", &format!("{value}"));
}
if let Some(value) = template_name {
url.query_pairs_mut().append_pair("template-name", &format!("{value}"));
}
let mut headers = reqwest::header::HeaderMap::new();
headers.append("authorization", reqwest::header::HeaderValue::from_str(&format!("{authorization}"))?);
{
let headers_vec: Vec<(&str, String)> = headers.iter().map(|(k, v)| crate::hide_authorization(k, v)).collect();
tracing::info!(method="get", url=url.to_string(), headers=?headers_vec, body="<no_body>", "get_all_templates");
}
let mut builder = reqwest::Client::builder();
if self.allow_insecure {
builder = builder.danger_accept_invalid_certs(true);
}
let client = builder.build()?;
let result = client
.get(url)
.headers(headers)
.send()
.await?;
match result.status().as_u16() {
200 => {
let body = result.json::<Vec<crate::model::Template>>().await?;
Ok(body)
}
504 => Err(TemplateError::Status504),
404 => {
let body = result.json::<TemplateEndpointErrorNotFoundPayload>().await?;
Err(TemplateError::Status404 { message: body.message })
}
403 => {
let body = result.json::<TemplateEndpointErrorLimitExceededPayload>().await?;
Err(TemplateError::Status403 { error: body.error })
}
400 => {
let body = result.json::<TemplateEndpointErrorArgValidationErrorPayload>().await?;
Err(TemplateError::Status400 { errors: body.errors })
}
500 => {
let body = result.json::<TemplateEndpointErrorInternalErrorPayload>().await?;
Err(TemplateError::Status500 { error: body.error })
}
401 => {
let body = result.json::<TemplateEndpointErrorUnauthorizedPayload>().await?;
Err(TemplateError::Status401 { error: body.error })
}
409 => {
let body = result.json::<TemplateEndpointErrorAlreadyExistsPayload>().await?;
Err(TemplateError::Status409 { component_id: body.component_id })
}
_ => Err(TemplateError::UnexpectedStatus(result.status()))
}
}
async fn upload_template(&self, field0: crate::model::TemplateQuery, template: impl Into<reqwest::Body> + Send, authorization: &str) -> Result<crate::model::Template, TemplateError> {
let mut url = self.base_url.clone();
url.path_segments_mut().unwrap()
.push("v1")
.push("templates");
let mut headers = reqwest::header::HeaderMap::new();
headers.append("authorization", reqwest::header::HeaderValue::from_str(&format!("{authorization}"))?);
{
let headers_vec: Vec<(&str, String)> = headers.iter().map(|(k, v)| crate::hide_authorization(k, v)).collect();
tracing::info!(method="post", url=url.to_string(), headers=?headers_vec, body="<multipart>", "upload_template");
}
let form = reqwest::multipart::Form::new()
.part("field0", reqwest::multipart::Part::text(serde_json::to_string(&field0).expect("Failed to serialize value to JSON")).mime_str("application/json")?)
.part("template", reqwest::multipart::Part::stream(template).mime_str("application/octet-stream")?);
let mut builder = reqwest::Client::builder();
if self.allow_insecure {
builder = builder.danger_accept_invalid_certs(true);
}
let client = builder.build()?;
let result = client
.post(url)
.headers(headers)
.multipart(form)
.send()
.await?;
match result.status().as_u16() {
200 => {
let body = result.json::<crate::model::Template>().await?;
Ok(body)
}
504 => Err(TemplateError::Status504),
404 => {
let body = result.json::<TemplateEndpointErrorNotFoundPayload>().await?;
Err(TemplateError::Status404 { message: body.message })
}
403 => {
let body = result.json::<TemplateEndpointErrorLimitExceededPayload>().await?;
Err(TemplateError::Status403 { error: body.error })
}
400 => {
let body = result.json::<TemplateEndpointErrorArgValidationErrorPayload>().await?;
Err(TemplateError::Status400 { errors: body.errors })
}
500 => {
let body = result.json::<TemplateEndpointErrorInternalErrorPayload>().await?;
Err(TemplateError::Status500 { error: body.error })
}
401 => {
let body = result.json::<TemplateEndpointErrorUnauthorizedPayload>().await?;
Err(TemplateError::Status401 { error: body.error })
}
409 => {
let body = result.json::<TemplateEndpointErrorAlreadyExistsPayload>().await?;
Err(TemplateError::Status409 { component_id: body.component_id })
}
_ => Err(TemplateError::UnexpectedStatus(result.status()))
}
}
async fn download_template(&self, template_id: &str, version: &str, authorization: &str) -> Result<Box<dyn futures_core::Stream<Item = reqwest::Result<bytes::Bytes>> + Send + Sync + Unpin>, TemplateError> {
let mut url = self.base_url.clone();
url.path_segments_mut().unwrap()
.push("v1")
.push("templates")
.push(template_id)
.push("download");
url.query_pairs_mut().append_pair("version", &format!("{version}"));
let mut headers = reqwest::header::HeaderMap::new();
headers.append("authorization", reqwest::header::HeaderValue::from_str(&format!("{authorization}"))?);
{
let headers_vec: Vec<(&str, String)> = headers.iter().map(|(k, v)| crate::hide_authorization(k, v)).collect();
tracing::info!(method="get", url=url.to_string(), headers=?headers_vec, body="<no_body>", "download_template");
}
let mut builder = reqwest::Client::builder();
if self.allow_insecure {
builder = builder.danger_accept_invalid_certs(true);
}
let client = builder.build()?;
let result = client
.get(url)
.headers(headers)
.send()
.await?;
match result.status().as_u16() {
200 => {
let body = Box::new(result.bytes_stream());
Ok(body)
}
504 => Err(TemplateError::Status504),
404 => {
let body = result.json::<TemplateEndpointErrorNotFoundPayload>().await?;
Err(TemplateError::Status404 { message: body.message })
}
403 => {
let body = result.json::<TemplateEndpointErrorLimitExceededPayload>().await?;
Err(TemplateError::Status403 { error: body.error })
}
400 => {
let body = result.json::<TemplateEndpointErrorArgValidationErrorPayload>().await?;
Err(TemplateError::Status400 { errors: body.errors })
}
500 => {
let body = result.json::<TemplateEndpointErrorInternalErrorPayload>().await?;
Err(TemplateError::Status500 { error: body.error })
}
401 => {
let body = result.json::<TemplateEndpointErrorUnauthorizedPayload>().await?;
Err(TemplateError::Status401 { error: body.error })
}
409 => {
let body = result.json::<TemplateEndpointErrorAlreadyExistsPayload>().await?;
Err(TemplateError::Status409 { component_id: body.component_id })
}
_ => Err(TemplateError::UnexpectedStatus(result.status()))
}
}
async fn get_latest_version(&self, template_id: &str, authorization: &str) -> Result<i32, TemplateError> {
let mut url = self.base_url.clone();
url.path_segments_mut().unwrap()
.push("v1")
.push("templates")
.push(template_id)
.push("latest");
let mut headers = reqwest::header::HeaderMap::new();
headers.append("authorization", reqwest::header::HeaderValue::from_str(&format!("{authorization}"))?);
{
let headers_vec: Vec<(&str, String)> = headers.iter().map(|(k, v)| crate::hide_authorization(k, v)).collect();
tracing::info!(method="get", url=url.to_string(), headers=?headers_vec, body="<no_body>", "get_latest_version");
}
let mut builder = reqwest::Client::builder();
if self.allow_insecure {
builder = builder.danger_accept_invalid_certs(true);
}
let client = builder.build()?;
let result = client
.get(url)
.headers(headers)
.send()
.await?;
match result.status().as_u16() {
200 => {
let body = result.json::<i32>().await?;
Ok(body)
}
504 => Err(TemplateError::Status504),
404 => {
let body = result.json::<TemplateEndpointErrorNotFoundPayload>().await?;
Err(TemplateError::Status404 { message: body.message })
}
403 => {
let body = result.json::<TemplateEndpointErrorLimitExceededPayload>().await?;
Err(TemplateError::Status403 { error: body.error })
}
400 => {
let body = result.json::<TemplateEndpointErrorArgValidationErrorPayload>().await?;
Err(TemplateError::Status400 { errors: body.errors })
}
500 => {
let body = result.json::<TemplateEndpointErrorInternalErrorPayload>().await?;
Err(TemplateError::Status500 { error: body.error })
}
401 => {
let body = result.json::<TemplateEndpointErrorUnauthorizedPayload>().await?;
Err(TemplateError::Status401 { error: body.error })
}
409 => {
let body = result.json::<TemplateEndpointErrorAlreadyExistsPayload>().await?;
Err(TemplateError::Status409 { component_id: body.component_id })
}
_ => Err(TemplateError::UnexpectedStatus(result.status()))
}
}
}