fix: apply different network policies based on current target #97
| @ -28,7 +28,13 @@ use super::{ | ||||
|     PreparationOutcome, Topology, | ||||
|     k8s::K8sClient, | ||||
|     oberservability::monitoring::AlertReceiver, | ||||
|     tenant::{TenantConfig, TenantManager, k8s::K8sTenantManager}, | ||||
|     tenant::{ | ||||
|         TenantConfig, TenantManager, | ||||
|         k8s::K8sTenantManager, | ||||
|         network_policy::{ | ||||
|             K3dNetworkPolicyStrategy, NetworkPolicyStrategy, NoopNetworkPolicyStrategy, | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| @ -250,16 +256,21 @@ impl K8sAnywhereTopology { | ||||
|         Ok(Some(state)) | ||||
|     } | ||||
| 
 | ||||
|     async fn ensure_k8s_tenant_manager(&self) -> Result<(), String> { | ||||
|     async fn ensure_k8s_tenant_manager(&self, k8s_state: &K8sState) -> Result<(), String> { | ||||
|         if self.tenant_manager.get().is_some() { | ||||
|             return Ok(()); | ||||
|         } | ||||
| 
 | ||||
|         self.tenant_manager | ||||
|             .get_or_try_init(async || -> Result<K8sTenantManager, String> { | ||||
|                 // TOOD: checker si K8s ou K3d/s tenant manager (ref. issue https://git.nationtech.io/NationTech/harmony/issues/94)
 | ||||
|                 let k8s_client = self.k8s_client().await?; | ||||
|                 Ok(K8sTenantManager::new(k8s_client)) | ||||
|                 let network_policy_strategy: Box<dyn NetworkPolicyStrategy> = match k8s_state.source | ||||
|                 { | ||||
|                     K8sSource::LocalK3d => Box::new(K3dNetworkPolicyStrategy::new()), | ||||
|                     K8sSource::Kubeconfig => Box::new(NoopNetworkPolicyStrategy::new()), | ||||
|                 }; | ||||
| 
 | ||||
|                 Ok(K8sTenantManager::new(k8s_client, network_policy_strategy)) | ||||
|             }) | ||||
|             .await?; | ||||
| 
 | ||||
| @ -390,7 +401,7 @@ impl Topology for K8sAnywhereTopology { | ||||
|             "no K8s client could be found or installed".to_string(), | ||||
|         ))?; | ||||
| 
 | ||||
|         self.ensure_k8s_tenant_manager() | ||||
|         self.ensure_k8s_tenant_manager(k8s_state) | ||||
|             .await | ||||
|             .map_err(PreparationError::new)?; | ||||
| 
 | ||||
|  | ||||
| @ -20,24 +20,27 @@ use serde::de::DeserializeOwned; | ||||
| use serde_json::json; | ||||
| use tokio::sync::OnceCell; | ||||
| 
 | ||||
| use super::{TenantConfig, TenantManager}; | ||||
| use super::{TenantConfig, TenantManager, network_policy::NetworkPolicyStrategy}; | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| #[derive(Debug)] | ||||
| pub struct K8sTenantManager { | ||||
|     k8s_client: Arc<K8sClient>, | ||||
|     k8s_tenant_config: Arc<OnceCell<TenantConfig>>, | ||||
|     network_policy_strategy: Box<dyn NetworkPolicyStrategy>, | ||||
| } | ||||
| 
 | ||||
| impl K8sTenantManager { | ||||
|     pub fn new(client: Arc<K8sClient>) -> Self { | ||||
|     pub fn new( | ||||
|         client: Arc<K8sClient>, | ||||
|         network_policy_strategy: Box<dyn NetworkPolicyStrategy>, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             k8s_client: client, | ||||
|             k8s_tenant_config: Arc::new(OnceCell::new()), | ||||
|             network_policy_strategy, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl K8sTenantManager { | ||||
|     fn get_namespace_name(&self, config: &TenantConfig) -> String { | ||||
|         config.name.clone() | ||||
|     } | ||||
| @ -218,29 +221,6 @@ impl K8sTenantManager { | ||||
|                   } | ||||
|                 ] | ||||
|               }, | ||||
|               { | ||||
|                 "to": [ | ||||
|                   { | ||||
|                 "ipBlock": { | ||||
|                     "cidr": "10.43.0.1/32", | ||||
|                     } | ||||
|                   } | ||||
|                 ] | ||||
|               }, | ||||
|               { | ||||
|                 "to": [ | ||||
|                   { | ||||
|                       //TODO this ip is from the docker network that k3d is running on
 | ||||
|                       //since k3d does not deploy kube-api-server as a pod it needs to ahve the ip
 | ||||
|                       //address opened up
 | ||||
|                       //need to find a way to automatically detect the ip address from the docker
 | ||||
|                       //network
 | ||||
|                 "ipBlock": { | ||||
|                     "cidr": "172.18.0.0/16", | ||||
|                     } | ||||
|                   } | ||||
|                 ] | ||||
|               }, | ||||
|               { | ||||
|                 "to": [ | ||||
|                   { | ||||
| @ -410,12 +390,27 @@ impl K8sTenantManager { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Clone for K8sTenantManager { | ||||
|     fn clone(&self) -> Self { | ||||
|         Self { | ||||
|             k8s_client: self.k8s_client.clone(), | ||||
|             k8s_tenant_config: self.k8s_tenant_config.clone(), | ||||
|             network_policy_strategy: self.network_policy_strategy.clone_box(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl TenantManager for K8sTenantManager { | ||||
|     async fn provision_tenant(&self, config: &TenantConfig) -> Result<(), ExecutorError> { | ||||
|         let namespace = self.build_namespace(config)?; | ||||
|         let resource_quota = self.build_resource_quota(config)?; | ||||
| 
 | ||||
|         let network_policy = self.build_network_policy(config)?; | ||||
|         let network_policy = self | ||||
|             .network_policy_strategy | ||||
|             .adjust_policy(network_policy, config); | ||||
| 
 | ||||
|         let resource_limit_range = self.build_limit_range(config)?; | ||||
| 
 | ||||
|         self.ensure_constraints(&namespace)?; | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| pub mod k8s; | ||||
| mod manager; | ||||
| use std::str::FromStr; | ||||
| 
 | ||||
| pub use manager::*; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| pub mod network_policy; | ||||
| 
 | ||||
| use crate::data::Id; | ||||
| pub use manager::*; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use std::str::FromStr; | ||||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] // Assuming serde for Scores
 | ||||
| pub struct TenantConfig { | ||||
|  | ||||
							
								
								
									
										120
									
								
								harmony/src/domain/topology/tenant/network_policy.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								harmony/src/domain/topology/tenant/network_policy.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | ||||
| use k8s_openapi::api::networking::v1::{ | ||||
|     IPBlock, NetworkPolicy, NetworkPolicyEgressRule, NetworkPolicyPeer, NetworkPolicySpec, | ||||
| }; | ||||
| 
 | ||||
| use super::TenantConfig; | ||||
| 
 | ||||
| pub trait NetworkPolicyStrategy: Send + Sync + std::fmt::Debug { | ||||
|     fn clone_box(&self) -> Box<dyn NetworkPolicyStrategy>; | ||||
| 
 | ||||
|     fn adjust_policy(&self, policy: NetworkPolicy, config: &TenantConfig) -> NetworkPolicy; | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct NoopNetworkPolicyStrategy {} | ||||
| 
 | ||||
| impl NoopNetworkPolicyStrategy { | ||||
|     pub fn new() -> Self { | ||||
|         Self {} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Default for NoopNetworkPolicyStrategy { | ||||
|     fn default() -> Self { | ||||
|         Self::new() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl NetworkPolicyStrategy for NoopNetworkPolicyStrategy { | ||||
|     fn clone_box(&self) -> Box<dyn NetworkPolicyStrategy> { | ||||
|         Box::new(self.clone()) | ||||
|     } | ||||
| 
 | ||||
|     fn adjust_policy(&self, policy: NetworkPolicy, _config: &TenantConfig) -> NetworkPolicy { | ||||
|         policy | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct K3dNetworkPolicyStrategy {} | ||||
| 
 | ||||
| impl K3dNetworkPolicyStrategy { | ||||
|     pub fn new() -> Self { | ||||
|         Self {} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Default for K3dNetworkPolicyStrategy { | ||||
|     fn default() -> Self { | ||||
|         Self::new() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl NetworkPolicyStrategy for K3dNetworkPolicyStrategy { | ||||
|     fn clone_box(&self) -> Box<dyn NetworkPolicyStrategy> { | ||||
|         Box::new(self.clone()) | ||||
|     } | ||||
| 
 | ||||
|     fn adjust_policy(&self, policy: NetworkPolicy, _config: &TenantConfig) -> NetworkPolicy { | ||||
|         let mut egress = policy | ||||
|             .spec | ||||
|             .clone() | ||||
|             .unwrap_or_default() | ||||
|             .egress | ||||
|             .clone() | ||||
|             .unwrap_or_default(); | ||||
|         egress.push(NetworkPolicyEgressRule { | ||||
|             to: Some(vec![NetworkPolicyPeer { | ||||
|                 ip_block: Some(IPBlock { | ||||
|                     cidr: "172.18.0.0/16".into(), // TODO: query the IP range https://git.nationtech.io/NationTech/harmony/issues/108
 | ||||
|                     ..Default::default() | ||||
|                 }), | ||||
|                 ..Default::default() | ||||
|             }]), | ||||
|             ..Default::default() | ||||
|         }); | ||||
| 
 | ||||
|         NetworkPolicy { | ||||
|             spec: Some(NetworkPolicySpec { | ||||
|                 egress: Some(egress), | ||||
|                 ..policy.spec.unwrap_or_default() | ||||
|             }), | ||||
|             ..policy | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use k8s_openapi::api::networking::v1::{ | ||||
|         IPBlock, NetworkPolicy, NetworkPolicyEgressRule, NetworkPolicyPeer, NetworkPolicySpec, | ||||
|     }; | ||||
| 
 | ||||
|     use super::{K3dNetworkPolicyStrategy, NetworkPolicyStrategy}; | ||||
| 
 | ||||
|     #[test] | ||||
|     pub fn should_add_ip_block_for_k3d_harmony_server() { | ||||
|         let strategy = K3dNetworkPolicyStrategy::new(); | ||||
| 
 | ||||
|         let policy = | ||||
|             strategy.adjust_policy(NetworkPolicy::default(), &super::TenantConfig::default()); | ||||
| 
 | ||||
|         let expected_policy = NetworkPolicy { | ||||
|             spec: Some(NetworkPolicySpec { | ||||
|                 egress: Some(vec![NetworkPolicyEgressRule { | ||||
|                     to: Some(vec![NetworkPolicyPeer { | ||||
|                         ip_block: Some(IPBlock { | ||||
|                             cidr: "172.18.0.0/16".into(), | ||||
|                             ..Default::default() | ||||
|                         }), | ||||
|                         ..Default::default() | ||||
|                     }]), | ||||
|                     ..Default::default() | ||||
|                 }]), | ||||
|                 ..Default::default() | ||||
|             }), | ||||
|             ..Default::default() | ||||
|         }; | ||||
|         assert_eq!(expected_policy, policy); | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user