mirror of
https://github.com/sadoyan/aralez.git
synced 2026-10-22 21:51:35 +08:00
Rewrite of Consul integration.
This commit is contained in:
Generated
+1
-1
@@ -138,7 +138,7 @@ checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aralez"
|
name = "aralez"
|
||||||
version = "0.92.19"
|
version = "0.93.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "aralez"
|
name = "aralez"
|
||||||
version = "0.92.19"
|
version = "0.93.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
description = "Reverse proxy built on top of Cloudflare's Pingora"
|
description = "Reverse proxy built on top of Cloudflare's Pingora"
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
job "apache" {
|
||||||
|
meta {
|
||||||
|
uuid = uuidv4()
|
||||||
|
}
|
||||||
|
datacenters = ["eu-ams-1"]
|
||||||
|
type = "service"
|
||||||
|
constraint {
|
||||||
|
attribute = node.unique.name
|
||||||
|
operator = "regexp"
|
||||||
|
value = "consul[0-9]"
|
||||||
|
}
|
||||||
|
update {
|
||||||
|
max_parallel = 1
|
||||||
|
min_healthy_time = "10s"
|
||||||
|
healthy_deadline = "3m"
|
||||||
|
progress_deadline = "10m"
|
||||||
|
auto_revert = false
|
||||||
|
canary = 0
|
||||||
|
}
|
||||||
|
migrate {
|
||||||
|
max_parallel = 1
|
||||||
|
health_check = "checks"
|
||||||
|
min_healthy_time = "10s"
|
||||||
|
healthy_deadline = "5m"
|
||||||
|
}
|
||||||
|
group "Apache" {
|
||||||
|
network {
|
||||||
|
port "apache" { to = 80 }
|
||||||
|
}
|
||||||
|
constraint {
|
||||||
|
operator = "distinct_hosts"
|
||||||
|
value = "true"
|
||||||
|
}
|
||||||
|
count = 3
|
||||||
|
restart {
|
||||||
|
attempts = 2
|
||||||
|
interval = "30m"
|
||||||
|
delay = "15s"
|
||||||
|
mode = "fail"
|
||||||
|
}
|
||||||
|
task "health" {
|
||||||
|
service {
|
||||||
|
port = "apache"
|
||||||
|
tags = [
|
||||||
|
"aralez.service=yes",
|
||||||
|
"aralez.host=apache.blablabla.com",
|
||||||
|
"aralez.path=/"
|
||||||
|
]
|
||||||
|
check {
|
||||||
|
type = "http"
|
||||||
|
port = "apache"
|
||||||
|
path = "/"
|
||||||
|
interval = "5s"
|
||||||
|
timeout = "2s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "httpd:latest"
|
||||||
|
force_pull = true
|
||||||
|
ports = ["apache"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
job "echo" {
|
||||||
|
meta {
|
||||||
|
uuid = uuidv4()
|
||||||
|
}
|
||||||
|
datacenters = ["eu-ams-1"]
|
||||||
|
type = "service"
|
||||||
|
constraint {
|
||||||
|
attribute = node.unique.name
|
||||||
|
operator = "regexp"
|
||||||
|
value = "consul[0-9]"
|
||||||
|
}
|
||||||
|
update {
|
||||||
|
max_parallel = 1
|
||||||
|
min_healthy_time = "10s"
|
||||||
|
healthy_deadline = "3m"
|
||||||
|
progress_deadline = "10m"
|
||||||
|
auto_revert = false
|
||||||
|
canary = 0
|
||||||
|
}
|
||||||
|
migrate {
|
||||||
|
max_parallel = 1
|
||||||
|
health_check = "checks"
|
||||||
|
min_healthy_time = "10s"
|
||||||
|
healthy_deadline = "5m"
|
||||||
|
}
|
||||||
|
group "Echo" {
|
||||||
|
network {
|
||||||
|
port "echo" { to = 80 }
|
||||||
|
}
|
||||||
|
constraint {
|
||||||
|
operator = "distinct_hosts"
|
||||||
|
value = "true"
|
||||||
|
}
|
||||||
|
count = 3
|
||||||
|
restart {
|
||||||
|
attempts = 2
|
||||||
|
interval = "30m"
|
||||||
|
delay = "15s"
|
||||||
|
mode = "fail"
|
||||||
|
}
|
||||||
|
task "server" {
|
||||||
|
service {
|
||||||
|
port = "echo"
|
||||||
|
tags = [
|
||||||
|
"aralez.service=yes",
|
||||||
|
"aralez.host=echo.blablabla.com",
|
||||||
|
"aralez.path=/",
|
||||||
|
"aralez.rate=100",
|
||||||
|
"aralez.4xx_rate=50",
|
||||||
|
"aralez.to_https=false",
|
||||||
|
"aralez.client_headers=WyJYLUVjaG8tU2VuZDpIb29vb29vb29vb29vIiwiWC1FY2hvLVJlY3Y6WW9vb29vb29vb29vbyJdCg==",
|
||||||
|
"aralez.server_headers=WyJYLVByb3h5LUZyb206IEFyYWxleiIsIlgtQmFyaS1MdXlzOiBBcGVyIEphbiIsIlgtQW5rYXAtSGVhZGVyOiBCZXNhbXAgQW5rYXAgSGVhZGVyIl0K"
|
||||||
|
]
|
||||||
|
check {
|
||||||
|
type = "http"
|
||||||
|
port = "echo"
|
||||||
|
path = "/"
|
||||||
|
interval = "5s"
|
||||||
|
timeout = "2s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "ealen/echo-server:latest"
|
||||||
|
force_pull = true
|
||||||
|
ports = ["echo"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
job "nginx" {
|
||||||
|
meta {
|
||||||
|
uuid = uuidv4()
|
||||||
|
}
|
||||||
|
datacenters = ["eu-ams-1"]
|
||||||
|
type = "service"
|
||||||
|
constraint {
|
||||||
|
attribute = node.unique.name
|
||||||
|
operator = "regexp"
|
||||||
|
value = "consul[0-9]"
|
||||||
|
}
|
||||||
|
update {
|
||||||
|
max_parallel = 1
|
||||||
|
min_healthy_time = "10s"
|
||||||
|
healthy_deadline = "3m"
|
||||||
|
progress_deadline = "10m"
|
||||||
|
auto_revert = false
|
||||||
|
canary = 0
|
||||||
|
}
|
||||||
|
migrate {
|
||||||
|
max_parallel = 1
|
||||||
|
health_check = "checks"
|
||||||
|
min_healthy_time = "10s"
|
||||||
|
healthy_deadline = "5m"
|
||||||
|
}
|
||||||
|
group "NginX" {
|
||||||
|
network {
|
||||||
|
port "nginx" { to = 80 }
|
||||||
|
}
|
||||||
|
constraint {
|
||||||
|
operator = "distinct_hosts"
|
||||||
|
value = "true"
|
||||||
|
}
|
||||||
|
count = 3
|
||||||
|
restart {
|
||||||
|
attempts = 2
|
||||||
|
interval = "30m"
|
||||||
|
delay = "15s"
|
||||||
|
mode = "fail"
|
||||||
|
}
|
||||||
|
task "server" {
|
||||||
|
service {
|
||||||
|
port = "nginx"
|
||||||
|
tags = [
|
||||||
|
"aralez.service=yes",
|
||||||
|
"aralez.host=nginx.blablabla.com",
|
||||||
|
"aralez.path=/",
|
||||||
|
"aralez.rate=20",
|
||||||
|
"aralez.4xx_rate=10",
|
||||||
|
"aralez.to_https=true",
|
||||||
|
"aralez.auth=basic root:toor",
|
||||||
|
"aralez.client_headers=WwogICAgIlgtU29tZS1IZWFkZXI6QUFBQUFBQUFBQUFBQUFBIiwKICAgICJYLUVtb3MtSGVhZGVyOlpaWlpaWlpaWlpaWlpaWiIsCiAgICAiWC1PdGhlci1oZWFkZXI6VmF5VmF5VmF5IiwKICAgICJYLVJlaHRvLWhlYWRlcjpaYXlaYXlaYXkiCl0KCg==",
|
||||||
|
"aralez.server_headers=WyJYLVByb3h5LUZyb206IEFyYWxleiIsIlgtQmFyaS1MdXlzOiBBcGVyIEphbiIsIlgtQW5rYXAtSGVhZGVyOiBCZXNhbXAgQW5rYXAgSGVhZGVyIl0K"
|
||||||
|
]
|
||||||
|
check {
|
||||||
|
type = "http"
|
||||||
|
port = "nginx"
|
||||||
|
path = "/"
|
||||||
|
interval = "5s"
|
||||||
|
timeout = "2s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "nginx:latest"
|
||||||
|
force_pull = true
|
||||||
|
ports = ["nginx"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
pub mod consul;
|
||||||
pub mod discovery;
|
pub mod discovery;
|
||||||
mod filewatch;
|
mod filewatch;
|
||||||
pub mod fordebug;
|
pub mod fordebug;
|
||||||
@@ -8,6 +9,7 @@ pub mod healthcheck;
|
|||||||
pub mod httpclient;
|
pub mod httpclient;
|
||||||
pub mod jwt;
|
pub mod jwt;
|
||||||
pub mod kuberconsul;
|
pub mod kuberconsul;
|
||||||
|
pub mod kubernetes;
|
||||||
pub mod kubewatcher;
|
pub mod kubewatcher;
|
||||||
pub mod lazylock;
|
pub mod lazylock;
|
||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
use crate::utils::httpclient;
|
||||||
|
use crate::utils::kuberconsul::{list_to_upstreams, ServiceDiscovery};
|
||||||
|
use crate::utils::parceyaml::build_headers;
|
||||||
|
use crate::utils::structs::{Configuration, GlobalServiceMapping, UpstreamsDashMap};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use dashmap::DashMap;
|
||||||
|
use pingora::prelude::sleep;
|
||||||
|
use rand::RngExt;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::env;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct ConsulService {
|
||||||
|
#[serde(rename = "Address")]
|
||||||
|
pub address: String,
|
||||||
|
#[serde(rename = "ServicePort")]
|
||||||
|
pub port: u16,
|
||||||
|
}
|
||||||
|
pub struct ConsulDiscovery;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ServiceDiscovery for ConsulDiscovery {
|
||||||
|
async fn fetch_upstreams(&self, config: Arc<Configuration>, toreturn: Sender<Configuration>) {
|
||||||
|
loop {
|
||||||
|
let upstreams = UpstreamsDashMap::new();
|
||||||
|
|
||||||
|
if let Some(consul) = config.consul.clone() {
|
||||||
|
let servers = consul.servers.unwrap_or_else(|| {
|
||||||
|
vec![format!(
|
||||||
|
"{}:{}",
|
||||||
|
env::var("CONSUL_SERVICE_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()),
|
||||||
|
env::var("CONSUL_SERVICE_PORT").unwrap_or_else(|_| "0".to_string())
|
||||||
|
)]
|
||||||
|
});
|
||||||
|
let end = servers.len().saturating_sub(1);
|
||||||
|
let num = if end > 0 { rand::rng().random_range(0..end) } else { 0 };
|
||||||
|
let consul_data = servers.get(num).unwrap().to_string();
|
||||||
|
let ss = format!("{}/v1/catalog/service/", consul_data);
|
||||||
|
let dc = format!("{}/v1/catalog/services?filter=%22aralez.service=yes%22+in+ServiceTags", consul_data);
|
||||||
|
|
||||||
|
if let Some(infolist) = httpclient::for_consul_list(dc.as_str(), consul.token.clone()).await {
|
||||||
|
for (k, v) in infolist {
|
||||||
|
let client_header_map: DashMap<Arc<str>, Vec<(String, Arc<str>)>> = DashMap::new();
|
||||||
|
let mut client_header_list = Vec::new();
|
||||||
|
build_headers(&v.client_headers, config.as_ref(), &mut client_header_list);
|
||||||
|
|
||||||
|
let sever_header_map: DashMap<Arc<str>, Vec<(String, Arc<str>)>> = DashMap::new();
|
||||||
|
let mut server_header_list = Vec::new();
|
||||||
|
build_headers(&v.server_headers, config.as_ref(), &mut server_header_list);
|
||||||
|
|
||||||
|
if !client_header_list.is_empty() {
|
||||||
|
let path_key = v.path.clone();
|
||||||
|
client_header_map.insert(Arc::from(path_key), client_header_list);
|
||||||
|
config.client_headers.insert(Arc::from(v.host.clone()), client_header_map);
|
||||||
|
}
|
||||||
|
if !server_header_list.is_empty() {
|
||||||
|
let path_key = v.path.clone();
|
||||||
|
sever_header_map.insert(Arc::from(path_key), server_header_list);
|
||||||
|
config.server_headers.insert(Arc::from(v.host.clone()), sever_header_map);
|
||||||
|
}
|
||||||
|
let pref = format!("{}{}", ss, k);
|
||||||
|
let gsm = &GlobalServiceMapping {
|
||||||
|
upstream: k.clone(),
|
||||||
|
hostname: v.host.clone(),
|
||||||
|
path: Some(v.path),
|
||||||
|
to_https: v.to_https,
|
||||||
|
redirect_to: v.redirect,
|
||||||
|
authorization: v.auth,
|
||||||
|
rate_limit: v.rate,
|
||||||
|
x4xx_limit: v.xrate,
|
||||||
|
client_headers: v.client_headers,
|
||||||
|
server_headers: v.server_headers,
|
||||||
|
};
|
||||||
|
|
||||||
|
let list = httpclient::for_consul(pref.as_str(), consul.token.clone(), gsm).await;
|
||||||
|
list_to_upstreams(list, &upstreams, gsm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(lt) = crate::utils::kuberconsul::clone_compare(&upstreams, &config).await {
|
||||||
|
let _ = toreturn.send(lt).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(Duration::from_secs(5)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
|
use crate::utils::consul::ConsulDiscovery;
|
||||||
use crate::utils::filewatch;
|
use crate::utils::filewatch;
|
||||||
use crate::utils::kuberconsul::{ConsulDiscovery, KubernetesDiscovery, ServiceDiscovery};
|
use crate::utils::kuberconsul::ServiceDiscovery;
|
||||||
|
use crate::utils::kubernetes::KubernetesDiscovery;
|
||||||
use crate::utils::structs::{Configuration, UpstreamsDashMap};
|
use crate::utils::structs::{Configuration, UpstreamsDashMap};
|
||||||
use crate::web::webserver;
|
use crate::web::webserver;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|||||||
+97
-6
@@ -1,33 +1,117 @@
|
|||||||
use crate::utils::kuberconsul::{match_path, ConsulService, KubeEndpoints};
|
use crate::utils::consul::ConsulService;
|
||||||
|
use crate::utils::kuberconsul::match_path;
|
||||||
|
use crate::utils::kubernetes::KubeEndpoints;
|
||||||
use crate::utils::structs::{GlobalServiceMapping, InnerMap};
|
use crate::utils::structs::{GlobalServiceMapping, InnerMap};
|
||||||
|
use ahash::HashMap;
|
||||||
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
|
use log::warn;
|
||||||
use pingora_core::connectors::http::Connector;
|
use pingora_core::connectors::http::Connector;
|
||||||
use pingora_core::listeners::ALPN;
|
use pingora_core::listeners::ALPN;
|
||||||
use pingora_core::prelude::HttpPeer;
|
use pingora_core::prelude::HttpPeer;
|
||||||
use pingora_http::RequestHeader;
|
use pingora_http::RequestHeader;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::{Arc, LazyLock};
|
use std::sync::{Arc, LazyLock};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub static CONNECTOR: LazyLock<Connector> = LazyLock::new(|| Connector::new(None));
|
pub static CONNECTOR: LazyLock<Connector> = LazyLock::new(|| Connector::new(None));
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct ConsulServicesInternal {
|
||||||
|
#[serde(rename = "aralez.host")]
|
||||||
|
pub host: String,
|
||||||
|
#[serde(rename = "aralez.path")]
|
||||||
|
pub path: String,
|
||||||
|
#[serde(rename = "aralez.auth")]
|
||||||
|
pub auth: Option<String>,
|
||||||
|
#[serde(rename = "aralez.redirect")]
|
||||||
|
pub redirect: Option<String>,
|
||||||
|
#[serde(rename = "aralez.rate")]
|
||||||
|
pub rate: Option<isize>,
|
||||||
|
#[serde(rename = "aralez.4xx_rate")]
|
||||||
|
pub xrate: Option<u32>,
|
||||||
|
#[serde(rename = "aralez.client_headers")]
|
||||||
|
pub client_headers: Option<Vec<String>>,
|
||||||
|
#[serde(rename = "aralez.server_headers")]
|
||||||
|
pub server_headers: Option<Vec<String>>,
|
||||||
|
#[serde(rename = "aralez.to_https")]
|
||||||
|
pub to_https: Option<bool>,
|
||||||
|
}
|
||||||
|
pub type ConsulServices = HashMap<String, ConsulServicesInternal>;
|
||||||
|
pub async fn for_consul_list(url: &str, token: Option<String>) -> Option<ConsulServices> {
|
||||||
|
if let Some(data) = getfromapi(url, token, "consul").await {
|
||||||
|
let yo = parse_services(data);
|
||||||
|
if let Ok(y) = yo {
|
||||||
|
return Some(y);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_services(json: Vec<u8>) -> Result<ConsulServices, serde_json::Error> {
|
||||||
|
let raw: HashMap<String, Vec<String>> = serde_json::from_slice(&json)?;
|
||||||
|
Ok(raw
|
||||||
|
.into_iter()
|
||||||
|
.map(|(service, tags)| {
|
||||||
|
let mut internal = ConsulServicesInternal::default();
|
||||||
|
for tag in tags {
|
||||||
|
if let Some((key, value)) = tag.split_once('=') {
|
||||||
|
match key {
|
||||||
|
"aralez.host" => internal.host = value.to_string(),
|
||||||
|
"aralez.path" => internal.path = value.to_string(),
|
||||||
|
"aralez.rate" => internal.rate = value.parse::<isize>().ok(),
|
||||||
|
"aralez.4xx_rate" => internal.xrate = value.parse::<u32>().ok(),
|
||||||
|
"aralez.to_https" => internal.to_https = value.parse::<bool>().ok(),
|
||||||
|
"aralez.auth" => internal.auth = Option::from(value.to_string()),
|
||||||
|
"aralez.redirect" => internal.redirect = Option::from(value.to_string()),
|
||||||
|
"aralez.client_headers" => {
|
||||||
|
let decoded_bytes = general_purpose::STANDARD.decode(value).unwrap_or_default();
|
||||||
|
let decoded: Result<Vec<String>, serde_json::Error> = serde_json::from_slice(&decoded_bytes);
|
||||||
|
match decoded {
|
||||||
|
Ok(dd) => internal.client_headers = Some(dd),
|
||||||
|
Err(er) => {
|
||||||
|
warn!("Could not decode client headers: {}", er);
|
||||||
|
internal.client_headers = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"aralez.server_headers" => {
|
||||||
|
let decoded_bytes = general_purpose::STANDARD.decode(value).unwrap_or_default();
|
||||||
|
let decoded: Result<Vec<String>, serde_json::Error> = serde_json::from_slice(&decoded_bytes);
|
||||||
|
match decoded {
|
||||||
|
Ok(dd) => internal.server_headers = Some(dd),
|
||||||
|
Err(er) => {
|
||||||
|
warn!("Could not decode server headers: {}", er);
|
||||||
|
internal.server_headers = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(service, internal)
|
||||||
|
})
|
||||||
|
.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()?;
|
||||||
let mut inner_vec = Vec::new();
|
let mut inner_vec = Vec::new();
|
||||||
let upstreams: DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)> = DashMap::new();
|
let upstreams: DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)> = DashMap::new();
|
||||||
for subsets in endpoints {
|
for subsets in endpoints {
|
||||||
let addr = subsets.tagged_addresses.get("lan_ipv4").unwrap().address.clone();
|
|
||||||
let prt = subsets.tagged_addresses.get("lan_ipv4").unwrap().port;
|
|
||||||
let to_add = Arc::from(InnerMap {
|
let to_add = Arc::from(InnerMap {
|
||||||
address: Arc::from(&*addr),
|
address: Arc::from(&*subsets.address),
|
||||||
port: prt,
|
port: subsets.port,
|
||||||
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),
|
||||||
rate_limit: conf.rate_limit,
|
rate_limit: conf.rate_limit,
|
||||||
x4xx_limit: conf.x4xx_limit,
|
x4xx_limit: conf.x4xx_limit,
|
||||||
redirect_to: None,
|
redirect_to: conf.redirect_to.clone().map(Arc::<str>::from),
|
||||||
healthcheck: None,
|
healthcheck: None,
|
||||||
authorization: None,
|
authorization: None,
|
||||||
});
|
});
|
||||||
@@ -164,3 +248,10 @@ 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
|
||||||
|
// }
|
||||||
|
|||||||
+2
-217
@@ -1,63 +1,13 @@
|
|||||||
use crate::utils::httpclient;
|
|
||||||
use crate::utils::kubewatcher::{start_ingress_watcher_with_config, AralezRouteUpdate};
|
|
||||||
use crate::utils::parceyaml::build_headers;
|
|
||||||
use crate::utils::structs::{Configuration, GlobalServiceMapping, InnerMap, UpstreamsDashMap};
|
use crate::utils::structs::{Configuration, GlobalServiceMapping, InnerMap, UpstreamsDashMap};
|
||||||
use crate::utils::tools::{clone_dashmap_into, compare_dashmaps, print_upstreams};
|
use crate::utils::tools::{clone_dashmap_into, compare_dashmaps, print_upstreams};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use log::error;
|
|
||||||
use pingora::prelude::sleep;
|
|
||||||
use rand::RngExt;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
|
||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
use rustls::crypto::ring::default_provider;
|
|
||||||
use rustls::crypto::CryptoProvider;
|
|
||||||
use tokio::sync::mpsc::Sender;
|
use tokio::sync::mpsc::Sender;
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
|
||||||
pub struct KubeEndpoints {
|
|
||||||
pub subsets: Option<Vec<KubeSubset>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
|
||||||
pub struct KubeSubset {
|
|
||||||
pub addresses: Option<Vec<KubeAddress>>,
|
|
||||||
pub ports: Option<Vec<KubePort>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
|
||||||
pub struct KubeAddress {
|
|
||||||
pub ip: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
|
||||||
pub struct KubePort {
|
|
||||||
pub port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct ConsulService {
|
|
||||||
#[serde(rename = "ServiceTaggedAddresses")]
|
|
||||||
pub tagged_addresses: HashMap<String, ConsulTaggedAddress>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct ConsulTaggedAddress {
|
|
||||||
#[serde(rename = "Address")]
|
|
||||||
pub address: String,
|
|
||||||
#[serde(rename = "Port")]
|
|
||||||
pub port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn list_to_upstreams(lt: Option<DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)>>, upstreams: &UpstreamsDashMap, i: &GlobalServiceMapping) {
|
pub fn list_to_upstreams(lt: Option<DashMap<Arc<str>, (Vec<Arc<InnerMap>>, AtomicUsize)>>, upstreams: &UpstreamsDashMap, i: &GlobalServiceMapping) {
|
||||||
if let Some(list) = lt {
|
if let Some(list) = lt {
|
||||||
@@ -80,7 +30,7 @@ pub fn match_path(conf: &GlobalServiceMapping, upstreams: &DashMap<Arc<str>, (Ve
|
|||||||
upstreams.insert(Arc::from(path), (values, AtomicUsize::new(0)));
|
upstreams.insert(Arc::from(path), (values, AtomicUsize::new(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_token(path: &str) -> String {
|
pub async fn read_token(path: &str) -> String {
|
||||||
let mut file = File::open(path).await.unwrap();
|
let mut file = File::open(path).await.unwrap();
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
file.read_to_string(&mut contents).await.unwrap();
|
file.read_to_string(&mut contents).await.unwrap();
|
||||||
@@ -92,172 +42,7 @@ pub trait ServiceDiscovery {
|
|||||||
async fn fetch_upstreams(&self, config: Arc<Configuration>, toreturn: Sender<Configuration>);
|
async fn fetch_upstreams(&self, config: Arc<Configuration>, toreturn: Sender<Configuration>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct KubernetesDiscovery;
|
pub async fn clone_compare(upstreams: &UpstreamsDashMap, config: &Arc<Configuration>) -> Option<Configuration> {
|
||||||
pub struct ConsulDiscovery;
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl ServiceDiscovery for KubernetesDiscovery {
|
|
||||||
async fn fetch_upstreams(&self, config: Arc<Configuration>, toreturn: Sender<Configuration>) {
|
|
||||||
if let Some(kuber) = config.kubernetes.clone() {
|
|
||||||
let servers = kuber.servers.unwrap_or_else(|| {
|
|
||||||
vec![format!(
|
|
||||||
"{}:{}",
|
|
||||||
env::var("KUBERNETES_SERVICE_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()),
|
|
||||||
env::var("KUBERNETES_SERVICE_PORT_HTTPS").unwrap_or_else(|_| "0".to_string())
|
|
||||||
)]
|
|
||||||
});
|
|
||||||
|
|
||||||
let end = servers.len().saturating_sub(1);
|
|
||||||
let num = if end > 0 { rand::rng().random_range(0..end) } else { 0 };
|
|
||||||
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 namespace = get_current_namespace().unwrap_or_else(|| "default".to_string());
|
|
||||||
let token = read_token(path.as_str()).await;
|
|
||||||
|
|
||||||
if CryptoProvider::get_default().is_none() {
|
|
||||||
default_provider().install_default().expect("Failed to install rustls crypto provider");
|
|
||||||
}
|
|
||||||
|
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::channel::<AralezRouteUpdate>(100);
|
|
||||||
let srv = server.clone();
|
|
||||||
let tok = token.clone();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
if let Err(e) = start_ingress_watcher_with_config(srv.as_str(), tok.as_str(), tx, "aralez").await {
|
|
||||||
error!("Fatal watcher error: {:?}", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let upstreams = UpstreamsDashMap::new();
|
|
||||||
|
|
||||||
while let Some(update) = rx.recv().await {
|
|
||||||
let host_key: Arc<str> = Arc::from(update.host.as_str());
|
|
||||||
|
|
||||||
if update.is_deleted {
|
|
||||||
upstreams.remove(&host_key);
|
|
||||||
config.client_headers.remove(&host_key);
|
|
||||||
} else {
|
|
||||||
let service = GlobalServiceMapping {
|
|
||||||
upstream: update.service_name.clone(),
|
|
||||||
hostname: update.host.clone(),
|
|
||||||
path: Some(update.path.clone()),
|
|
||||||
to_https: None,
|
|
||||||
sticky_sessions: update.sticky_sessions,
|
|
||||||
rate_limit: update.rate_limit,
|
|
||||||
x4xx_limit: update.x4xx_limit,
|
|
||||||
client_headers: None,
|
|
||||||
server_headers: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let cheader_list: DashMap<Arc<str>, Vec<(String, Arc<str>)>> = DashMap::new();
|
|
||||||
let sheader_list: DashMap<Arc<str>, Vec<(String, Arc<str>)>> = DashMap::new();
|
|
||||||
|
|
||||||
let mut client_headers_list = Vec::new();
|
|
||||||
let mut server_headers_list = Vec::new();
|
|
||||||
|
|
||||||
let mut chl: Option<Vec<String>> = None;
|
|
||||||
let mut shl: Option<Vec<String>> = None;
|
|
||||||
|
|
||||||
if let Some(hdr) = service.client_headers.as_ref() {
|
|
||||||
chl.get_or_insert_with(Vec::new).extend(hdr.iter().cloned());
|
|
||||||
}
|
|
||||||
if let Some(hdr) = service.server_headers.as_ref() {
|
|
||||||
shl.get_or_insert_with(Vec::new).extend(hdr.iter().cloned());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ch) = update.client_headers {
|
|
||||||
chl.get_or_insert_with(Vec::new).extend(ch);
|
|
||||||
}
|
|
||||||
if let Some(hdr) = update.server_headers.as_ref() {
|
|
||||||
shl.get_or_insert_with(Vec::new).extend(hdr.iter().cloned());
|
|
||||||
}
|
|
||||||
|
|
||||||
build_headers(&chl, config.as_ref(), &mut client_headers_list);
|
|
||||||
if !client_headers_list.is_empty() {
|
|
||||||
let path_key = service.path.as_deref().unwrap_or("/");
|
|
||||||
cheader_list.insert(Arc::from(path_key), client_headers_list);
|
|
||||||
config.client_headers.insert(host_key.clone(), cheader_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
build_headers(&shl, config.as_ref(), &mut server_headers_list);
|
|
||||||
if !server_headers_list.is_empty() {
|
|
||||||
let path_key = service.path.as_deref().unwrap_or("/");
|
|
||||||
sheader_list.insert(Arc::from(path_key), server_headers_list);
|
|
||||||
config.server_headers.insert(host_key.clone(), sheader_list);
|
|
||||||
}
|
|
||||||
let url = format!("https://{}/api/v1/namespaces/{}/endpoints/{}", server, namespace, update.service_name);
|
|
||||||
let list = httpclient::for_kuber(&url, &token, &service).await;
|
|
||||||
|
|
||||||
if list.is_none() {
|
|
||||||
error!("Endpoint URL: {} returned empty/invalid response", url);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_to_upstreams(list, &upstreams, &service);
|
|
||||||
}
|
|
||||||
if let Some(lt) = clone_compare(&upstreams, &config).await {
|
|
||||||
let _ = toreturn.send(lt).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl ServiceDiscovery for ConsulDiscovery {
|
|
||||||
async fn fetch_upstreams(&self, config: Arc<Configuration>, toreturn: Sender<Configuration>) {
|
|
||||||
loop {
|
|
||||||
let upstreams = UpstreamsDashMap::new();
|
|
||||||
|
|
||||||
if let Some(consul) = config.consul.clone() {
|
|
||||||
let servers = consul.servers.unwrap_or_else(|| {
|
|
||||||
vec![format!(
|
|
||||||
"{}:{}",
|
|
||||||
env::var("CONSUL_SERVICE_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()),
|
|
||||||
env::var("CONSUL_SERVICE_PORT").unwrap_or_else(|_| "0".to_string())
|
|
||||||
)]
|
|
||||||
});
|
|
||||||
let end = servers.len().saturating_sub(1);
|
|
||||||
let num = if end > 0 { rand::rng().random_range(0..end) } else { 0 };
|
|
||||||
let consul_data = servers.get(num).unwrap().to_string();
|
|
||||||
let ss = format!("{}/v1/catalog/service/", consul_data);
|
|
||||||
|
|
||||||
if let Some(svc) = consul.services {
|
|
||||||
for i in &svc {
|
|
||||||
let header_list = DashMap::new();
|
|
||||||
let mut hl = Vec::new();
|
|
||||||
build_headers(&i.client_headers, config.as_ref(), &mut hl);
|
|
||||||
if !hl.is_empty() {
|
|
||||||
let path_key = i.path.as_deref().unwrap_or("/");
|
|
||||||
header_list.insert(Arc::from(path_key), hl);
|
|
||||||
config.client_headers.insert(Arc::from(i.hostname.clone()), header_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
let pref = format!("{}{}", ss, i.upstream);
|
|
||||||
let list = httpclient::for_consul(pref.as_str(), consul.token.clone(), i).await;
|
|
||||||
list_to_upstreams(list, &upstreams, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(lt) = clone_compare(&upstreams, &config).await {
|
|
||||||
let _ = toreturn.send(lt).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(Duration::from_secs(5)).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn clone_compare(upstreams: &UpstreamsDashMap, config: &Arc<Configuration>) -> Option<Configuration> {
|
|
||||||
if !compare_dashmaps(upstreams, &config.upstreams) {
|
if !compare_dashmaps(upstreams, &config.upstreams) {
|
||||||
let tosend = Configuration {
|
let tosend = Configuration {
|
||||||
upstreams: Default::default(),
|
upstreams: Default::default(),
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
use crate::utils::httpclient;
|
||||||
|
use crate::utils::kubewatcher::{start_ingress_watcher_with_config, AralezRouteUpdate};
|
||||||
|
use crate::utils::parceyaml::build_headers;
|
||||||
|
use crate::utils::structs::{Configuration, GlobalServiceMapping, UpstreamsDashMap};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use dashmap::DashMap;
|
||||||
|
use log::error;
|
||||||
|
use rand::RngExt;
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::utils::kuberconsul::{clone_compare, list_to_upstreams, ServiceDiscovery};
|
||||||
|
use rustls::crypto::ring::default_provider;
|
||||||
|
use rustls::crypto::CryptoProvider;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
pub struct KubeEndpoints {
|
||||||
|
pub subsets: Option<Vec<KubeSubset>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
pub struct KubeSubset {
|
||||||
|
pub addresses: Option<Vec<KubeAddress>>,
|
||||||
|
pub ports: Option<Vec<KubePort>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
pub struct KubeAddress {
|
||||||
|
pub ip: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
pub struct KubePort {
|
||||||
|
pub port: u16,
|
||||||
|
}
|
||||||
|
pub struct KubernetesDiscovery;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ServiceDiscovery for KubernetesDiscovery {
|
||||||
|
async fn fetch_upstreams(&self, config: Arc<Configuration>, toreturn: Sender<Configuration>) {
|
||||||
|
if let Some(kuber) = config.kubernetes.clone() {
|
||||||
|
let servers = kuber.servers.unwrap_or_else(|| {
|
||||||
|
vec![format!(
|
||||||
|
"{}:{}",
|
||||||
|
env::var("KUBERNETES_SERVICE_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()),
|
||||||
|
env::var("KUBERNETES_SERVICE_PORT_HTTPS").unwrap_or_else(|_| "0".to_string())
|
||||||
|
)]
|
||||||
|
});
|
||||||
|
|
||||||
|
let end = servers.len().saturating_sub(1);
|
||||||
|
let num = if end > 0 { rand::rng().random_range(0..end) } else { 0 };
|
||||||
|
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 namespace = get_current_namespace().unwrap_or_else(|| "default".to_string());
|
||||||
|
let token = crate::utils::kuberconsul::read_token(path.as_str()).await;
|
||||||
|
|
||||||
|
if CryptoProvider::get_default().is_none() {
|
||||||
|
default_provider().install_default().expect("Failed to install rustls crypto provider");
|
||||||
|
}
|
||||||
|
|
||||||
|
let (tx, mut rx) = tokio::sync::mpsc::channel::<AralezRouteUpdate>(100);
|
||||||
|
let srv = server.clone();
|
||||||
|
let tok = token.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = start_ingress_watcher_with_config(srv.as_str(), tok.as_str(), tx, "aralez").await {
|
||||||
|
error!("Fatal watcher error: {:?}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let upstreams = UpstreamsDashMap::new();
|
||||||
|
|
||||||
|
while let Some(update) = rx.recv().await {
|
||||||
|
let host_key: Arc<str> = Arc::from(update.host.as_str());
|
||||||
|
|
||||||
|
if update.is_deleted {
|
||||||
|
upstreams.remove(&host_key);
|
||||||
|
config.client_headers.remove(&host_key);
|
||||||
|
} else {
|
||||||
|
let service = GlobalServiceMapping {
|
||||||
|
upstream: update.service_name.clone(),
|
||||||
|
hostname: update.host.clone(),
|
||||||
|
path: Some(update.path.clone()),
|
||||||
|
to_https: None,
|
||||||
|
redirect_to: None,
|
||||||
|
authorization: None,
|
||||||
|
// sticky_sessions: update.sticky_sessions,
|
||||||
|
rate_limit: update.rate_limit,
|
||||||
|
x4xx_limit: update.x4xx_limit,
|
||||||
|
client_headers: None,
|
||||||
|
server_headers: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let cheader_list: DashMap<Arc<str>, Vec<(String, Arc<str>)>> = DashMap::new();
|
||||||
|
let sheader_list: DashMap<Arc<str>, Vec<(String, Arc<str>)>> = DashMap::new();
|
||||||
|
|
||||||
|
let mut client_headers_list = Vec::new();
|
||||||
|
let mut server_headers_list = Vec::new();
|
||||||
|
|
||||||
|
let mut chl: Option<Vec<String>> = None;
|
||||||
|
let mut shl: Option<Vec<String>> = None;
|
||||||
|
|
||||||
|
if let Some(hdr) = service.client_headers.as_ref() {
|
||||||
|
chl.get_or_insert_with(Vec::new).extend(hdr.iter().cloned());
|
||||||
|
}
|
||||||
|
if let Some(hdr) = service.server_headers.as_ref() {
|
||||||
|
shl.get_or_insert_with(Vec::new).extend(hdr.iter().cloned());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ch) = update.client_headers {
|
||||||
|
chl.get_or_insert_with(Vec::new).extend(ch);
|
||||||
|
}
|
||||||
|
if let Some(hdr) = update.server_headers.as_ref() {
|
||||||
|
shl.get_or_insert_with(Vec::new).extend(hdr.iter().cloned());
|
||||||
|
}
|
||||||
|
|
||||||
|
build_headers(&chl, config.as_ref(), &mut client_headers_list);
|
||||||
|
if !client_headers_list.is_empty() {
|
||||||
|
let path_key = service.path.as_deref().unwrap_or("/");
|
||||||
|
cheader_list.insert(Arc::from(path_key), client_headers_list);
|
||||||
|
config.client_headers.insert(host_key.clone(), cheader_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
build_headers(&shl, config.as_ref(), &mut server_headers_list);
|
||||||
|
if !server_headers_list.is_empty() {
|
||||||
|
let path_key = service.path.as_deref().unwrap_or("/");
|
||||||
|
sheader_list.insert(Arc::from(path_key), server_headers_list);
|
||||||
|
config.server_headers.insert(host_key.clone(), sheader_list);
|
||||||
|
}
|
||||||
|
let url = format!("https://{}/api/v1/namespaces/{}/endpoints/{}", server, namespace, update.service_name);
|
||||||
|
let list = httpclient::for_kuber(&url, &token, &service).await;
|
||||||
|
|
||||||
|
if list.is_none() {
|
||||||
|
error!("Endpoint URL: {} returned empty/invalid response", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_to_upstreams(list, &upstreams, &service);
|
||||||
|
}
|
||||||
|
if let Some(lt) = clone_compare(&upstreams, &config).await {
|
||||||
|
let _ = toreturn.send(lt).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
@@ -16,14 +16,3 @@ pub fn is_first_run() -> bool {
|
|||||||
let state = GLOBAL_STATE.read().unwrap();
|
let state = GLOBAL_STATE.read().unwrap();
|
||||||
state.first_run
|
state.first_run
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
impl SharedState {
|
|
||||||
pub fn mark_first_run(&mut self) {
|
|
||||||
self.first_run = false;
|
|
||||||
}
|
|
||||||
pub fn is_first_run(&self) -> bool {
|
|
||||||
self.first_run
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -20,11 +20,12 @@ pub struct Extraparams {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
pub struct GlobalServiceMapping {
|
pub struct GlobalServiceMapping {
|
||||||
|
pub redirect_to: Option<String>,
|
||||||
|
pub authorization: Option<String>,
|
||||||
pub upstream: String,
|
pub upstream: String,
|
||||||
pub hostname: String,
|
pub hostname: String,
|
||||||
pub path: Option<String>,
|
pub path: Option<String>,
|
||||||
pub to_https: Option<bool>,
|
pub to_https: Option<bool>,
|
||||||
pub sticky_sessions: Option<u64>,
|
|
||||||
pub rate_limit: Option<isize>,
|
pub rate_limit: Option<isize>,
|
||||||
pub x4xx_limit: Option<u32>,
|
pub x4xx_limit: Option<u32>,
|
||||||
pub client_headers: Option<Vec<String>>,
|
pub client_headers: Option<Vec<String>>,
|
||||||
@@ -34,14 +35,12 @@ pub struct GlobalServiceMapping {
|
|||||||
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
|
||||||
pub struct Kubernetes {
|
pub struct Kubernetes {
|
||||||
pub servers: Option<Vec<String>>,
|
pub servers: Option<Vec<String>>,
|
||||||
pub services: Option<Vec<GlobalServiceMapping>>,
|
|
||||||
pub tokenpath: Option<String>,
|
pub tokenpath: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
|
||||||
pub struct Consul {
|
pub struct Consul {
|
||||||
pub servers: Option<Vec<String>>,
|
pub servers: Option<Vec<String>>,
|
||||||
pub services: Option<Vec<GlobalServiceMapping>>,
|
|
||||||
pub token: Option<String>,
|
pub token: Option<String>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
|
|||||||
Reference in New Issue
Block a user