Compare commits
	
		
			2 Commits
		
	
	
		
			eb8a8a2e04
			...
			f7d3da3ac9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f7d3da3ac9 | |||
| 0d94c537a0 | 
							
								
								
									
										17
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										17
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -1181,6 +1181,16 @@ dependencies = [ | |||||||
|  "percent-encoding", |  "percent-encoding", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "fqdn" | ||||||
|  | version = "0.4.6" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "c0f5d7f7b3eed2f771fc7f6fcb651f9560d7b0c483d75876082acb4649d266b3" | ||||||
|  | dependencies = [ | ||||||
|  |  "punycode", | ||||||
|  |  "serde", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "funty" | name = "funty" | ||||||
| version = "2.0.0" | version = "2.0.0" | ||||||
| @ -1407,6 +1417,7 @@ dependencies = [ | |||||||
|  "dockerfile_builder", |  "dockerfile_builder", | ||||||
|  "email_address", |  "email_address", | ||||||
|  "env_logger", |  "env_logger", | ||||||
|  |  "fqdn", | ||||||
|  "harmony_macros", |  "harmony_macros", | ||||||
|  "harmony_types", |  "harmony_types", | ||||||
|  "helm-wrapper-rs", |  "helm-wrapper-rs", | ||||||
| @ -3026,6 +3037,12 @@ dependencies = [ | |||||||
|  "unicode-ident", |  "unicode-ident", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "punycode" | ||||||
|  | version = "0.4.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "quote" | name = "quote" | ||||||
| version = "1.0.40" | version = "1.0.40" | ||||||
|  | |||||||
| @ -3,7 +3,9 @@ use harmony::{ | |||||||
|     inventory::Inventory, |     inventory::Inventory, | ||||||
|     maestro::Maestro, |     maestro::Maestro, | ||||||
|     modules::{ |     modules::{ | ||||||
|  |         { | ||||||
|         lamp::{LAMPConfig, LAMPScore}, |         lamp::{LAMPConfig, LAMPScore}, | ||||||
|  |     }, | ||||||
|         monitoring::monitoring_alerting::MonitoringAlertingStackScore, |         monitoring::monitoring_alerting::MonitoringAlertingStackScore, | ||||||
|     }, |     }, | ||||||
|     topology::{K8sAnywhereTopology, Url}, |     topology::{K8sAnywhereTopology, Url}, | ||||||
|  | |||||||
| @ -40,3 +40,11 @@ dockerfile_builder = "0.1.5" | |||||||
| temp-file = "0.1.9" | temp-file = "0.1.9" | ||||||
| convert_case.workspace = true | convert_case.workspace = true | ||||||
| email_address = "0.2.9" | email_address = "0.2.9" | ||||||
|  | fqdn = { version = "0.4.6", features = [ | ||||||
|  |     "domain-label-cannot-start-or-end-with-hyphen", | ||||||
|  |     "domain-label-length-limited-to-63", | ||||||
|  |     "domain-name-without-special-chars", | ||||||
|  |     "domain-name-length-limited-to-255", | ||||||
|  |     "punycode", | ||||||
|  |     "serde", | ||||||
|  | ] } | ||||||
|  | |||||||
							
								
								
									
										98
									
								
								harmony/src/modules/k8s/ingress.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								harmony/src/modules/k8s/ingress.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  | use harmony_macros::ingress_path; | ||||||
|  | use k8s_openapi::api::networking::v1::Ingress; | ||||||
|  | use serde::Serialize; | ||||||
|  | use serde_json::json; | ||||||
|  | 
 | ||||||
|  | use crate::{ | ||||||
|  |     interpret::Interpret, | ||||||
|  |     score::Score, | ||||||
|  |     topology::{K8sclient, Topology}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use super::resource::{K8sResourceInterpret, K8sResourceScore}; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone, Serialize)] | ||||||
|  | pub enum PathType { | ||||||
|  |     ImplementationSpecific, | ||||||
|  |     Exact, | ||||||
|  |     Prefix, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl PathType { | ||||||
|  |     fn as_str(&self) -> &'static str { | ||||||
|  |         match self { | ||||||
|  |             PathType::ImplementationSpecific => "ImplementationSpecific", | ||||||
|  |             PathType::Exact => "Exact", | ||||||
|  |             PathType::Prefix => "Prefix", | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type IngressPath = String; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone, Serialize)] | ||||||
|  | pub struct K8sIngressScore { | ||||||
|  |     pub name: fqdn::FQDN, | ||||||
|  |     pub host: fqdn::FQDN, | ||||||
|  |     pub backend_service: fqdn::FQDN, | ||||||
|  |     pub port: u16, | ||||||
|  |     pub path: Option<IngressPath>, | ||||||
|  |     pub path_type: Option<PathType>, | ||||||
|  |     pub namespace: Option<fqdn::FQDN>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T: Topology + K8sclient> Score<T> for K8sIngressScore { | ||||||
|  |     fn create_interpret(&self) -> Box<dyn Interpret<T>> { | ||||||
|  |         let path = match self.path.clone() { | ||||||
|  |             Some(p) => p, | ||||||
|  |             None => ingress_path!("/"), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let path_type = match self.path_type.clone() { | ||||||
|  |             Some(p) => p, | ||||||
|  |             None => PathType::Prefix, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let ingress = json!( | ||||||
|  |             { | ||||||
|  |                 "metadata": { | ||||||
|  |                     "name": self.name | ||||||
|  |                 }, | ||||||
|  |                 "spec": { | ||||||
|  |                     "rules": [ | ||||||
|  |                         {   "host": self.host, | ||||||
|  |                             "http": { | ||||||
|  |                                 "paths": [ | ||||||
|  |                                     { | ||||||
|  |                                         "path": path, | ||||||
|  |                                         "pathType": path_type.as_str(), | ||||||
|  |                                         "backend": [ | ||||||
|  |                                             { | ||||||
|  |                                                 "service": self.backend_service, | ||||||
|  |                                                 "port": self.port | ||||||
|  |                                             } | ||||||
|  |                                         ] | ||||||
|  |                                     } | ||||||
|  |                                 ] | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     ] | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         let ingress: Ingress = serde_json::from_value(ingress).unwrap(); | ||||||
|  |         Box::new(K8sResourceInterpret { | ||||||
|  |             score: K8sResourceScore::single( | ||||||
|  |                 ingress.clone(), | ||||||
|  |                 self.namespace | ||||||
|  |                     .clone() | ||||||
|  |                     .map(|f| f.as_c_str().to_str().unwrap().to_string()), | ||||||
|  |             ), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn name(&self) -> String { | ||||||
|  |         format!("{} K8sIngressScore", self.name) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,3 +1,4 @@ | |||||||
| pub mod deployment; | pub mod deployment; | ||||||
|  | pub mod ingress; | ||||||
| pub mod namespace; | pub mod namespace; | ||||||
| pub mod resource; | pub mod resource; | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| use convert_case::{Case, Casing}; | use convert_case::{Case, Casing}; | ||||||
| use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, WORKDIR}; | use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, WORKDIR}; | ||||||
| use dockerfile_builder::{Dockerfile, instruction_builder::EnvBuilder}; | use dockerfile_builder::{Dockerfile, instruction_builder::EnvBuilder}; | ||||||
|  | use fqdn::fqdn; | ||||||
|  | use harmony_macros::ingress_path; | ||||||
| use non_blank_string_rs::NonBlankString; | use non_blank_string_rs::NonBlankString; | ||||||
| use serde_json::json; | use serde_json::json; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| @ -13,6 +15,7 @@ use log::{debug, info}; | |||||||
| use serde::Serialize; | use serde::Serialize; | ||||||
| 
 | 
 | ||||||
| use crate::config::{REGISTRY_PROJECT, REGISTRY_URL}; | use crate::config::{REGISTRY_PROJECT, REGISTRY_URL}; | ||||||
|  | use crate::modules::k8s::ingress::K8sIngressScore; | ||||||
| use crate::topology::HelmCommand; | use crate::topology::HelmCommand; | ||||||
| use crate::{ | use crate::{ | ||||||
|     data::{Id, Version}, |     data::{Id, Version}, | ||||||
| @ -132,6 +135,29 @@ impl<T: Topology + K8sclient + HelmCommand> Interpret<T> for LAMPInterpret { | |||||||
| 
 | 
 | ||||||
|         info!("LAMP deployment_score {deployment_score:?}"); |         info!("LAMP deployment_score {deployment_score:?}"); | ||||||
| 
 | 
 | ||||||
|  |         let lamp_ingress = K8sIngressScore { | ||||||
|  |             name: fqdn!("lamp-ingress"), | ||||||
|  |             host: fqdn!("test"), | ||||||
|  |             backend_service: fqdn!( | ||||||
|  |                 <LAMPScore as Score<T>>::name(&self.score) | ||||||
|  |                     .to_case(Case::Kebab) | ||||||
|  |                     .as_str() | ||||||
|  |             ), | ||||||
|  |             port: 8080, | ||||||
|  |             path: Some(ingress_path!("/")), | ||||||
|  |             path_type: None, | ||||||
|  |             namespace: self | ||||||
|  |                 .get_namespace() | ||||||
|  |                 .map(|nbs| fqdn!(nbs.to_string().as_str())), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         lamp_ingress | ||||||
|  |             .create_interpret() | ||||||
|  |             .execute(inventory, topology) | ||||||
|  |             .await?; | ||||||
|  | 
 | ||||||
|  |         info!("LAMP lamp_ingress {lamp_ingress:?}"); | ||||||
|  | 
 | ||||||
|         Ok(Outcome::success( |         Ok(Outcome::success( | ||||||
|             "Successfully deployed LAMP Stack!".to_string(), |             "Successfully deployed LAMP Stack!".to_string(), | ||||||
|         )) |         )) | ||||||
|  | |||||||
| @ -116,3 +116,19 @@ pub fn yaml(input: TokenStream) -> TokenStream { | |||||||
|     } |     } | ||||||
|     .into() |     .into() | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /// Verify that a string is a valid(ish) ingress path
 | ||||||
|  | /// Panics if path does not start with `/`
 | ||||||
|  | #[proc_macro] | ||||||
|  | pub fn ingress_path(input: TokenStream) -> TokenStream { | ||||||
|  |     let input = parse_macro_input!(input as LitStr); | ||||||
|  |     let path_str = input.value(); | ||||||
|  | 
 | ||||||
|  |     match path_str.starts_with("/") { | ||||||
|  |         true => { | ||||||
|  |             let expanded = quote! {(#path_str.to_string()) }; | ||||||
|  |             return TokenStream::from(expanded); | ||||||
|  |         } | ||||||
|  |         false => panic!("Invalid ingress path"), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user