fix: apply different network policies based on current target #97
| @ -28,7 +28,13 @@ use super::{ | |||||||
|     PreparationOutcome, Topology, |     PreparationOutcome, Topology, | ||||||
|     k8s::K8sClient, |     k8s::K8sClient, | ||||||
|     oberservability::monitoring::AlertReceiver, |     oberservability::monitoring::AlertReceiver, | ||||||
|     tenant::{TenantConfig, TenantManager, k8s::K8sTenantManager}, |     tenant::{ | ||||||
|  |         TenantConfig, TenantManager, | ||||||
|  |         k8s::K8sTenantManager, | ||||||
|  |         network_policy::{ | ||||||
|  |             K3dNetworkPolicyStrategy, NetworkPolicyStrategy, NoopNetworkPolicyStrategy, | ||||||
|  |         }, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| @ -250,16 +256,21 @@ impl K8sAnywhereTopology { | |||||||
|         Ok(Some(state)) |         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() { |         if self.tenant_manager.get().is_some() { | ||||||
|             return Ok(()); |             return Ok(()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         self.tenant_manager |         self.tenant_manager | ||||||
|             .get_or_try_init(async || -> Result<K8sTenantManager, String> { |             .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?; |                 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?; |             .await?; | ||||||
| 
 | 
 | ||||||
| @ -390,7 +401,7 @@ impl Topology for K8sAnywhereTopology { | |||||||
|             "no K8s client could be found or installed".to_string(), |             "no K8s client could be found or installed".to_string(), | ||||||
|         ))?; |         ))?; | ||||||
| 
 | 
 | ||||||
|         self.ensure_k8s_tenant_manager() |         self.ensure_k8s_tenant_manager(k8s_state) | ||||||
|             .await |             .await | ||||||
|             .map_err(PreparationError::new)?; |             .map_err(PreparationError::new)?; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,24 +20,27 @@ use serde::de::DeserializeOwned; | |||||||
| use serde_json::json; | use serde_json::json; | ||||||
| use tokio::sync::OnceCell; | use tokio::sync::OnceCell; | ||||||
| 
 | 
 | ||||||
| use super::{TenantConfig, TenantManager}; | use super::{TenantConfig, TenantManager, network_policy::NetworkPolicyStrategy}; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Debug)] | ||||||
| pub struct K8sTenantManager { | pub struct K8sTenantManager { | ||||||
|     k8s_client: Arc<K8sClient>, |     k8s_client: Arc<K8sClient>, | ||||||
|     k8s_tenant_config: Arc<OnceCell<TenantConfig>>, |     k8s_tenant_config: Arc<OnceCell<TenantConfig>>, | ||||||
|  |     network_policy_strategy: Box<dyn NetworkPolicyStrategy>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl K8sTenantManager { | impl K8sTenantManager { | ||||||
|     pub fn new(client: Arc<K8sClient>) -> Self { |     pub fn new( | ||||||
|  |         client: Arc<K8sClient>, | ||||||
|  |         network_policy_strategy: Box<dyn NetworkPolicyStrategy>, | ||||||
|  |     ) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             k8s_client: client, |             k8s_client: client, | ||||||
|             k8s_tenant_config: Arc::new(OnceCell::new()), |             k8s_tenant_config: Arc::new(OnceCell::new()), | ||||||
|  |             network_policy_strategy, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| impl K8sTenantManager { |  | ||||||
|     fn get_namespace_name(&self, config: &TenantConfig) -> String { |     fn get_namespace_name(&self, config: &TenantConfig) -> String { | ||||||
|         config.name.clone() |         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": [ |                 "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] | #[async_trait] | ||||||
| impl TenantManager for K8sTenantManager { | impl TenantManager for K8sTenantManager { | ||||||
|     async fn provision_tenant(&self, config: &TenantConfig) -> Result<(), ExecutorError> { |     async fn provision_tenant(&self, config: &TenantConfig) -> Result<(), ExecutorError> { | ||||||
|         let namespace = self.build_namespace(config)?; |         let namespace = self.build_namespace(config)?; | ||||||
|         let resource_quota = self.build_resource_quota(config)?; |         let resource_quota = self.build_resource_quota(config)?; | ||||||
|  | 
 | ||||||
|         let network_policy = self.build_network_policy(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)?; |         let resource_limit_range = self.build_limit_range(config)?; | ||||||
| 
 | 
 | ||||||
|         self.ensure_constraints(&namespace)?; |         self.ensure_constraints(&namespace)?; | ||||||
|  | |||||||
| @ -1,11 +1,11 @@ | |||||||
| pub mod k8s; | pub mod k8s; | ||||||
| mod manager; | mod manager; | ||||||
| use std::str::FromStr; | pub mod network_policy; | ||||||
| 
 |  | ||||||
| pub use manager::*; |  | ||||||
| use serde::{Deserialize, Serialize}; |  | ||||||
| 
 | 
 | ||||||
| use crate::data::Id; | 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
 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] // Assuming serde for Scores
 | ||||||
| pub struct TenantConfig { | 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