fix: modified cert-manager ensure ready to check for existence of pods with labels matching cert-manager in kubernetes env. replaced deprecated olm subscription based install of cert-manager for supported helm-chart #218

Merged
wjro merged 2 commits from fix/cert-manager into master 2026-01-23 16:28:34 +00:00
3 changed files with 61 additions and 41 deletions

View File

@@ -925,6 +925,27 @@ impl K8sClient {
api.get_opt(name).await
}
pub async fn list_all_resources_with_labels<K>(&self, labels: &str) -> Result<Vec<K>, Error>
where
K: Resource + Clone + std::fmt::Debug + DeserializeOwned,
<K as kube::Resource>::DynamicType: Default,
{
let api: Api<K> = Api::all(self.client.clone());
let lp = ListParams::default().labels(labels);
Ok(api.list(&lp).await?.items)
}
pub async fn get_all_resource_in_all_namespace<K>(&self) -> Result<Vec<K>, Error>
where
Review

Remove comment and make name more explicit

Remove comment and make name more explicit
K: Resource + Clone + std::fmt::Debug + DeserializeOwned,
<K as Resource>::Scope: ApplyStrategy<K>,
<K as kube::Resource>::DynamicType: Default,
{
let api: Api<K> = Api::all(self.client.clone());
Ok(api.list(&Default::default()).await?.items)
}
/// Lists all resources of a specific type `K`.
///
/// This function uses the `ApplyStrategy` trait to correctly determine

View File

@@ -4,7 +4,7 @@ use async_trait::async_trait;
use base64::{Engine, engine::general_purpose};
use harmony_types::rfc1123::Rfc1123Name;
use k8s_openapi::api::{
core::v1::Secret,
core::v1::{Pod, Secret},
rbac::v1::{ClusterRoleBinding, RoleRef, Subject},
};
use kube::api::{DynamicObject, GroupVersionKind, ObjectMeta};
@@ -28,10 +28,7 @@ use crate::{
score_cert_management::CertificateManagementScore,
},
k3d::K3DInstallationScore,
k8s::{
apps::crd::Subscription,
ingress::{K8sIngressScore, PathType},
},
k8s::ingress::{K8sIngressScore, PathType},
monitoring::{
grafana::{grafana::Grafana, helm::helm_grafana::grafana_helm_chart_score},
kube_prometheus::crd::{
@@ -376,7 +373,6 @@ impl Serialize for K8sAnywhereTopology {
impl CertificateManagement for K8sAnywhereTopology {
async fn install(&self) -> Result<Outcome, ExecutorError> {
let cert_management_operator = CertManagerOperatorScore::default();
cert_management_operator
.interpret(&Inventory::empty(), self)
.await
@@ -390,17 +386,21 @@ impl CertificateManagement for K8sAnywhereTopology {
async fn ensure_ready(&self) -> Result<Outcome, ExecutorError> {
let k8s_client = self.k8s_client().await.unwrap();
match k8s_client
.get_resource::<Subscription>("cert-manager", Some("openshift-operators"))
let pods = k8s_client
.list_all_resources_with_labels::<Pod>(
"app.kubernetes.io/component=controller,\
app.kubernetes.io/name=cert-manager",
)
.await
.map_err(|e| ExecutorError::UnexpectedError(format!("{}", e)))?
{
Some(subscription) => {
trace!("subscription {:#?}", subscription,);
Ok(Outcome::success(format!("Certificate Management Ready",)))
}
None => self.install().await,
.map_err(|e| ExecutorError::UnexpectedError(format!("{}", e)))?;
if pods.is_empty() {
info!("cert-manager not installed (no controller pods found)");
self.install().await
} else {
trace!("cert-manager controller pods found: {:#?}", pods);
Review

should be info since this has a major implication of installing a full thing

should be info since this has a major implication of installing a full thing
info!("cert-manager controller pods found");
Ok(Outcome::success("Certificate Management Ready".to_string()))
}
}

View File

@@ -1,18 +1,17 @@
use kube::api::ObjectMeta;
use std::{collections::HashMap, str::FromStr};
use non_blank_string_rs::NonBlankString;
use serde::Serialize;
use crate::{
interpret::Interpret,
modules::k8s::{
apps::crd::{Subscription, SubscriptionSpec},
resource::K8sResourceScore,
},
modules::helm::chart::HelmChartScore,
score::Score,
topology::{K8sclient, Topology, k8s::K8sClient},
topology::{HelmCommand, K8sclient, Topology},
};
/// Install the Cert-Manager Operator via RedHat Community Operators registry.redhat.io/redhat/community-operator-index:v4.19
/// This Score creates a Subscription CR in the specified namespace
/// Install the Cert-Manager Operator via helm chart
/// This Score installs the cert-manager CRs in the specified namespace
#[derive(Debug, Clone, Serialize)]
pub struct CertManagerOperatorScore {
@@ -35,30 +34,30 @@ impl Default for CertManagerOperatorScore {
}
}
impl<T: Topology + K8sclient> Score<T> for CertManagerOperatorScore {
impl<T: Topology + K8sclient + HelmCommand + 'static> Score<T> for CertManagerOperatorScore {
fn name(&self) -> String {
"CertManagerOperatorScore".to_string()
}
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
let metadata = ObjectMeta {
name: Some("cert-manager".to_string()),
namespace: Some(self.namespace.clone()),
..ObjectMeta::default()
let cert_manager_score = HelmChartScore {
namespace: Some(NonBlankString::from_str(&self.namespace.as_str()).unwrap()),
release_name: NonBlankString::from_str("cert-manager").unwrap(),
chart_name: NonBlankString::from_str("oci://quay.io/jetstack/charts/cert-manager")
.unwrap(),
chart_version: None,
values_overrides: Some(HashMap::from([(
NonBlankString::from_str("installCRDs").unwrap(),
"true".to_string(),
)])),
values_yaml: None,
create_namespace: true,
install_only: true,
repository: None,
};
let spec = SubscriptionSpec {
channel: Some(self.channel.clone()),
config: None,
install_plan_approval: Some(self.install_plan_approval.clone()),
name: "cert-manager".to_string(),
source: self.source.clone(),
source_namespace: self.source_namespace.clone(),
starting_csv: None,
};
let cert_score = cert_manager_score.create_interpret();
let subscription = Subscription { metadata, spec };
K8sResourceScore::single(subscription, Some(self.namespace.clone())).create_interpret()
cert_score
}
}