apisix_admin_client/models/
admin_upstream_requests.rsuse serde::{Deserialize, Serialize, Serializer};
use serde::ser::SerializeSeq;
use serde_json::Value;
use strum_macros::{Display, EnumString};
use crate::models::generate_identifier;
use crate::{Result};
use crate::common::ApisixTimeout;
#[serde_with::skip_serializing_none]
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UpstreamBuilder {
pub id: Option<String>,
pub retries: Option<i32>,
pub retry_timeout: Option<i32>,
pub timeout: Option<ApisixTimeout>,
pub nodes: Option<Value>,
pub service_name: Option<String>,
pub discovery_type: Option<String>,
#[serde(rename = "type")]
pub type_field: Option<UpstreamType>,
pub name: Option<String>,
pub desc: Option<String>,
pub scheme: Option<UpstreamSchema>,
}
impl UpstreamBuilder {
pub fn new() -> Self {
UpstreamRequest::default().into()
}
pub fn id(mut self, id: String) -> Self {
self.id = Some(id);
self
}
pub fn u_type(mut self, u_type: UpstreamType) -> Self {
self.type_field = Some(u_type);
self
}
pub fn nodes(mut self, nodes: Value) -> Self {
self.nodes = Some(nodes);
self
}
pub fn service_name(mut self, service_name: String) -> Self {
self.service_name = Some(service_name);
self.discovery_type = Some("eureka".to_string()); self.nodes = None; self
}
pub fn discovery_type(mut self, discovery_type: String) -> Self {
self.discovery_type = Some(discovery_type);
self
}
pub fn retries(mut self, retries: i32) -> Self {
self.retries = Some(retries);
self
}
pub fn retry_timeout(mut self, retry_timeout: i32) -> Self {
self.retry_timeout = Some(retry_timeout);
self
}
pub fn timeout(mut self, timeout: ApisixTimeout) -> Self {
self.timeout = Some(timeout);
self
}
pub fn name(mut self, name: String) -> Self {
self.name = Some(name);
self
}
pub fn desc(mut self, desc: String) -> Self {
self.desc = Some(desc);
self
}
pub fn schema(mut self, scheme: UpstreamSchema) -> Self {
self.scheme = Some(scheme);
self
}
pub fn build(&self) -> Result<UpstreamRequest> {
Ok(UpstreamRequest {
id: self.id.clone(),
retries: self.retries.clone(),
retry_timeout: self.retry_timeout.clone(),
timeout: self.timeout.clone(),
nodes: self.nodes.clone(),
service_name: self.service_name.clone(),
discovery_type: self.discovery_type.clone(),
type_field: self.type_field.clone(),
name: self.name.clone(),
desc: self.desc.clone(),
scheme: self.scheme.clone(),
})
}
}
#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UpstreamRequest {
pub id: Option<String>,
pub retries: Option<i32>,
pub retry_timeout: Option<i32>,
pub timeout: Option<ApisixTimeout>,
pub nodes: Option<Value>,
pub service_name: Option<String>,
pub discovery_type: Option<String>,
#[serde(rename = "type")]
pub type_field: Option<UpstreamType>,
pub name: Option<String>,
pub desc: Option<String>,
pub scheme: Option<UpstreamSchema>,
}
impl Default for UpstreamRequest {
fn default() -> Self {
let nodes = r#"
{
"localhost:9000": 1
}"#;
let nodes = serde_json::from_str(nodes).unwrap();
UpstreamRequest {
id: Some(generate_identifier()),
retries: Some(0_i32), retry_timeout: Some(0_i32),
timeout: None,
nodes: Some(nodes),
service_name: None,
discovery_type: None,
type_field: None,
name: None,
desc: None,
scheme: Some(UpstreamSchema::http),
}
}
}
impl From<UpstreamRequest> for UpstreamBuilder {
fn from(upstream: UpstreamRequest) -> Self {
UpstreamBuilder {
id: upstream.id,
retries: upstream.retries,
retry_timeout: upstream.retry_timeout,
timeout: upstream.timeout,
nodes: upstream.nodes,
service_name: upstream.service_name,
discovery_type: upstream.discovery_type,
type_field: upstream.type_field,
name: upstream.name,
desc: upstream.desc,
scheme: upstream.scheme,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Display, EnumString)]
#[allow(non_camel_case_types)]
#[strum(ascii_case_insensitive)]
#[non_exhaustive]
pub enum UpstreamType {
roundrobin,
chash,
ewma,
least_conn,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Display, EnumString)]
#[allow(non_camel_case_types)]
#[strum(ascii_case_insensitive)]
#[non_exhaustive]
pub enum UpstreamTypeChashAuxiliary {
vars,
header,
cookie,
consumer,
}
impl From<String> for UpstreamTypeChashAuxiliary {
fn from(value: String) -> Self {
match value.to_uppercase().as_str() {
"vars" => UpstreamTypeChashAuxiliary::vars,
"header" => UpstreamTypeChashAuxiliary::header,
"cookie" => UpstreamTypeChashAuxiliary::cookie,
"consumer" => UpstreamTypeChashAuxiliary::consumer,
_ => UpstreamTypeChashAuxiliary::vars
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Display, EnumString)]
#[allow(non_camel_case_types)]
#[strum(ascii_case_insensitive)]
#[non_exhaustive]
pub enum UpstreamSchema {
http,
https,
grpc,
grpcs,
tcp,
udp,
tls
}
#[cfg(test)]
mod tests {
use serde_json::{to_string, to_string_pretty};
use super::*;
use tracing::{error, info};
use tracing_test::traced_test;
use crate::models::admin_upstream_requests::UpstreamType;
#[traced_test]
#[tokio::test]
async fn test_generate_upstream_request() {
let nodes = r#"
{
"localhost:9000": 1
}"#;
let nodes = serde_json::from_str(nodes).unwrap();
let upstream_req = UpstreamBuilder::new()
.id("test_upstream".to_string())
.name("Test Upstream".to_string())
.desc("Test Upstream Description".to_string())
.schema(UpstreamSchema::https)
.u_type(UpstreamType::roundrobin)
.nodes(nodes)
.retries(3)
.retry_timeout(5)
.timeout(ApisixTimeout { connect: Some(0.5), send: Some(0.5), read: Some(0.5) })
.build().unwrap();
info!("Upstream Request: {:?}", to_string(&upstream_req));
assert!(true)
}
}