forked from NationTech/harmony
		
	feat(cert-manager): add cluster issuer to okd cluster score (#157)
added score to install okd cluster issuer Reviewed-on: https://git.nationtech.io/NationTech/harmony/pulls/157
This commit is contained in:
		
							parent
							
								
									14d1823d15
								
							
						
					
					
						commit
						987f195e2f
					
				
							
								
								
									
										209
									
								
								harmony/src/modules/cert_manager/cluster_issuer.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								harmony/src/modules/cert_manager/cluster_issuer.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,209 @@ | |||||||
|  | use std::sync::Arc; | ||||||
|  | 
 | ||||||
|  | use async_trait::async_trait; | ||||||
|  | use harmony_types::id::Id; | ||||||
|  | use kube::{CustomResource, api::ObjectMeta}; | ||||||
|  | use schemars::JsonSchema; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | 
 | ||||||
|  | use crate::{ | ||||||
|  |     data::Version, | ||||||
|  |     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||||
|  |     inventory::Inventory, | ||||||
|  |     score::Score, | ||||||
|  |     topology::{K8sclient, Topology, k8s::K8sClient}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, Serialize)] | ||||||
|  | pub struct ClusterIssuerScore { | ||||||
|  |     email: String, | ||||||
|  |     server: String, | ||||||
|  |     issuer_name: String, | ||||||
|  |     namespace: String, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T: Topology + K8sclient> Score<T> for ClusterIssuerScore { | ||||||
|  |     fn name(&self) -> String { | ||||||
|  |         "ClusterIssuerScore".to_string() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[doc(hidden)] | ||||||
|  |     fn create_interpret(&self) -> Box<dyn Interpret<T>> { | ||||||
|  |         Box::new(ClusterIssuerInterpret { | ||||||
|  |             score: self.clone(), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone)] | ||||||
|  | pub struct ClusterIssuerInterpret { | ||||||
|  |     score: ClusterIssuerScore, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[async_trait] | ||||||
|  | impl<T: Topology + K8sclient> Interpret<T> for ClusterIssuerInterpret { | ||||||
|  |     async fn execute( | ||||||
|  |         &self, | ||||||
|  |         _inventory: &Inventory, | ||||||
|  |         topology: &T, | ||||||
|  |     ) -> Result<Outcome, InterpretError> { | ||||||
|  |         self.apply_cluster_issuer(topology.k8s_client().await.unwrap()) | ||||||
|  |             .await | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_name(&self) -> InterpretName { | ||||||
|  |         InterpretName::Custom("ClusterIssuer") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_version(&self) -> Version { | ||||||
|  |         todo!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_status(&self) -> InterpretStatus { | ||||||
|  |         todo!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_children(&self) -> Vec<Id> { | ||||||
|  |         todo!() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ClusterIssuerInterpret { | ||||||
|  |     async fn validate_cert_manager( | ||||||
|  |         &self, | ||||||
|  |         client: &Arc<K8sClient>, | ||||||
|  |     ) -> Result<Outcome, InterpretError> { | ||||||
|  |         let cert_manager = "cert-manager".to_string(); | ||||||
|  |         let operator_namespace = "openshift-operators".to_string(); | ||||||
|  |         match client | ||||||
|  |             .get_deployment(&cert_manager, Some(&operator_namespace)) | ||||||
|  |             .await | ||||||
|  |         { | ||||||
|  |             Ok(Some(deployment)) => { | ||||||
|  |                 if let Some(status) = deployment.status { | ||||||
|  |                     let ready_count = status.ready_replicas.unwrap_or(0); | ||||||
|  |                     if ready_count >= 1 { | ||||||
|  |                         return Ok(Outcome::success(format!( | ||||||
|  |                             "'{}' is ready with {} replica(s).", | ||||||
|  |                             &cert_manager, ready_count | ||||||
|  |                         ))); | ||||||
|  |                     } else { | ||||||
|  |                         return Err(InterpretError::new( | ||||||
|  |                             "cert-manager operator not ready in cluster".to_string(), | ||||||
|  |                         )); | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     Err(InterpretError::new(format!( | ||||||
|  |                         "failed to get deployment status {} in ns {}", | ||||||
|  |                         &cert_manager, &operator_namespace | ||||||
|  |                     ))) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Ok(None) => Err(InterpretError::new(format!( | ||||||
|  |                 "Deployment '{}' not found in namespace '{}'.", | ||||||
|  |                 &cert_manager, &operator_namespace | ||||||
|  |             ))), | ||||||
|  |             Err(e) => Err(InterpretError::new(format!( | ||||||
|  |                 "Failed to query for deployment '{}': {}", | ||||||
|  |                 &cert_manager, e | ||||||
|  |             ))), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn build_cluster_issuer(&self) -> Result<ClusterIssuer, InterpretError> { | ||||||
|  |         let issuer_name = &self.score.issuer_name; | ||||||
|  |         let email = &self.score.email; | ||||||
|  |         let server = &self.score.server; | ||||||
|  |         let namespace = &self.score.namespace; | ||||||
|  |         let cluster_issuer = ClusterIssuer { | ||||||
|  |             metadata: ObjectMeta { | ||||||
|  |                 name: Some(issuer_name.to_string()), | ||||||
|  |                 namespace: Some(namespace.to_string()), | ||||||
|  |                 ..Default::default() | ||||||
|  |             }, | ||||||
|  |             spec: ClusterIssuerSpec { | ||||||
|  |                 acme: AcmeSpec { | ||||||
|  |                     email: email.to_string(), | ||||||
|  |                     private_key_secret_ref: PrivateKeySecretRef { | ||||||
|  |                         name: issuer_name.to_string(), | ||||||
|  |                     }, | ||||||
|  |                     server: server.to_string(), | ||||||
|  |                     solvers: vec![SolverSpec { | ||||||
|  |                         http01: Some(Http01Solver { | ||||||
|  |                             ingress: Http01Ingress { | ||||||
|  |                                 class: "nginx".to_string(), | ||||||
|  |                             }, | ||||||
|  |                         }), | ||||||
|  |                     }], | ||||||
|  |                 }, | ||||||
|  |             }, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         Ok(cluster_issuer) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub async fn apply_cluster_issuer( | ||||||
|  |         &self, | ||||||
|  |         client: Arc<K8sClient>, | ||||||
|  |     ) -> Result<Outcome, InterpretError> { | ||||||
|  |         let namespace = self.score.namespace.clone(); | ||||||
|  |         self.validate_cert_manager(&client).await?; | ||||||
|  |         let cluster_issuer = self.build_cluster_issuer().unwrap(); | ||||||
|  |         client | ||||||
|  |             .apply_yaml( | ||||||
|  |                 &serde_yaml::to_value(cluster_issuer).unwrap(), | ||||||
|  |                 Some(&namespace), | ||||||
|  |             ) | ||||||
|  |             .await?; | ||||||
|  |         Ok(Outcome::success(format!( | ||||||
|  |             "successfully deployed cluster operator: {} in namespace: {}", | ||||||
|  |             self.score.issuer_name, self.score.namespace | ||||||
|  |         ))) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)] | ||||||
|  | #[kube(
 | ||||||
|  |     group = "cert-manager.io", | ||||||
|  |     version = "v1", | ||||||
|  |     kind = "ClusterIssuer", | ||||||
|  |     plural = "clusterissuers" | ||||||
|  | )] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct ClusterIssuerSpec { | ||||||
|  |     pub acme: AcmeSpec, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct AcmeSpec { | ||||||
|  |     pub email: String, | ||||||
|  |     pub private_key_secret_ref: PrivateKeySecretRef, | ||||||
|  |     pub server: String, | ||||||
|  |     pub solvers: Vec<SolverSpec>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct PrivateKeySecretRef { | ||||||
|  |     pub name: String, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct SolverSpec { | ||||||
|  |     pub http01: Option<Http01Solver>, | ||||||
|  |     // Other solver types (e.g., dns01) would go here as Options
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct Http01Solver { | ||||||
|  |     pub ingress: Http01Ingress, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct Http01Ingress { | ||||||
|  |     pub class: String, | ||||||
|  | } | ||||||
| @ -1,2 +1,3 @@ | |||||||
|  | pub mod cluster_issuer; | ||||||
| mod helm; | mod helm; | ||||||
| pub use helm::*; | pub use helm::*; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user