diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bbfa201..82de67d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - Added Listener operator to supported operators ([#143](https://github.com/stackabletech/stackablectl/pull/143)) +- Detect IONOS managed Stackable clusters and skip installing releases ([#147](https://github.com/stackabletech/stackablectl/pull/147)) ## [0.5.0] - 2022-09-14 diff --git a/Cargo.lock b/Cargo.lock index 0aa51867..277eb8a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1399,6 +1399,7 @@ dependencies = [ "lazy_static", "log", "openssl", + "regex", "reqwest", "semver", "serde", diff --git a/Cargo.toml b/Cargo.toml index 136d5ea2..14b1af44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ kube = "0.74" # Using openssl (and not native-tls) as kube-rs team tries to move lazy_static = "1.4" log = "0.4" openssl = { version = "0.10.36", features = ["vendored"] } # Must match version from kube +regex = "1.6" which = "4.2" semver = "1.0" serde = { version = "1.0", features = ["derive"]} diff --git a/src/ionos.rs b/src/ionos.rs new file mode 100644 index 00000000..92d3bf0d --- /dev/null +++ b/src/ionos.rs @@ -0,0 +1,36 @@ +use std::error::Error; + +use k8s_openapi::api::apps::v1::Deployment; +use kube::{api::ListParams, Api, ResourceExt}; +use lazy_static::lazy_static; +use regex::Regex; + +/// We asked the IONOS guys and agreed an this way of identifying a managed stackable cluster +/// One idea was to give the Namespace `stackable-operators` as special label +/// +/// The current solution lists the deployment in the `stackable-operators` namespace and searches for matching names +/// This not the ideal solution and should be improved when there are better points of identifying a managed stackable cluster +pub async fn detect_ionos_managed_stackable_operators() -> Result, Box> { + lazy_static! { + static ref OPERATOR_DEPLOYMENT_REGEX: Regex = + Regex::new("dp-[0-9a-f]{20}-([a-z-]+)-operator-deployment").unwrap(); + } + + let mut operators = Vec::new(); + + let client = crate::kube::get_client().await?; + let deployments = Api::::namespaced(client, "stackable-operators") + .list(&ListParams::default()) + .await?; + for deployment in deployments { + let deployment_name = deployment.name_unchecked(); + if let Some(operator_name) = OPERATOR_DEPLOYMENT_REGEX + .captures(&deployment_name) + .and_then(|cap| cap.get(1).map(|m| m.as_str())) + { + operators.push(operator_name.to_string()); + } + } + + Ok(operators) +} diff --git a/src/main.rs b/src/main.rs index 4eac73dd..4808143c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod arguments; mod demo; mod helm; mod helpers; +mod ionos; mod kind; mod kube; mod operator; diff --git a/src/release.rs b/src/release.rs index 890878a3..e336d573 100644 --- a/src/release.rs +++ b/src/release.rs @@ -1,4 +1,4 @@ -use crate::{arguments::OutputType, helpers, kind, operator, operator::Operator, CliArgs}; +use crate::{arguments::OutputType, helpers, ionos, kind, operator, operator::Operator, CliArgs}; use cached::proc_macro::cached; use clap::{ArgGroup, Parser, ValueHint}; use indexmap::IndexMap; @@ -201,6 +201,15 @@ pub async fn install_release( include_products: &[String], exclude_products: &[String], ) -> Result<(), Box> { + let managed_stackable_operators = ionos::detect_ionos_managed_stackable_operators().await?; + if !managed_stackable_operators.is_empty() { + warn!("stackablectl detected that you are running on a managed Stackable cluster operated by IONOS. \ + As IONOS has installed the Stackable operators already, stackablectl is not going to install them a second time. \ + Please make sure that your managed Stackable cluster uses the same Stackable operator versions as the release {release_name}. \ + You can list the Stackable operator versions of the {release_name} release using `stackablectl release describe {release_name}`."); + return Ok(()); + } + info!("Installing release {release_name}"); let release = get_release(release_name).await;