Skip to content

Commit

Permalink
remove admin k8s feature(in progress)
Browse files Browse the repository at this point in the history
  • Loading branch information
RWDai committed Nov 20, 2023
1 parent ecd4a6a commit 835c36d
Show file tree
Hide file tree
Showing 23 changed files with 536 additions and 329 deletions.
19 changes: 11 additions & 8 deletions admin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ edition.workspace = true
readme = "./README.md"

[features]
k8s = ["kube", "k8s-openapi", "k8s-gateway-api","kernel-common/k8s"]
doc=["tardis/openapi-rapidoc"]
doc = ["tardis/openapi-rapidoc"]

[dependencies]
tardis = { workspace = true ,features = ["web-server","crypto"]}
tardis = { workspace = true, features = ["web-server", "crypto", "cache"] }
serde.workspace = true
serde_json.workspace = true

kernel-common={path = "../kernel-common",features = ["admin-support"]}
kube = { workspace = true, optional = true }
k8s-openapi = { workspace = true, optional = true }
k8s-gateway-api = { workspace = true, optional = true }
lazy_static = "1.4.0"
secrecy = { version = "0.8.0", features = [
"alloc",
"serde",
] }
kernel-common = { path = "../kernel-common", features = ["admin-support", "k8s","cache"] }
kube = { workspace = true }
k8s-openapi = { workspace = true }
k8s-gateway-api = { workspace = true }
lazy_static = { workspace = true }
1 change: 1 addition & 0 deletions admin/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pub(crate) mod gateway_api;
pub(crate) mod plugin_api;
pub(crate) mod route_api;
pub(crate) mod tls_api;
pub(crate) mod spacegate_manage_api;
38 changes: 38 additions & 0 deletions admin/src/api/spacegate_manage_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::model::vo::spacegate_inst_vo::InstConfigVo;
use tardis::web::poem_openapi;
use tardis::web::poem_openapi::param::Query;
use tardis::web::poem_openapi::payload::Json;
use tardis::web::web_resp::{TardisApiResult, TardisResp, Void};

#[derive(Clone, Default)]
pub struct SpacegateManageApi;

#[poem_openapi::OpenApi(prefix_path = "/spacegate/manage")]
impl SpacegateManageApi {
/// List Spacegate Inst
#[oai(path = "/", method = "get")]
async fn list(&self) -> TardisApiResult<Vec<InstConfigVo>> {
SpacegateManageService::list().await?;
}

/// Add Spacegate Inst
#[oai(path = "/", method = "post")]
async fn add(&self, add: Json<InstConfigVo>) -> TardisApiResult<Void> {
// HttpRouteVoService::add(add.0).await?;
TardisResp::ok(Void {})
}

/// Update Spacegate Inst
#[oai(path = "/", method = "put")]
async fn update(&self, backend: Json<InstConfigVo>) -> TardisApiResult<Void> {
// HttpRouteVoService::update(backend.0).await?;
TardisResp::ok(Void {})
}

/// Delete Spacegate Inst
#[oai(path = "/", method = "delete")]
async fn delete(&self, name: Query<String>) -> TardisApiResult<Void> {
// HttpRouteVoService::delete(&name.0).await?;
TardisResp::ok(Void {})
}
}
28 changes: 28 additions & 0 deletions admin/src/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::config::k8s_config::ToKubeconfig;
use crate::model::vo::spacegate_inst_vo::K8sClusterConfig;
use kube::config::Kubeconfig;
use lazy_static::lazy_static;
use std::mem;
use std::sync::RwLock;
use tardis::basic::error::TardisError;
use tardis::basic::result::TardisResult;

lazy_static! {
///Total kube config
pub static ref KUBECONFIG: RwLock<kube::config::Kubeconfig> = RwLock::default();
}

pub fn add_k8s_config(config: K8sClusterConfig) -> TardisResult<()> {
for _ in 0..100 {
if let Ok(mut kube_config) = KUBECONFIG.try_write() {
let mut swap_config = Kubeconfig::default();
mem::swap(&mut swap_config, &mut kube_config);
swap_config = swap_config.merge(config.to_kubeconfig()).map_err(|e| TardisError::wrap(&format!("kubeconfig parse error:{e}"), ""))?;

mem::swap(&mut swap_config, &mut kube_config);
return Ok(());
};
}

Err(TardisError::conflict("[SG.admin] add config: get lock time out", ""))
}
242 changes: 207 additions & 35 deletions admin/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
use crate::config::k8s_config::K8sConfig;
use serde::Deserializer;
use tardis::config::config_dto::CacheConfig;
use tardis::serde::{Deserialize, Serialize};

#[derive(Default, Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct SpacegateAdminConfig {
#[cfg(feature = "k8s")]
pub cache_config: Option<CacheConfig>,

#[serde(flatten)]
pub kube_config: AdminK8sConfig,
}

#[derive(Default, Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct AdminK8sConfig {
/// If enable is true , then must use k8s configmap.
/// Otherwise , just try k8s.
pub enable: bool,

