Compare commits

..

1 Commits

13 changed files with 64 additions and 49 deletions

16
Cargo.lock generated
View File

@@ -1776,6 +1776,21 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "example-multisite-postgres"
version = "0.1.0"
dependencies = [
"cidr",
"env_logger",
"harmony",
"harmony_cli",
"harmony_macros",
"harmony_types",
"log",
"tokio",
"url",
]
[[package]] [[package]]
name = "example-nanodc" name = "example-nanodc"
version = "0.1.0" version = "0.1.0"
@@ -2561,6 +2576,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"rand 0.9.2", "rand 0.9.2",
"serde", "serde",
"serde_json",
"url", "url",
] ]

View File

@@ -1,7 +1,7 @@
use harmony::{ use harmony::{
inventory::Inventory, inventory::Inventory,
modules::postgresql::{ modules::postgresql::{
capability::PostgreSQLConfig, K8sPostgreSQLScore, PublicPostgreSQLScore K8sPostgreSQLScore, PublicPostgreSQLScore, capability::PostgreSQLConfig,
}, },
topology::{FailoverTopology, K8sAnywhereTopology}, topology::{FailoverTopology, K8sAnywhereTopology},
}; };

View File

@@ -34,9 +34,10 @@ impl FailoverTopology<K8sAnywhereTopology> {
/// ///
/// Panics if required env vars are missing or malformed. /// Panics if required env vars are missing or malformed.
pub fn from_env() -> Self { pub fn from_env() -> Self {
let primary_config =
let primary_config = K8sAnywhereConfig::remote_k8s_from_env_var("HARMONY_FAILOVER_TOPOLOGY_K8S_PRIMARY"); K8sAnywhereConfig::remote_k8s_from_env_var("HARMONY_FAILOVER_TOPOLOGY_K8S_PRIMARY");
let replica_config = K8sAnywhereConfig::remote_k8s_from_env_var("HARMONY_FAILOVER_TOPOLOGY_K8S_REPLICA"); let replica_config =
K8sAnywhereConfig::remote_k8s_from_env_var("HARMONY_FAILOVER_TOPOLOGY_K8S_REPLICA");
let primary = K8sAnywhereTopology::with_config(primary_config); let primary = K8sAnywhereTopology::with_config(primary_config);
let replica = K8sAnywhereTopology::with_config(replica_config); let replica = K8sAnywhereTopology::with_config(replica_config);

View File

@@ -1131,10 +1131,11 @@ mod tests {
fn test_remote_k8s_from_env_var_full() { fn test_remote_k8s_from_env_var_full() {
let (config_var, profile_var) = setup_env_vars( let (config_var, profile_var) = setup_env_vars(
Some("kubeconfig=/foo.kc,context_name=bar"), Some("kubeconfig=/foo.kc,context_name=bar"),
Some("testprof") Some("testprof"),
); );
let cfg = K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var); let cfg =
K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var);
assert_eq!(cfg.kubeconfig.as_deref(), Some("/foo.kc")); assert_eq!(cfg.kubeconfig.as_deref(), Some("/foo.kc"));
assert_eq!(cfg.k8s_context.as_deref(), Some("bar")); assert_eq!(cfg.k8s_context.as_deref(), Some("bar"));
@@ -1146,12 +1147,10 @@ mod tests {
#[test] #[test]
fn test_remote_k8s_from_env_var_only_kubeconfig() { fn test_remote_k8s_from_env_var_only_kubeconfig() {
let (config_var, profile_var) = setup_env_vars( let (config_var, profile_var) = setup_env_vars(Some("kubeconfig=/foo.kc"), None);
Some("kubeconfig=/foo.kc"),
None
);
let cfg = K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var); let cfg =
K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var);
assert_eq!(cfg.kubeconfig.as_deref(), Some("/foo.kc")); assert_eq!(cfg.kubeconfig.as_deref(), Some("/foo.kc"));
assert_eq!(cfg.k8s_context, None); assert_eq!(cfg.k8s_context, None);
@@ -1160,12 +1159,10 @@ mod tests {
#[test] #[test]
fn test_remote_k8s_from_env_var_only_context() { fn test_remote_k8s_from_env_var_only_context() {
let (config_var, profile_var) = setup_env_vars( let (config_var, profile_var) = setup_env_vars(Some("context_name=bar"), None);
Some("context_name=bar"),
None
);
let cfg = K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var); let cfg =
K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var);
assert_eq!(cfg.kubeconfig, None); assert_eq!(cfg.kubeconfig, None);
assert_eq!(cfg.k8s_context.as_deref(), Some("bar")); assert_eq!(cfg.k8s_context.as_deref(), Some("bar"));
@@ -1175,10 +1172,11 @@ mod tests {
fn test_remote_k8s_from_env_var_unknown_key_trim() { fn test_remote_k8s_from_env_var_unknown_key_trim() {
let (config_var, profile_var) = setup_env_vars( let (config_var, profile_var) = setup_env_vars(
Some(" unknown=bla , kubeconfig= /foo.kc ,context_name= bar "), Some(" unknown=bla , kubeconfig= /foo.kc ,context_name= bar "),
None None,
); );
let cfg = K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var); let cfg =
K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var);
assert_eq!(cfg.kubeconfig.as_deref(), Some("/foo.kc")); assert_eq!(cfg.kubeconfig.as_deref(), Some("/foo.kc"));
assert_eq!(cfg.k8s_context.as_deref(), Some("bar")); assert_eq!(cfg.k8s_context.as_deref(), Some("bar"));
@@ -1186,12 +1184,10 @@ mod tests {
#[test] #[test]
fn test_remote_k8s_from_env_var_empty_malformed() { fn test_remote_k8s_from_env_var_empty_malformed() {
let (config_var, profile_var) = setup_env_vars( let (config_var, profile_var) = setup_env_vars(Some("malformed,no=,equal"), None);
Some("malformed,no=,equal"),
None
);
let cfg = K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var); let cfg =
K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var);
// Unknown/malformed ignored, defaults to None // Unknown/malformed ignored, defaults to None
assert_eq!(cfg.kubeconfig, None); assert_eq!(cfg.kubeconfig, None);
@@ -1207,12 +1203,10 @@ mod tests {
#[test] #[test]
fn test_remote_k8s_from_env_var_harmony_profile_default() { fn test_remote_k8s_from_env_var_harmony_profile_default() {
let (config_var, profile_var) = setup_env_vars( let (config_var, profile_var) = setup_env_vars(Some("kubeconfig=/foo"), None);
Some("kubeconfig=/foo"),
None
);
let cfg = K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var); let cfg =
K8sAnywhereConfig::remote_k8s_from_env_var_with_profile(&config_var, &profile_var);
assert_eq!(cfg.harmony_profile, "dev"); assert_eq!(cfg.harmony_profile, "dev");
} }

View File

@@ -3,8 +3,7 @@ use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use log::warn; use log::warn;
use crate::topology::{k8s::K8sClient, FailoverTopology, K8sclient}; use crate::topology::{FailoverTopology, K8sclient, k8s::K8sClient};
#[async_trait] #[async_trait]
impl<T: K8sclient> K8sclient for FailoverTopology<T> { impl<T: K8sclient> K8sclient for FailoverTopology<T> {
@@ -12,7 +11,9 @@ impl<T: K8sclient> K8sclient for FailoverTopology<T> {
// client, which will work in many cases but is clearly not good enough for all uses cases // client, which will work in many cases but is clearly not good enough for all uses cases
// where k8s_client can be used. Logging a warning for now. // where k8s_client can be used. Logging a warning for now.
async fn k8s_client(&self) -> Result<Arc<K8sClient>, String> { async fn k8s_client(&self) -> Result<Arc<K8sClient>, String> {
warn!("Failover topology k8s_client capability currently defers to the primary only. Make sure to check this is OK for you"); warn!(
"Failover topology k8s_client capability currently defers to the primary only. Make sure to check this is OK for you"
);
self.primary.k8s_client().await self.primary.k8s_client().await
} }
} }

View File

@@ -1,6 +1,6 @@
pub mod apps; pub mod apps;
pub mod deployment; pub mod deployment;
mod failover;
pub mod ingress; pub mod ingress;
pub mod namespace; pub mod namespace;
pub mod resource; pub mod resource;
mod failover;

View File

@@ -1,3 +1,3 @@
mod tls_router;
mod failover; mod failover;
mod tls_router;
pub use tls_router::*; pub use tls_router::*;

View File

@@ -88,7 +88,11 @@ impl<T: Topology + K8sclient> Score<T> for OKDTlsPassthroughScore {
}), }),
..Default::default() ..Default::default()
}; };
let route_score = OKDRouteScore::new(&self.name.to_string(), &self.route.namespace, passthrough_spec); let route_score = OKDRouteScore::new(
&self.name.to_string(),
&self.route.namespace,
passthrough_spec,
);
route_score.create_interpret() route_score.create_interpret()
} }

View File

@@ -1,6 +1,6 @@
pub mod capability; pub mod capability;
mod score_k8s;
mod score_connect; mod score_connect;
mod score_k8s;
pub use score_connect::*; pub use score_connect::*;
pub use score_k8s::*; pub use score_k8s::*;
mod score_public; mod score_public;

View File

@@ -1,5 +1,5 @@
pub mod id; pub mod id;
pub mod net; pub mod net;
pub mod rfc1123;
pub mod storage; pub mod storage;
pub mod switch; pub mod switch;
pub mod rfc1123;

View File

@@ -43,7 +43,9 @@ impl TryFrom<&str> for Rfc1123Name {
} }
// Trim leading/trailing non-alphanumeric // Trim leading/trailing non-alphanumeric
content = content.trim_matches(|c: char| !c.is_ascii_alphanumeric()).to_string(); content = content
.trim_matches(|c: char| !c.is_ascii_alphanumeric())
.to_string();
if content.is_empty() { if content.is_empty() {
return Err(format!("Input '{}' resulted in empty string", s)); return Err(format!("Input '{}' resulted in empty string", s));
@@ -55,7 +57,6 @@ impl TryFrom<&str> for Rfc1123Name {
type Error = String; type Error = String;
} }
/// Converts an `Rfc1123Name` into a `String`. /// Converts an `Rfc1123Name` into a `String`.
/// ///
/// This allows using `Rfc1123Name` in contexts where a `String` is expected. /// This allows using `Rfc1123Name` in contexts where a `String` is expected.
@@ -99,7 +100,6 @@ impl std::fmt::Display for Rfc1123Name {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Rfc1123Name; use super::Rfc1123Name;
@@ -229,4 +229,3 @@ mod tests {
assert_eq!(name.content, "a.b.c"); assert_eq!(name.content, "a.b.c");
} }
} }

View File

@@ -71,7 +71,7 @@ impl StorageSize {
Self { Self {
size_bytes: size * 1024 * 1024 * 1024 * 1024, size_bytes: size * 1024 * 1024 * 1024 * 1024,
display_value: Some(size), display_value: Some(size),
display_suffix: Some("TiB".to_string()), display_suffix: Some("Ti".to_string()),
} }
} }