feat: adding kubernetes implentation of tenant manager
Some checks failed
Run Check Script / check (push) Failing after 43s

This commit is contained in:
Willem 2025-05-29 14:35:58 -04:00
parent 624e4330bb
commit 97fba07f4e
3 changed files with 114 additions and 76 deletions

View File

@ -15,9 +15,7 @@ use crate::{
};
use super::{
HelmCommand, K8sclient, Topology,
k8s::K8sClient,
tenant::{ResourceLimits, TenantConfig, TenantManager, TenantNetworkPolicy},
k8s::K8sClient, tenant::{k8s::K8sTenantManager, ResourceLimits, TenantConfig, TenantManager, TenantNetworkPolicy}, HelmCommand, K8sclient, Topology
};
struct K8sState {
@ -34,8 +32,10 @@ enum K8sSource {
pub struct K8sAnywhereTopology {
k8s_state: OnceCell<Option<K8sState>>,
tenant_manager: K8sTenantManager,
}
#[async_trait]
impl K8sclient for K8sAnywhereTopology {
async fn k8s_client(&self) -> Result<Arc<K8sClient>, String> {
@ -216,80 +216,29 @@ impl Topology for K8sAnywhereTopology {
impl HelmCommand for K8sAnywhereTopology {}
#[async_trait]
impl TenantManager for K8sAnywhereTopology {
fn provision_tenant<'life0, 'life1, 'async_trait>(
&'life0 self,
config: &'life1 TenantConfig,
) -> ::core::pin::Pin<
Box<
dyn ::core::future::Future<Output = Result<(), ExecutorError>>
+ ::core::marker::Send
+ 'async_trait,
>,
>
where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
{
todo!()
async fn provision_tenant(&self, config: &TenantConfig) -> Result<(), ExecutorError> {
self.tenant_manager.provision_tenant(config).await
}
fn update_tenant_resource_limits<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
tenant_name: &'life1 str,
new_limits: &'life2 ResourceLimits,
) -> ::core::pin::Pin<
Box<
dyn ::core::future::Future<Output = Result<(), ExecutorError>>
+ ::core::marker::Send
+ 'async_trait,
>,
>
where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
{
todo!()
async fn update_tenant_resource_limits(
&self,
tenant_name: &str,
new_limits: &ResourceLimits,
) -> Result<(), ExecutorError> {
self.tenant_manager.update_tenant_resource_limits(tenant_name, new_limits).await
}
fn update_tenant_network_policy<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
tenant_name: &'life1 str,
new_policy: &'life2 TenantNetworkPolicy,
) -> ::core::pin::Pin<
Box<
dyn ::core::future::Future<Output = Result<(), ExecutorError>>
+ ::core::marker::Send
+ 'async_trait,
>,
>
where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
{
todo!()
async fn update_tenant_network_policy(
&self,
tenant_name: &str,
new_policy: &TenantNetworkPolicy,
) -> Result<(), ExecutorError> {
self.tenant_manager.update_tenant_network_policy(tenant_name, new_policy).await
}
fn deprovision_tenant<'life0, 'life1, 'async_trait>(
&'life0 self,
tenant_name: &'life1 str,
) -> ::core::pin::Pin<
Box<
dyn ::core::future::Future<Output = Result<(), ExecutorError>>
+ ::core::marker::Send
+ 'async_trait,
>,
>
where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
{
todo!()
async fn deprovision_tenant(&self, tenant_name: &str) -> Result<(), ExecutorError> {
self.tenant_manager.deprovision_tenant(tenant_name).await
}
}

View File

@ -0,0 +1,88 @@
use std::sync::Arc;
use crate::{executors::ExecutorError, topology::k8s::K8sClient};
use async_trait::async_trait;
use k8s_openapi::api::core::v1::Namespace;
use serde_json::json;
use super::{ResourceLimits, TenantConfig, TenantManager, TenantNetworkPolicy};
pub struct K8sTenantManager {
k8s_client: Arc<K8sClient>,
}
#[async_trait]
impl TenantManager for K8sTenantManager {
async fn provision_tenant(&self, config: &TenantConfig) -> Result<(), ExecutorError> {
let namespace = json!(
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"labels": {
"harmony.nationtech.io/tenant.id": config.id,
"name": config.name,
},
"name": config.name,
},
}
);
todo!("Validate that when tenant already exists (by id) that name has not changed");
let namespace: Namespace = serde_json::from_value(namespace).unwrap();
let resource_quota = json!(
{
"apiVersion": "v1",
"kind": "List",
"items": [
{
"apiVersion": "v1",
"kind": "ResourceQuota",
"metadata": {
"name": config.name
},
"spec": {
"hard": {
"cpu": config.resource_limits.cpu_limit_cores,
"memory": format!("{:.3}Gi", config.resource_limits.memory_limit_gb),
},
"scopeSelector": {
"matchExpressions": [
{
"operator": "In",
"scopeName": "PriorityClass",
"values": ["high"]
}
]
}
}
}
]
}
);
}
async fn update_tenant_resource_limits(
&self,
tenant_name: &str,
new_limits: &ResourceLimits,
) -> Result<(), ExecutorError> {
todo!()
}
async fn update_tenant_network_policy(
&self,
tenant_name: &str,
new_policy: &TenantNetworkPolicy,
) -> Result<(), ExecutorError> {
todo!()
}
async fn deprovision_tenant(&self, tenant_name: &str) -> Result<(), ExecutorError> {
todo!()
}
}

View File

@ -1,4 +1,5 @@
mod manager;
pub mod k8s;
pub use manager::*;
use serde::{Deserialize, Serialize};
@ -29,17 +30,17 @@ pub struct TenantConfig {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct ResourceLimits {
/// Requested/guaranteed CPU cores (e.g., 2.0).
pub cpu_request_cores: Option<f32>,
pub cpu_request_cores: f32,
/// Maximum CPU cores the tenant can burst to (e.g., 4.0).
pub cpu_limit_cores: Option<f32>,
pub cpu_limit_cores: f32,
/// Requested/guaranteed memory in Gigabytes (e.g., 8.0).
pub memory_request_gb: Option<f32>,
pub memory_request_gb: f32,
/// Maximum memory in Gigabytes tenant can burst to (e.g., 16.0).
pub memory_limit_gb: Option<f32>,
pub memory_limit_gb: f32,
/// Total persistent storage allocation in Gigabytes across all volumes.
pub storage_total_gb: Option<f32>,
pub storage_total_gb: f32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]