From e9e4c160e2c71b298d6f79254742eed0b7a37c45 Mon Sep 17 00:00:00 2001 From: Techassi Date: Mon, 27 Apr 2026 15:12:35 +0200 Subject: [PATCH 1/6] feat: Support dynamic image repositories --- Cargo.lock | 25 ++++++++-------- Cargo.nix | 30 ++++++++++++-------- Cargo.toml | 2 +- crate-hashes.json | 18 ++++++------ extra/crds.yaml | 17 +++++++---- rust/operator-binary/src/druid_controller.rs | 16 +++++++++-- rust/operator-binary/src/main.rs | 1 + 7 files changed, 67 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e2587fbc..028d2b4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1539,7 +1539,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "darling", "regex", @@ -2934,7 +2934,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "const-oid", "ecdsa", @@ -2983,8 +2983,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.110.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +version = "0.111.0" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "base64", "clap", @@ -3025,7 +3025,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "darling", "proc-macro2", @@ -3036,7 +3036,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.1.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "jiff", "k8s-openapi", @@ -3053,7 +3053,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "axum", "clap", @@ -3076,9 +3076,10 @@ dependencies = [ [[package]] name = "stackable-versioned" -version = "0.9.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +version = "0.10.0" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ + "kube", "schemars", "serde", "serde_json", @@ -3089,8 +3090,8 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" -version = "0.9.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +version = "0.10.0" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "convert_case", "convert_case_extras", @@ -3108,7 +3109,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.9.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#96f42571ea185a3cd76fedde351fcabbeefcae16" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 7b791636..849bca72 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -4890,7 +4890,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "k8s_version"; @@ -9633,7 +9633,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_certs"; @@ -9840,12 +9840,12 @@ rec { }; "stackable-operator" = rec { crateName = "stackable-operator"; - version = "0.110.1"; + version = "0.111.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_operator"; @@ -10025,7 +10025,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; procMacro = true; @@ -10060,7 +10060,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_shared"; @@ -10141,7 +10141,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_telemetry"; @@ -10246,12 +10246,12 @@ rec { }; "stackable-versioned" = rec { crateName = "stackable-versioned"; - version = "0.9.0"; + version = "0.10.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_versioned"; @@ -10259,6 +10259,12 @@ rec { "Stackable GmbH " ]; dependencies = [ + { + name = "kube"; + packageId = "kube"; + usesDefaultFeatures = false; + features = [ "client" "jsonpatch" "runtime" "derive" "admission" "rustls-tls" "ring" ]; + } { name = "schemars"; packageId = "schemars"; @@ -10290,12 +10296,12 @@ rec { }; "stackable-versioned-macros" = rec { crateName = "stackable-versioned-macros"; - version = "0.9.0"; + version = "0.10.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; procMacro = true; @@ -10363,7 +10369,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "b7c8a3a5483b4d35d0abfa11f6db6c153bda8a51"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_webhook"; diff --git a/Cargo.toml b/Cargo.toml index dee8f8ca..3e7fa478 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/stackabletech/druid-operator" [workspace.dependencies] product-config = { git = "https://github.com/stackabletech/product-config.git", tag = "0.8.0" } -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.110.1", features = ["crds", "webhook"] } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.111.0", features = ["crds", "webhook"] } anyhow = "1.0" built = { version = "0.8", features = ["chrono", "git2"] } diff --git a/crate-hashes.json b/crate-hashes.json index e19b553d..4ab79fa6 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,12 +1,12 @@ { - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#k8s-version@0.1.3": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-certs@0.4.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-operator-derive@0.3.1": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-operator@0.110.1": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-shared@0.1.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-telemetry@0.6.3": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-versioned-macros@0.9.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-versioned@0.9.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.110.1#stackable-webhook@0.9.1": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#k8s-version@0.1.3": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-certs@0.4.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-operator-derive@0.3.1": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-operator@0.111.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-shared@0.1.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-telemetry@0.6.3": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-versioned-macros@0.10.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-versioned@0.10.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.0#stackable-webhook@0.9.1": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", "git+https://github.com/stackabletech/product-config.git?tag=0.8.0#product-config@0.8.0": "1dz70kapm2wdqcr7ndyjji0lhsl98bsq95gnb2lw487wf6yr7987" } \ No newline at end of file diff --git a/extra/crds.yaml b/extra/crds.yaml index 959d6c31..19ee5312 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -3575,8 +3575,9 @@ spec: properties: custom: description: |- - Overwrite the docker image. - Specify the full docker image name, e.g. `oci.stackable.tech/sdp/superset:1.4.1-stackable2.1.0` + Provide a custom container image. + + Specify the full container image name, e.g. `oci.example.tech/namespace/superset:1.4.1-my-tag` type: string productVersion: description: Version of the product, e.g. `1.4.1`. @@ -3603,14 +3604,20 @@ spec: nullable: true type: array repo: - description: Name of the docker repo, e.g. `oci.stackable.tech/sdp` + description: |- + The repository on the container image registry where the container image is located, e.g. + `oci.example.com/namespace`. + + If not specified, the operator will use the image registry provided via the operator + environment options. nullable: true type: string stackableVersion: description: |- Stackable version of the product, e.g. `23.4`, `23.4.1` or `0.0.0-dev`. - If not specified, the operator will use its own version, e.g. `23.4.1`. - When using a nightly operator or a pr version, it will use the nightly `0.0.0-dev` image. + + If not specified, the operator will use its own version, e.g. `23.4.1`. When using a nightly + operator or a PR version, it will use the nightly `0.0.0-dev` image. nullable: true type: string type: object diff --git a/rust/operator-binary/src/druid_controller.rs b/rust/operator-binary/src/druid_controller.rs index 819665c2..4b56971e 100644 --- a/rust/operator-binary/src/druid_controller.rs +++ b/rust/operator-binary/src/druid_controller.rs @@ -24,6 +24,7 @@ use stackable_operator::{ security::PodSecurityContextBuilder, volume::VolumeBuilder, }, }, + cli::OperatorEnvironmentOptions, cluster_resources::{ClusterResourceApplyStrategy, ClusterResources}, commons::{ opa::OpaApiVersion, @@ -95,7 +96,7 @@ use crate::{ pub const DRUID_CONTROLLER_NAME: &str = "druidcluster"; pub const FULL_CONTROLLER_NAME: &str = concatcp!(DRUID_CONTROLLER_NAME, '.', OPERATOR_NAME); -const DOCKER_IMAGE_BASE_NAME: &str = "druid"; +const CONTAINER_IMAGE_BASE_NAME: &str = "druid"; // volume names const DRUID_CONFIG_VOLUME_NAME: &str = "config"; @@ -108,6 +109,7 @@ const USERDATA_MOUNTPOINT: &str = "/stackable/userdata"; pub struct Ctx { pub client: stackable_operator::client::Client, pub product_config: ProductConfigManager, + pub operator_environment: OperatorEnvironmentOptions, } #[derive(Snafu, Debug, EnumDiscriminants)] @@ -414,7 +416,11 @@ pub async fn reconcile_druid( let resolved_product_image = druid .spec .image - .resolve(DOCKER_IMAGE_BASE_NAME, crate::built_info::PKG_VERSION) + .resolve( + CONTAINER_IMAGE_BASE_NAME, + &ctx.operator_environment.image_repository, + crate::built_info::PKG_VERSION, + ) .context(ResolveProductImageSnafu)?; let zk_confmap = druid.spec.cluster_config.zookeeper_config_map_name.clone(); @@ -1421,7 +1427,11 @@ mod test { let resolved_product_image: ResolvedProductImage = druid .spec .image - .resolve(DOCKER_IMAGE_BASE_NAME, crate::built_info::PKG_VERSION) + .resolve( + CONTAINER_IMAGE_BASE_NAME, + "oci.example.org", + crate::built_info::PKG_VERSION, + ) .expect("test: resolved product image is always valid"); let role_config = transform_all_roles_to_config(&druid, &druid.build_role_properties()); diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 65bdaccc..cd74f3dc 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -165,6 +165,7 @@ async fn main() -> anyhow::Result<()> { druid_controller::error_policy, Arc::new(druid_controller::Ctx { client: client.clone(), + operator_environment, product_config, }), ) From 08946e39c1d0386570ddd44ec816cc7b9afd6e34 Mon Sep 17 00:00:00 2001 From: Techassi Date: Mon, 27 Apr 2026 15:15:08 +0200 Subject: [PATCH 2/6] test: Add placeholder values to satify roundtrip tests --- rust/operator-binary/src/crd/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 4c202368..36ad2ef3 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -1729,6 +1729,10 @@ where #[cfg(test)] mod tests { + use stackable_operator::versioned::test_utils::RoundtripTestData; + + use crate::crd::v1alpha1; + pub fn deserialize_yaml_str<'a, T: serde::de::Deserialize<'a>>(value: &'a str) -> T { let deserializer = serde_yaml::Deserializer::from_str(value); serde_yaml::with::singleton_map_recursive::deserialize(deserializer).unwrap() @@ -1739,4 +1743,10 @@ mod tests { let deserializer = serde_yaml::Deserializer::from_reader(file); serde_yaml::with::singleton_map_recursive::deserialize(deserializer).unwrap() } + + impl RoundtripTestData for v1alpha1::DruidClusterSpec { + fn roundtrip_test_data() -> Vec { + vec![] + } + } } From 04ded1e955f67564fb7a88fc2899826256756776 Mon Sep 17 00:00:00 2001 From: Techassi Date: Mon, 27 Apr 2026 15:30:45 +0200 Subject: [PATCH 3/6] fix: Bump rustls-webpki to 0.103.13 to negate RUSTSEC-2026-0104 --- Cargo.lock | 4 ++-- Cargo.nix | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 028d2b4f..7248e70c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2547,9 +2547,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.12" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", diff --git a/Cargo.nix b/Cargo.nix index 849bca72..875c5924 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -8464,9 +8464,9 @@ rec { }; "rustls-webpki" = rec { crateName = "rustls-webpki"; - version = "0.103.12"; + version = "0.103.13"; edition = "2021"; - sha256 = "01nxzkfd1l96jzp04svc7iznlkarzx3wb9p63a0i17rc4y2vnyc2"; + sha256 = "0vkm7z9pnxz5qz66p2kmyy2pwx0g4jnsbqk5xzfhs4czcjl2ki31"; libName = "webpki"; dependencies = [ { From 588c1780641a3832deeeedd126791bccc67f9a5d Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 27 Apr 2026 16:41:09 +0200 Subject: [PATCH 4/6] test: Use yaml_from_str_singleton_map helper instead of defining own --- rust/operator-binary/src/crd/mod.rs | 11 ----------- rust/operator-binary/src/crd/resource.rs | 16 +++++++++------- rust/operator-binary/src/crd/tls.rs | 23 ++++++++++++----------- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 36ad2ef3..4d106a11 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -1733,17 +1733,6 @@ mod tests { use crate::crd::v1alpha1; - pub fn deserialize_yaml_str<'a, T: serde::de::Deserialize<'a>>(value: &'a str) -> T { - let deserializer = serde_yaml::Deserializer::from_str(value); - serde_yaml::with::singleton_map_recursive::deserialize(deserializer).unwrap() - } - - pub fn deserialize_yaml_file<'a, T: serde::de::Deserialize<'a>>(path: &'a str) -> T { - let file = std::fs::File::open(path).unwrap(); - let deserializer = serde_yaml::Deserializer::from_reader(file); - serde_yaml::with::singleton_map_recursive::deserialize(deserializer).unwrap() - } - impl RoundtripTestData for v1alpha1::DruidClusterSpec { fn roundtrip_test_data() -> Vec { vec![] diff --git a/rust/operator-binary/src/crd/resource.rs b/rust/operator-binary/src/crd/resource.rs index 90054d5a..e2d6bfb2 100644 --- a/rust/operator-binary/src/crd/resource.rs +++ b/rust/operator-binary/src/crd/resource.rs @@ -252,13 +252,13 @@ mod test { }, k8s_openapi::apimachinery::pkg::api::resource::Quantity, role_utils::{CommonConfiguration, RoleGroup}, + utils::yaml_from_str_singleton_map, }; use super::*; use crate::crd::{ MiddleManagerConfig, storage::{HistoricalStorage, default_free_percentage_empty_dir}, - tests::deserialize_yaml_file, v1alpha1, }; @@ -406,9 +406,10 @@ mod test { #[test] fn test_resources() -> Result<(), Error> { - let cluster = deserialize_yaml_file::( - "test/resources/crd/resource_merge/druid_cluster.yaml", - ); + let cluster: v1alpha1::DruidCluster = yaml_from_str_singleton_map(include_str!( + "../../test/resources/crd/resource_merge/druid_cluster.yaml" + )) + .expect("failed to parse YAML"); let config = cluster.merged_config().unwrap(); if let Some(RoleGroup { @@ -482,9 +483,10 @@ mod test { #[test] fn test_segment_cache() -> Result<(), Error> { - let cluster = deserialize_yaml_file::( - "test/resources/crd/resource_merge/segment_cache.yaml", - ); + let cluster: v1alpha1::DruidCluster = yaml_from_str_singleton_map(include_str!( + "../../test/resources/crd/resource_merge/segment_cache.yaml" + )) + .expect("failed to parse YAML"); // ---------- default role group let config = cluster.merged_config().unwrap(); diff --git a/rust/operator-binary/src/crd/tls.rs b/rust/operator-binary/src/crd/tls.rs index b4fc25b3..3a9fa431 100644 --- a/rust/operator-binary/src/crd/tls.rs +++ b/rust/operator-binary/src/crd/tls.rs @@ -32,8 +32,9 @@ pub fn tls_default() -> Option { #[cfg(test)] mod tests { use indoc::formatdoc; + use stackable_operator::utils::yaml_from_str_singleton_map; - use crate::crd::{tests::deserialize_yaml_str, tls::DruidTls, v1alpha1::DruidClusterConfig}; + use crate::crd::{tls::DruidTls, v1alpha1::DruidClusterConfig}; const BASE_DRUID_CONFIGURATION: &str = r#" deepStorage: @@ -50,8 +51,8 @@ zookeeperConfigMapName: zk-config-map #[test] fn test_tls_default() { - let druid_cluster_config = - deserialize_yaml_str::(BASE_DRUID_CONFIGURATION); + let druid_cluster_config: DruidClusterConfig = + yaml_from_str_singleton_map(BASE_DRUID_CONFIGURATION).expect("failed to parse YAML"); assert_eq!( druid_cluster_config.tls, @@ -69,8 +70,8 @@ zookeeperConfigMapName: zk-config-map tls: serverAndInternalSecretClass: druid-secret-class "}; - dbg!(&input); - let druid_cluster_config = deserialize_yaml_str::(&input); + let druid_cluster_config: DruidClusterConfig = + yaml_from_str_singleton_map(&input).expect("failed to parse YAML"); assert_eq!( druid_cluster_config.tls, @@ -87,8 +88,8 @@ zookeeperConfigMapName: zk-config-map {BASE_DRUID_CONFIGURATION} tls: null "}; - dbg!(&input); - let druid_cluster_config = deserialize_yaml_str::(&input); + let druid_cluster_config: DruidClusterConfig = + yaml_from_str_singleton_map(&input).expect("failed to parse YAML"); assert_eq!(druid_cluster_config.tls, None,); assert_eq!(druid_cluster_config.authentication, vec![]); @@ -101,8 +102,8 @@ zookeeperConfigMapName: zk-config-map tls: serverAndInternalSecretClass: null "}; - dbg!(&input); - let druid_cluster_config = deserialize_yaml_str::(&input); + let druid_cluster_config: DruidClusterConfig = + yaml_from_str_singleton_map(&input).expect("failed to parse YAML"); assert_eq!( druid_cluster_config.tls, @@ -122,8 +123,8 @@ zookeeperConfigMapName: zk-config-map authentication: - authenticationClass: druid-user-authentication-class "}; - dbg!(&input); - let druid_cluster_config = deserialize_yaml_str::(&input); + let druid_cluster_config: DruidClusterConfig = + yaml_from_str_singleton_map(&input).expect("failed to parse YAML"); assert_eq!( druid_cluster_config.tls, From eb489debcf1796849ae5db8117baab627b36d08d Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 27 Apr 2026 16:42:38 +0200 Subject: [PATCH 5/6] test: Add CRD roundtrip test data --- rust/operator-binary/src/crd/mod.rs | 74 ++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 4d106a11..7b5a0e81 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -1735,7 +1735,79 @@ mod tests { impl RoundtripTestData for v1alpha1::DruidClusterSpec { fn roundtrip_test_data() -> Vec { - vec![] + stackable_operator::utils::yaml_from_str_singleton_map(indoc::indoc! {" + - image: + productVersion: 30.0.0 + pullPolicy: IfNotPresent + clusterOperation: + stopped: false + reconciliationPaused: false + clusterConfig: + metadataStorageDatabase: + dbType: postgresql + connString: jdbc:postgresql://druid-postgresql/druid + host: druid-postgresql + port: 5432 + credentialsSecret: druid-credentials + # metadataDatabase: + # postgresql: + # host: druid-postgresql + # database: druid + # credentialsSecretName: mySecret + deepStorage: + hdfs: + configMapName: simple-hdfs + directory: /druid + ingestion: + s3connection: + inline: + host: s3-de-central.profitbricks.com + credentials: + secretClass: s3-credentials-class + zookeeperConfigMapName: simple-druid-znode + authorization: + opa: + configMapName: test-opa + package: druid + vectorAggregatorConfigMapName: vector-aggregator-discovery + brokers: + config: + gracefulShutdownTimeout: 1s + logging: + enableVectorAgent: true + containers: + druid: + console: + level: INFO + file: + level: INFO + loggers: + ROOT: + level: INFO + configOverrides: + runtime.properties: &runtime-properties + druid.foo: bar + roleGroups: + default: + replicas: 1 + coordinators: + roleGroups: + default: + replicas: 1 + historicals: + roleGroups: + default: + replicas: 1 + middleManagers: + roleGroups: + default: + replicas: 1 + routers: + roleGroups: + default: + replicas: 1 + "}) + .expect("Failed to parse DruidClusterSpec YAML") } } } From 094d7a33094bdcabf8e453e0b19a0969eeaec81f Mon Sep 17 00:00:00 2001 From: Techassi Date: Tue, 28 Apr 2026 12:39:59 +0200 Subject: [PATCH 6/6] chore: Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68fbd577..1a5e8898 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ### Added +- BREAKING: Add required CLI argument and env var to set the image repository used to construct final product image names: `IMAGE_REPOSITORY` (`--image-repository`), eg. `oci.example.org/my/namespace` ([#818]). - Support OIDC `clientAuthenticationMethod` configuration ([#813]). ### Changed @@ -16,6 +17,7 @@ All notable changes to this project will be documented in this file. [#810]: https://github.com/stackabletech/druid-operator/pull/810 [#813]: https://github.com/stackabletech/druid-operator/pull/813 +[#818]: https://github.com/stackabletech/druid-operator/pull/818 ## [26.3.0] - 2026-03-16