pub k8s_config: Option<K8sConfig>,
/// # `KUBECONFIG`
///
Expand All @@ -18,41 +33,198 @@ pub struct SpacegateAdminConfig {
/// ```cmd
/// set KUBECONFIG=<C>:\path\to\your\config
/// ```
#[cfg(feature = "k8s")]
pub kube_config: Option<String>,
}

#[cfg(feature = "k8s")]
#[derive(Default, Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct K8sConfig {
/// The configured cluster url
pub cluster_url: String,
/// The configured default namespace
pub default_namespace: String,
/// The configured root certificate
pub root_cert: Option<Vec<Vec<u8>>>,
/// Set the timeout for connecting to the Kubernetes API.
///
/// A value of `None` means no timeout
pub connect_timeout: Option<std::time::Duration>,
/// Set the timeout for the Kubernetes API response.
///
/// A value of `None` means no timeout
pub read_timeout: Option<std::time::Duration>,
/// Set the timeout for the Kubernetes API request.
///
/// A value of `None` means no timeout
pub write_timeout: Option<std::time::Duration>,
/// Whether to accept invalid certificates
pub accept_invalid_certs: bool,
/// Stores information to tell the cluster who you are.
pub auth_info: kube::config::AuthInfo,
// TODO Actually support proxy or create an example with custom client
/// Optional proxy URL.
pub proxy_url: Option<String>,
/// If set, apiserver certificate will be validated to contain this string
///
/// If not set, the `cluster_url` is used instead
pub tls_server_name: Option<String>,
pub mod k8s_config {
use kube::config::NamedContext;
use secrecy::SecretString;
use serde::{Deserialize, Deserializer, Serialize};
use tardis::web::poem_openapi;

pub trait ToKubeconfig<T> {
fn to_kubeconfig(self) -> T;
}

#[derive(Default, Debug, Serialize, Deserialize, poem_openapi::Object)]
#[serde(default)]
pub struct K8sConfig {
/// Referencable names to cluster configs
#[serde(default, deserialize_with = "deserialize_null_as_default")]
pub clusters: NamedCluster,
/// Referencable names to user configs
#[serde(default, deserialize_with = "deserialize_null_as_default")]
pub users: NamedAuthInfo,
}
impl ToKubeconfig<kube::config::Kubeconfig> for K8sConfig {
fn to_kubeconfig(self) -> kube::config::Kubeconfig {
let cluster = self.clusters.to_kubeconfig();
let user = self.users.to_kubeconfig();
let context = NamedContext {
name: "default".to_string(),
context: Some(kube::config::Context {
cluster: cluster.name.clone(),
user: user.name.clone(),
namespace: None,
extensions: None,
}),
};
kube::config::Kubeconfig {
preferences: None,
clusters: vec![cluster],
auth_infos: vec![user],
contexts: vec![context],
current_context: Some("default".to_string()),
extensions: None,
kind: Some("Config".to_string()),
api_version: Some("v1".to_string()),
}
}
}

#[derive(Clone, Debug, Serialize, Deserialize, Default, poem_openapi::Object)]
pub struct NamedCluster {
/// Name of cluster
pub name: String,
/// Information about how to communicate with a kubernetes cluster
#[serde(skip_serializing_if = "Option::is_none")]
pub cluster: Option<Cluster>,
}

impl ToKubeconfig<kube::config::NamedCluster> for NamedCluster {
fn to_kubeconfig(self) -> kube::config::NamedCluster {
kube::config::NamedCluster {
name: self.name,
cluster: self.cluster.map(|c| c.to_kubeconfig()),
}
}
}

/// Cluster stores information to connect Kubernetes cluster.
#[derive(Clone, Debug, Serialize, Deserialize, Default, poem_openapi::Object)]
pub struct Cluster {
/// The address of the kubernetes cluster (https://hostname:port).
#[serde(skip_serializing_if = "Option::is_none")]
pub server: Option<String>,
/// Skips the validity check for the server's certificate. This will make your HTTPS connections insecure.
#[serde(rename = "insecure-skip-tls-verify")]
#[serde(skip_serializing_if = "Option::is_none")]
pub insecure_skip_tls_verify: Option<bool>,
/// The path to a cert file for the certificate authority.
#[serde(rename = "certificate-authority")]
#[serde(skip_serializing_if = "Option::is_none")]
pub certificate_authority: Option<String>,
/// PEM-encoded certificate authority certificates. Overrides `certificate_authority`
#[serde(rename = "certificate-authority-data")]
#[serde(skip_serializing_if = "Option::is_none")]
pub certificate_authority_data: Option<String>,
/// URL to the proxy to be used for all requests.
#[serde(rename = "proxy-url")]
#[serde(skip_serializing_if = "Option::is_none")]
pub proxy_url: Option<String>,
/// Name used to check server certificate.
///
/// If `tls_server_name` is `None`, the hostname used to contact the server is used.
#[serde(rename = "tls-server-name")]
#[serde(skip_serializing_if = "Option::is_none")]
pub tls_server_name: Option<String>,
}

impl ToKubeconfig<kube::config::Cluster> for Cluster {
fn to_kubeconfig(self) -> kube::config::Cluster {
kube::config::Cluster {
server: self.server,
insecure_skip_tls_verify: self.insecure_skip_tls_verify,
certificate_authority: self.certificate_authority,
certificate_authority_data: self.certificate_authority_data,
proxy_url: self.proxy_url,
tls_server_name: self.tls_server_name,
extensions: None,
}
}
}

/// NamedAuthInfo associates name with authentication.
#[derive(Clone, Debug, Serialize, Deserialize, Default, poem_openapi::Object)]
pub struct NamedAuthInfo {
/// Name of the user
pub name: String,
/// Information that describes identity of the user
#[serde(rename = "user")]
#[serde(skip_serializing_if = "Option::is_none")]
pub auth_info: Option<AuthInfo>,
}

impl ToKubeconfig<kube::config::NamedAuthInfo> for NamedAuthInfo {
fn to_kubeconfig(self) -> kube::config::NamedAuthInfo {
kube::config::NamedAuthInfo {
name: self.name,
auth_info: self.auth_info.map(|auth| auth.to_kubeconfig()),
}
}
}

#[derive(Clone, Debug, Serialize, Deserialize, Default, poem_openapi::Object)]
pub struct AuthInfo {
/// The username for basic authentication to the kubernetes cluster.
#[serde(skip_serializing_if = "Option::is_none")]
pub username: Option<String>,
/// The password for basic authentication to the kubernetes cluster.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub password: Option<String>,

/// The bearer token for authentication to the kubernetes cluster.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub token: Option<String>,
/// Pointer to a file that contains a bearer token (as described above). If both `token` and token_file` are present, `token` takes precedence.
#[serde(rename = "tokenFile")]
#[serde(skip_serializing_if = "Option::is_none")]
pub token_file: Option<String>,

/// Path to a client cert file for TLS.
#[serde(rename = "client-certificate")]
#[serde(skip_serializing_if = "Option::is_none")]
pub client_certificate: Option<String>,
/// PEM-encoded data from a client cert file for TLS. Overrides `client_certificate`
#[serde(rename = "client-certificate-data")]
#[serde(skip_serializing_if = "Option::is_none")]
pub client_certificate_data: Option<String>,

/// Path to a client key file for TLS.
#[serde(rename = "client-key")]
#[serde(skip_serializing_if = "Option::is_none")]
pub client_key: Option<String>,
/// PEM-encoded data from a client key file for TLS. Overrides `client_key`
#[serde(rename = "client-key-data")]
#[serde(skip_serializing_if = "Option::is_none", default)]
pub client_key_data: Option<String>,
}

impl ToKubeconfig<kube::config::AuthInfo> for AuthInfo {
fn to_kubeconfig(self) -> kube::config::AuthInfo {
kube::config::AuthInfo {
username: self.username,
password: self.password.map(|s| SecretString::new(s)),
token: self.token.map(|token| SecretString::new(token)),
token_file: self.token_file,
client_certificate: self.client_certificate,
client_certificate_data: self.client_certificate_data,
client_key: self.client_key,
client_key_data: self.client_key_data.map(|data| SecretString::new(data)),
impersonate: None,
impersonate_groups: None,
auth_provider: None,
exec: None,
}
}
}

fn deserialize_null_as_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
T: Default + Deserialize<'de>,
D: Deserializer<'de>,
{
let opt = Option::deserialize(deserializer)?;
Ok(opt.unwrap_or_default())
}
}
1 change: 1 addition & 0 deletions admin/src/initializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use tardis::basic::result::TardisResult;
use tardis::web::web_server::{TardisWebServer, WebServerModule};

pub(crate) async fn init(web_server: &TardisWebServer) -> TardisResult<()> {
// todo 根据现有的k8s资源初始化成VO
init_api(web_server).await
}

Expand Down
2 changes: 1 addition & 1 deletion admin/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use tardis::{basic::result::TardisResult, tokio, TardisFuns};

mod api;
mod client;
mod config;
mod constants;
mod helper;
Expand All @@ -10,7 +11,6 @@ mod service;

#[tokio::main]
async fn main() -> TardisResult<()> {
// todo 根据现有的k8s资源初始化成VO
TardisFuns::init(Some("config")).await?;
let web_server = TardisFuns::web_server();
initializer::init(&web_server).await?;
Expand Down
2 changes: 1 addition & 1 deletion admin/src/model/vo.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pub mod backend_vo;
pub mod gateway_vo;
pub mod http_route_vo;
pub mod k8s_cluster_vo;
pub mod plugin_vo;
pub mod spacegate_inst_vo;
pub mod tls_vo;

/// Vo is a base until for admin.
Expand Down
1 change: 0 additions & 1 deletion admin/src/model/vo/k8s_cluster_vo.rs

This file was deleted.

Loading

0 comments on commit 835c36d

Please sign in to comment.