From 85371c56ae92358f4c789731e65abffe0b3b6913 Mon Sep 17 00:00:00 2001 From: Ian Stanton Date: Wed, 11 Dec 2024 16:16:31 -0500 Subject: [PATCH] Remove IngressRoutes for stopped instances Signed-off-by: Ian Stanton --- tembo-operator/src/cloudnativepg/hibernate.rs | 41 ++++++++++++++---- tembo-operator/src/ingress.rs | 42 +++++++++++++++++++ tembo-operator/tests/integration_tests.rs | 17 ++++++-- 3 files changed, 90 insertions(+), 10 deletions(-) diff --git a/tembo-operator/src/cloudnativepg/hibernate.rs b/tembo-operator/src/cloudnativepg/hibernate.rs index 340ed019e..c7a8b279e 100644 --- a/tembo-operator/src/cloudnativepg/hibernate.rs +++ b/tembo-operator/src/cloudnativepg/hibernate.rs @@ -3,7 +3,7 @@ use crate::cloudnativepg::clusters::{ClusterStatusConditions, ClusterStatusCondi use crate::cloudnativepg::cnpg::{get_cluster, get_pooler, get_scheduled_backups}; use crate::cloudnativepg::poolers::Pooler; use crate::cloudnativepg::scheduledbackups::ScheduledBackup; -use crate::ingress::delete_ingress_route_tcp; +use crate::ingress::{delete_ingress_route, delete_ingress_route_tcp}; use crate::Error; use crate::{patch_cdb_status_merge, requeue_normal_with_jitter, Context}; @@ -14,17 +14,17 @@ use serde_json::json; use k8s_openapi::api::apps::v1::Deployment; +use super::clusters::Cluster; use crate::app_service::manager::get_appservice_deployment_objects; use crate::cloudnativepg::cnpg_utils::{ get_pooler_instances, patch_cluster_merge, patch_pooler_merge, patch_scheduled_backup_merge, removed_stalled_backups, }; +use crate::ingress_route_crd::IngressRoute; use std::sync::Arc; use std::time::Duration; use tracing::{debug, error, info, warn}; -use super::clusters::Cluster; - /// Resolves hibernation in the Cluster and related services of the CoreDB /// /// If the cluster is in spec.stop state, this will activate the CNPG hibernation @@ -146,6 +146,33 @@ pub async fn reconcile_cluster_hibernation(cdb: &CoreDB, ctx: &Arc) -> } } + // Remove IngressRoutes for stopped instances + let ingress_route_api: Api = Api::namespaced(ctx.client.clone(), &namespace); + if let Err(err) = delete_ingress_route(ingress_route_api.clone(), &namespace, &name).await { + warn!( + "Error deleting app service IngressRoute for {}: {}", + cdb.name_any(), + err + ); + return Err(Action::requeue(Duration::from_secs(300))); + } + + let metrics_ing_route_name = format!("{}-metrics", cdb.name_any().as_str()); + if let Err(err) = delete_ingress_route( + ingress_route_api.clone(), + &namespace, + &metrics_ing_route_name, + ) + .await + { + warn!( + "Error deleting metrics IngressRoute for {}: {}", + cdb.name_any(), + err + ); + return Err(Action::requeue(Duration::from_secs(300))); + } + // Remove IngressRouteTCP route for stopped instances let ingress_route_tcp_api = Api::namespaced(ctx.client.clone(), &namespace); let prefix_read_only = format!("{}-ro-0", cdb.name_any().as_str()); @@ -153,7 +180,7 @@ pub async fn reconcile_cluster_hibernation(cdb: &CoreDB, ctx: &Arc) -> delete_ingress_route_tcp(ingress_route_tcp_api.clone(), &namespace, &prefix_read_only).await { warn!( - "Error deleting postgres ingress route for {}: {}", + "Error deleting postgres IngressRouteTCP for {}: {}", cdb.name_any(), err ); @@ -169,7 +196,7 @@ pub async fn reconcile_cluster_hibernation(cdb: &CoreDB, ctx: &Arc) -> .await { warn!( - "Error deleting postgres ingress route for {}: {}", + "Error deleting postgres IngressRouteTCP for {}: {}", cdb.name_any(), err ); @@ -181,7 +208,7 @@ pub async fn reconcile_cluster_hibernation(cdb: &CoreDB, ctx: &Arc) -> delete_ingress_route_tcp(ingress_route_tcp_api.clone(), &namespace, &prefix_pooler).await { warn!( - "Error deleting postgres ingress route for {}: {}", + "Error deleting postgres IngressRouteTCP for {}: {}", cdb.name_any(), err ); @@ -195,7 +222,7 @@ pub async fn reconcile_cluster_hibernation(cdb: &CoreDB, ctx: &Arc) -> delete_ingress_route_tcp(ingress_route_tcp_api.clone(), &namespace, &prefix_extra).await { warn!( - "Error deleting extra postgres ingress route for {}: {}", + "Error deleting extra postgres IngressRouteTCP for {}: {}", cdb.name_any(), err ); diff --git a/tembo-operator/src/ingress.rs b/tembo-operator/src/ingress.rs index e1da9a22d..0568c8e6f 100644 --- a/tembo-operator/src/ingress.rs +++ b/tembo-operator/src/ingress.rs @@ -13,6 +13,7 @@ use kube::{ use regex::Regex; use std::sync::Arc; +use crate::ingress_route_crd::IngressRoute; use crate::{ apis::coredb_types::CoreDB, errors::OperatorError, @@ -196,6 +197,47 @@ async fn apply_ingress_route_tcp( Ok(()) } +pub async fn delete_ingress_route( + ingress_route_api: Api, + namespace: &str, + ingress_route_name: &String, +) -> Result<(), OperatorError> { + // Check if the resource exists + if ingress_route_api + .get(&ingress_route_name.clone()) + .await + .is_ok() + { + // If it exists, proceed with the deletion + let delete_parameters = DeleteParams::default(); + match ingress_route_api + .delete(&ingress_route_name.clone(), &delete_parameters) + .await + { + Ok(_) => { + info!( + "Deleted IngressRoute {}.{}", + ingress_route_name.clone(), + namespace + ); + } + Err(e) => { + error!( + "Failed to delete IngressRoute {}.{}: {}", + ingress_route_name, namespace, e + ); + return Err(OperatorError::IngressRouteError); + } + } + } else { + debug!( + "IngressRoute {}.{} was not found. Assuming it's already deleted.", + ingress_route_name, namespace + ); + } + Ok(()) +} + pub async fn delete_ingress_route_tcp( ingress_route_tcp_api: Api, namespace: &str, diff --git a/tembo-operator/tests/integration_tests.rs b/tembo-operator/tests/integration_tests.rs index d570ca3bf..743741bab 100644 --- a/tembo-operator/tests/integration_tests.rs +++ b/tembo-operator/tests/integration_tests.rs @@ -5851,8 +5851,7 @@ CREATE EVENT TRIGGER pgrst_watch .await .not()); - // Assert that ingress routes are removed after hibernation - + // Assert that IngressRouteTCPs are removed after hibernation let client = test.client.clone(); let ingresses_tcp: Vec = list_resources(client.clone(), &name, &namespace, 0) @@ -5861,7 +5860,19 @@ CREATE EVENT TRIGGER pgrst_watch assert_eq!( ingresses_tcp.len(), 0, - "Ingress routes should be removed after hibernation" + "IngressRouteTCPs should be removed after hibernation" + ); + + // Assert that IngressRoutes are removed after hibernation + let client = test.client.clone(); + let ingress_routes: Vec = + list_resources(client.clone(), &name, &namespace, 0) + .await + .unwrap(); + assert_eq!( + ingress_routes.len(), + 0, + "IngressRoutes should be removed after hibernation" ); // Patch the cluster to start it up again, then check to ensure it