mirror of
https://github.com/sadoyan/aralez.git
synced 2026-10-23 06:01:35 +08:00
Implemented EndpointSlices #55
This commit is contained in:
+25
-16
@@ -1,6 +1,6 @@
|
|||||||
use crate::utils::consul::ConsulService;
|
use crate::utils::consul::ConsulService;
|
||||||
use crate::utils::kuberconsul::match_path;
|
use crate::utils::kuberconsul::match_path;
|
||||||
use crate::utils::kubernetes::KubeEndpoints;
|
use crate::utils::kubernetes::KubeEndpointSliceList;
|
||||||
use crate::utils::structs::{GlobalServiceMapping, InnerMap};
|
use crate::utils::structs::{GlobalServiceMapping, InnerMap};
|
||||||
use ahash::HashMap;
|
use ahash::HashMap;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
@@ -36,7 +36,9 @@ pub struct ConsulServicesInternal {
|
|||||||
#[serde(rename = "aralez.to_https")]
|
#[serde(rename = "aralez.to_https")]
|
||||||
pub to_https: Option<bool>,
|
pub to_https: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ConsulServices = HashMap<String, ConsulServicesInternal>;
|
pub type ConsulServices = HashMap<String, ConsulServicesInternal>;
|
||||||
|
|
||||||
pub async fn for_consul_list(url: &str, token: Option<String>) -> Option<ConsulServices> {
|
pub async fn for_consul_list(url: &str, token: Option<String>) -> Option<ConsulServices> {
|
||||||
if let Some(data) = getfromapi(url, token, "consul").await {
|
if let Some(data) = getfromapi(url, token, "consul").await {
|
||||||
let yo = parse_services(data);
|
let yo = parse_services(data);
|
||||||
@@ -75,6 +77,7 @@ fn parse_services(json: Vec<u8>) -> Result<ConsulServices, serde_json::Error> {
|
|||||||
})
|
})
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn for_consul(url: &str, token: Option<String>, conf: &GlobalServiceMapping) -> Option<DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)>> {
|
pub async fn for_consul(url: &str, token: Option<String>, conf: &GlobalServiceMapping) -> Option<DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)>> {
|
||||||
if let Some(data) = getfromapi(url, token, "consul").await {
|
if let Some(data) = getfromapi(url, token, "consul").await {
|
||||||
let endpoints: Vec<ConsulService> = serde_json::from_slice(&data).ok()?;
|
let endpoints: Vec<ConsulService> = serde_json::from_slice(&data).ok()?;
|
||||||
@@ -103,18 +106,29 @@ pub async fn for_consul(url: &str, token: Option<String>, conf: &GlobalServiceMa
|
|||||||
|
|
||||||
pub async fn for_kuber(url: &str, token: &str, conf: &GlobalServiceMapping) -> Option<DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)>> {
|
pub async fn for_kuber(url: &str, token: &str, conf: &GlobalServiceMapping) -> Option<DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)>> {
|
||||||
if let Some(data) = getfromapi(url, Some(token.to_string()), "kubernetes").await {
|
if let Some(data) = getfromapi(url, Some(token.to_string()), "kubernetes").await {
|
||||||
let endpoints: KubeEndpoints = serde_json::from_slice(&data).ok()?;
|
let slice_list: KubeEndpointSliceList = serde_json::from_slice(&data).ok()?;
|
||||||
let upstreams: DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)> = DashMap::new();
|
let upstreams: DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)> = DashMap::new();
|
||||||
let mut inner_vec = Vec::new();
|
let mut inner_vec = Vec::new();
|
||||||
|
|
||||||
if let Some(subsets) = endpoints.subsets {
|
for slice in slice_list.items {
|
||||||
for subset in subsets {
|
let ports = match &slice.ports {
|
||||||
if let (Some(addresses), Some(ports)) = (subset.addresses, subset.ports) {
|
Some(p) if !p.is_empty() => p,
|
||||||
for addr in addresses {
|
_ => continue,
|
||||||
for port in &ports {
|
};
|
||||||
|
|
||||||
|
for ep in &slice.endpoints {
|
||||||
|
let is_ready = ep.conditions.as_ref().and_then(|c| c.ready).unwrap_or(true);
|
||||||
|
|
||||||
|
if !is_ready {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for addr in &ep.addresses {
|
||||||
|
for port in ports {
|
||||||
|
if let Some(port_num) = port.port {
|
||||||
let to_add = Arc::from(InnerMap {
|
let to_add = Arc::from(InnerMap {
|
||||||
address: Arc::from(addr.ip.as_str()),
|
address: Arc::from(addr.as_str()),
|
||||||
port: port.port,
|
port: port_num,
|
||||||
is_ssl: false,
|
is_ssl: false,
|
||||||
is_http2: false,
|
is_http2: false,
|
||||||
to_https: conf.to_https.unwrap_or(false),
|
to_https: conf.to_https.unwrap_or(false),
|
||||||
@@ -130,6 +144,7 @@ pub async fn for_kuber(url: &str, token: &str, conf: &GlobalServiceMapping) -> O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !inner_vec.is_empty() {
|
if !inner_vec.is_empty() {
|
||||||
match_path(conf, &upstreams, inner_vec);
|
match_path(conf, &upstreams, inner_vec);
|
||||||
return Some(upstreams);
|
return Some(upstreams);
|
||||||
@@ -137,6 +152,7 @@ pub async fn for_kuber(url: &str, token: &str, conf: &GlobalServiceMapping) -> O
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn getfromapi(url: &str, token: Option<String>, provider: &str) -> Option<Vec<u8>> {
|
pub async fn getfromapi(url: &str, token: Option<String>, provider: &str) -> Option<Vec<u8>> {
|
||||||
let (host, port, path, is_tls) = parse_url(&url).ok()?;
|
let (host, port, path, is_tls) = parse_url(&url).ok()?;
|
||||||
|
|
||||||
@@ -226,10 +242,3 @@ fn parse_url(url: &str) -> Result<(&str, u16, &str, bool), &'static str> {
|
|||||||
|
|
||||||
Ok((host, port, uri, is_https))
|
Ok((host, port, uri, is_https))
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn base64_decode(encoded: &str) -> Option<String> {
|
|
||||||
// let decoded_bytes = general_purpose::STANDARD.decode(encoded).unwrap_or_default();
|
|
||||||
// let decoded: Result<HashMap<String, String>, serde_json::Error> = serde_json::from_slice(&decoded_bytes);
|
|
||||||
// println!("Decoded: {:?}", decoded);
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
|
|||||||
+32
-20
@@ -15,25 +15,44 @@ use rustls::crypto::CryptoProvider;
|
|||||||
use tokio::sync::mpsc::Sender;
|
use tokio::sync::mpsc::Sender;
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
pub struct KubeEndpoints {
|
#[serde(rename_all = "camelCase")]
|
||||||
pub subsets: Option<Vec<KubeSubset>>,
|
pub struct KubeEndpointSliceList {
|
||||||
|
#[serde(default)]
|
||||||
|
pub items: Vec<KubeEndpointSlice>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
pub struct KubeSubset {
|
#[serde(rename_all = "camelCase")]
|
||||||
pub addresses: Option<Vec<KubeAddress>>,
|
pub struct KubeEndpointSlice {
|
||||||
pub ports: Option<Vec<KubePort>>,
|
pub ports: Option<Vec<KubePort>>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub endpoints: Vec<KubeEndpoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
pub struct KubeAddress {
|
#[serde(rename_all = "camelCase")]
|
||||||
pub ip: String,
|
pub struct KubeEndpoint {
|
||||||
|
#[serde(default)]
|
||||||
|
pub addresses: Vec<String>,
|
||||||
|
pub conditions: Option<KubeConditions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct KubeConditions {
|
||||||
|
pub ready: Option<bool>,
|
||||||
|
pub serving: Option<bool>,
|
||||||
|
pub terminating: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct KubePort {
|
pub struct KubePort {
|
||||||
pub port: u16,
|
pub name: Option<String>,
|
||||||
|
pub port: Option<u16>,
|
||||||
|
pub protocol: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct KubernetesDiscovery;
|
pub struct KubernetesDiscovery;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -52,7 +71,6 @@ impl ServiceDiscovery for KubernetesDiscovery {
|
|||||||
let num = if end > 0 { rand::rng().random_range(0..end) } else { 0 };
|
let num = if end > 0 { rand::rng().random_range(0..end) } else { 0 };
|
||||||
let server = servers.get(num).unwrap().to_string();
|
let server = servers.get(num).unwrap().to_string();
|
||||||
let path = kuber.tokenpath.unwrap_or_else(|| "/var/run/secrets/kubernetes.io/serviceaccount/token".to_string());
|
let path = kuber.tokenpath.unwrap_or_else(|| "/var/run/secrets/kubernetes.io/serviceaccount/token".to_string());
|
||||||
// let namespace = get_current_namespace().unwrap_or_else(|| "default".to_string());
|
|
||||||
let token = crate::utils::kuberconsul::read_token(path.as_str()).await;
|
let token = crate::utils::kuberconsul::read_token(path.as_str()).await;
|
||||||
|
|
||||||
if CryptoProvider::get_default().is_none() {
|
if CryptoProvider::get_default().is_none() {
|
||||||
@@ -126,7 +144,12 @@ impl ServiceDiscovery for KubernetesDiscovery {
|
|||||||
sheader_list.insert(Arc::from(path_key), server_headers_list);
|
sheader_list.insert(Arc::from(path_key), server_headers_list);
|
||||||
config.server_headers.insert(host_key.clone(), sheader_list);
|
config.server_headers.insert(host_key.clone(), sheader_list);
|
||||||
}
|
}
|
||||||
let url = format!("https://{}/api/v1/namespaces/{}/endpoints/{}", server, update.namespace, update.service_name);
|
|
||||||
|
let url = format!(
|
||||||
|
"https://{}/apis/discovery.k8s.io/v1/namespaces/{}/endpointslices?labelSelector=kubernetes.io%2Fservice-name%3D{}",
|
||||||
|
server, update.namespace, update.service_name
|
||||||
|
);
|
||||||
|
|
||||||
let list = httpclient::for_kuber(&url, &token, &service).await;
|
let list = httpclient::for_kuber(&url, &token, &service).await;
|
||||||
|
|
||||||
if list.is_none() {
|
if list.is_none() {
|
||||||
@@ -142,14 +165,3 @@ impl ServiceDiscovery for KubernetesDiscovery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
fn get_current_namespace() -> Option<String> {
|
|
||||||
let ns_path = "/var/run/secrets/kubernetes.io/serviceaccount/namespace";
|
|
||||||
if Path::new(ns_path).exists() {
|
|
||||||
if let Ok(contents) = fs::read_to_string(ns_path) {
|
|
||||||
return Some(contents.trim().to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
env::var("POD_NAMESPACE").ok()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
Reference in New Issue
Block a user