From e7946cf3699e3baa244a00176b4ec6cfc93fc910 Mon Sep 17 00:00:00 2001 From: Techassi Date: Tue, 12 May 2026 09:51:55 +0200 Subject: [PATCH 1/5] 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/controller.rs | 18 +++++++-- .../src/controller/validate.rs | 38 +++++++++++++++---- rust/operator-binary/src/main.rs | 3 +- 8 files changed, 101 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d44cf07c..ad93da41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1532,7 +1532,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "darling", "regex", @@ -2916,7 +2916,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "const-oid", "ecdsa", @@ -2961,8 +2961,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.1" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "base64", "clap", @@ -3003,7 +3003,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "darling", "proc-macro2", @@ -3014,7 +3014,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "jiff", "k8s-openapi", @@ -3031,7 +3031,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "axum", "clap", @@ -3054,9 +3054,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ + "kube", "schemars", "serde", "serde_json", @@ -3067,8 +3068,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "convert_case", "convert_case_extras", @@ -3086,7 +3087,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.1#7a5f0c3fbcd091340214a23f0607fcd4b4fcc152" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index c4ed3a5b..7c479ff8 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -4884,7 +4884,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "k8s_version"; @@ -9596,7 +9596,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_certs"; @@ -9789,12 +9789,12 @@ rec { }; "stackable-operator" = rec { crateName = "stackable-operator"; - version = "0.110.1"; + version = "0.111.1"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_operator"; @@ -9974,7 +9974,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; procMacro = true; @@ -10009,7 +10009,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_shared"; @@ -10090,7 +10090,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_telemetry"; @@ -10195,12 +10195,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 = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_versioned"; @@ -10208,6 +10208,12 @@ rec { "Stackable GmbH " ]; dependencies = [ + { + name = "kube"; + packageId = "kube"; + usesDefaultFeatures = false; + features = [ "client" "jsonpatch" "runtime" "derive" "admission" "rustls-tls" "ring" ]; + } { name = "schemars"; packageId = "schemars"; @@ -10239,12 +10245,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 = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; procMacro = true; @@ -10312,7 +10318,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "96f42571ea185a3cd76fedde351fcabbeefcae16"; + rev = "7a5f0c3fbcd091340214a23f0607fcd4b4fcc152"; sha256 = "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by"; }; libName = "stackable_webhook"; diff --git a/Cargo.toml b/Cargo.toml index c1a284bb..91d645f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ edition = "2024" repository = "https://github.com/stackabletech/opensearch-operator" [workspace.dependencies] -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.110.1", features = ["webhook"] } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.111.1", features = ["webhook"] } built = { version = "0.8.0", features = ["chrono", "git2"] } clap = "4.5" diff --git a/crate-hashes.json b/crate-hashes.json index e19b553d..a6396ca0 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.1#k8s-version@0.1.3": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#stackable-certs@0.4.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#stackable-operator-derive@0.3.1": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#stackable-operator@0.111.1": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#stackable-shared@0.1.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#stackable-telemetry@0.6.3": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#stackable-versioned-macros@0.10.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#stackable-versioned@0.10.0": "0d58yvxvy8hbai12bjhcyvh4zw182j5dsfyqja4k2xc1vzjy29by", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.111.1#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 547d5228..f73fdda8 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -1207,8 +1207,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`. @@ -1235,14 +1236,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/controller.rs b/rust/operator-binary/src/controller.rs index a686ee6b..b6c65f87 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -15,6 +15,7 @@ use build::build; use dereference::dereference; use snafu::{ResultExt, Snafu}; use stackable_operator::{ + cli::OperatorEnvironmentOptions, cluster_resources::ClusterResourceApplyStrategy, commons::{ affinity::StackableAffinity, networking::DomainName, @@ -80,16 +81,22 @@ pub struct ContextNames { /// The controller context pub struct Context { + operator_environment: OperatorEnvironmentOptions, client: stackable_operator::client::Client, names: ContextNames, } impl Context { - pub fn new(client: stackable_operator::client::Client, operator_name: OperatorName) -> Self { + pub fn new( + client: stackable_operator::client::Client, + operator_environment: OperatorEnvironmentOptions, + operator_name: OperatorName, + ) -> Self { let cluster_domain_name = client.kubernetes_cluster_info.cluster_domain.clone(); Context { client, + operator_environment, names: Self::context_names(operator_name, cluster_domain_name), } } @@ -454,8 +461,13 @@ pub async fn reconcile( let preprocessed_cluster = preprocess(cluster); // validate (no client required) - let validated_cluster = validate(&context.names, &preprocessed_cluster, &dereferenced_objects) - .context(ValidateClusterSnafu)?; + let validated_cluster = validate( + &context.names, + &context.operator_environment, + &preprocessed_cluster, + &dereferenced_objects, + ) + .context(ValidateClusterSnafu)?; // build (no client required; infallible) let prepared_resources = build(&context.names, validated_cluster.clone()); diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index ce37a499..ac0330f6 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -4,8 +4,8 @@ use std::{collections::BTreeMap, str::FromStr}; use snafu::{OptionExt, ResultExt, Snafu, ensure}; use stackable_operator::{ - crd::listener, kube::ResourceExt, product_logging::spec::Logging, role_utils::RoleGroup, - shared::time::Duration, + cli::OperatorEnvironmentOptions, crd::listener, kube::ResourceExt, + product_logging::spec::Logging, role_utils::RoleGroup, shared::time::Duration, }; use strum::{EnumDiscriminants, IntoStaticStr}; @@ -124,7 +124,7 @@ pub enum Error { type Result = std::result::Result; -const DEFAULT_IMAGE_BASE_NAME: &str = "opensearch"; +const CONTAINER_IMAGE_BASE_NAME: &str = "opensearch"; /// Validates the [`v1alpha1::OpenSearchCluster`] and returns a [`ValidatedCluster`] /// @@ -135,6 +135,7 @@ const DEFAULT_IMAGE_BASE_NAME: &str = "opensearch"; /// already be dereferenced in a prior step. pub fn validate( context_names: &ContextNames, + operator_environment: &OperatorEnvironmentOptions, cluster: &v1alpha1::OpenSearchCluster, dereferenced_objects: &DereferencedObjects, ) -> Result { @@ -145,7 +146,11 @@ pub fn validate( let product_image = cluster .spec .image - .resolve(DEFAULT_IMAGE_BASE_NAME, crate::built_info::PKG_VERSION) + .resolve( + CONTAINER_IMAGE_BASE_NAME, + &operator_environment.image_repository, + crate::built_info::PKG_VERSION, + ) .context(ResolveProductImageSnafu)?; // Cannot fail because `ProductImage::resolve` already validated it and would have thrown a @@ -433,6 +438,7 @@ mod tests { use pretty_assertions::assert_eq; use serde_json::json; use stackable_operator::{ + cli::OperatorEnvironmentOptions, commons::{ affinity::StackableAffinity, cluster_operation::ClusterOperation, @@ -492,7 +498,12 @@ mod tests { #[test] fn test_validate_ok() { - let result = validate(&context_names(), &cluster(), &dereferenced_objects()); + let result = validate( + &context_names(), + &operator_environment(), + &cluster(), + &dereferenced_objects(), + ); assert_eq!( Some(ValidatedCluster::new( @@ -504,7 +515,7 @@ mod tests { )) .expect("should be a valid label value"), image: format!( - "oci.stackable.tech/sdp/opensearch:3.4.0-stackable{pkg_version}", + "oci.example.org/opensearch:3.4.0-stackable{pkg_version}", pkg_version = built_info::PKG_VERSION ), image_pull_policy: "Always".to_owned(), @@ -973,7 +984,12 @@ mod tests { let mut dereferenced_objects = dereferenced_objects(); change_test_objects(&mut cluster, &mut dereferenced_objects); - let result = validate(&context_names(), &cluster, &dereferenced_objects); + let result = validate( + &context_names(), + &operator_environment(), + &cluster, + &dereferenced_objects, + ); assert_eq!(Err(expected_err), result.map_err(ErrorDiscriminants::from)); } @@ -988,6 +1004,14 @@ mod tests { } } + fn operator_environment() -> OperatorEnvironmentOptions { + OperatorEnvironmentOptions { + operator_namespace: "stackable_operators".to_owned(), + operator_service_name: "opensearch-operator".to_owned(), + image_repository: "oci.example.org".to_owned(), + } + } + fn cluster() -> v1alpha1::OpenSearchCluster { v1alpha1::OpenSearchCluster { metadata: ObjectMeta { diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 1db46e37..b06ba779 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -172,7 +172,8 @@ async fn main() -> Result<()> { .run(sigterm_watcher.handle()) .context(RunWebhookSnafu); - let controller_context = controller::Context::new(client.clone(), operator_name); + let controller_context = + controller::Context::new(client.clone(), operator_environment, operator_name); let full_controller_name = controller_context.full_controller_name(); let event_recorder = Arc::new(Recorder::new( From 52f5a3cd3bb9f5013e7d91600766ac29d2b616ab Mon Sep 17 00:00:00 2001 From: Techassi Date: Tue, 12 May 2026 09:55:15 +0200 Subject: [PATCH 2/5] test: Add placeholder values to satify roundtrip tests --- rust/operator-binary/src/crd/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index a8842ec0..bdce92e1 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -874,6 +874,7 @@ attributed_string_type! { #[cfg(test)] mod tests { + use stackable_operator::versioned::test_utils::RoundtripTestData; use strum::IntoEnumIterator; use crate::crd::{security_config_managing_role_group_default, v1alpha1}; @@ -912,4 +913,10 @@ mod tests { // Test that the function does not panic security_config_managing_role_group_default(); } + + impl RoundtripTestData for v1alpha1::OpenSearchClusterSpec { + fn roundtrip_test_data() -> Vec { + vec![] + } + } } From df4562892e8694cbe25833aa446acffd5b3ef441 Mon Sep 17 00:00:00 2001 From: Techassi Date: Tue, 12 May 2026 09:58:12 +0200 Subject: [PATCH 3/5] chore: Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a65fd50..9704be59 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` ([#141]). - Support hot-reloading of security configuration files ([#130]). ### Changed @@ -18,6 +19,7 @@ All notable changes to this project will be documented in this file. [#129]: https://github.com/stackabletech/opensearch-operator/pull/129 [#130]: https://github.com/stackabletech/opensearch-operator/pull/130 [#137]: https://github.com/stackabletech/opensearch-operator/pull/137 +[#141]: https://github.com/stackabletech/opensearch-operator/pull/141 ## [26.3.0] - 2026-03-16 From 1916ae12db3e7134b084239358931e12f07794c2 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 13 May 2026 14:36:24 +0200 Subject: [PATCH 4/5] test: Add some roundtrip test data --- Cargo.lock | 1 + Cargo.toml | 1 + rust/operator-binary/Cargo.toml | 1 + rust/operator-binary/src/crd/mod.rs | 135 +++++++++++++++++++++++++++- 4 files changed, 137 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ad93da41..61983a5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2944,6 +2944,7 @@ dependencies = [ "built", "clap", "futures 0.3.32", + "indoc", "json-patch", "pretty_assertions", "regex", diff --git a/Cargo.toml b/Cargo.toml index 91d645f1..a8157d62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", built = { version = "0.8.0", features = ["chrono", "git2"] } clap = "4.5" futures = { version = "0.3", features = ["compat"] } +indoc = "2.0" json-patch = { version = "4.2", features = ["schemars"] } pretty_assertions = "1.4" regex = "1.11" diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 6a23107e..0c9e6695 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -29,5 +29,6 @@ uuid.workspace = true built.workspace = true [dev-dependencies] +indoc.workspace = true pretty_assertions.workspace = true rstest.workspace = true diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index bdce92e1..4bc0db20 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -916,7 +916,140 @@ mod tests { impl RoundtripTestData for v1alpha1::OpenSearchClusterSpec { fn roundtrip_test_data() -> Vec { - vec![] + stackable_operator::utils::yaml_from_str_singleton_map(indoc::indoc! {r#" + - image: + productVersion: 3.4.0 + pullPolicy: IfNotPresent + clusterOperation: + reconciliationPaused: false + stopped: false + clusterConfig: + keystore: + - key: s3.client.default.access_key + secretKeyRef: + name: s3-credentials + key: ACCESS_KEY + - key: s3.client.default.secret_key + secretKeyRef: + name: s3-credentials + key: SECRET_KEY + security: + enabled: true + managingRoleGroup: security-coord + settings: + config: + managedBy: operator + content: + value: + _meta: + type: config + config_version: 2 + config: + dynamic: + authc: + basic_internal_auth_domain: + description: Authenticate via HTTP Basic against internal users database + http_enabled: true + transport_enabled: true + order: 1 + http_authenticator: + type: basic + challenge: true + authentication_backend: + type: intern + authz: {} + internalUsers: + managedBy: API + content: + valueFrom: + secretKeyRef: + name: opensearch-security-config + key: internal_users.yml + roles: + managedBy: API + content: + valueFrom: + configMapKeyRef: + name: opensearch-security-config + key: roles.yml + rolesMapping: + managedBy: API + content: + value: + _meta: + type: rolesmapping + config_version: 2 + all_access: + reserved: false + backend_roles: + - admin + tls: + serverSecretClass: tls + internalSecretClass: tls + vectorAggregatorConfigMapName: vector-aggregator-discovery + nodes: + config: + logging: + enableVectorAgent: true + gracefulShutdownTimeout: 2m + requestedSecretLifetime: 1d + envOverrides: + DISABLE_INSTALL_DEMO_CONFIG: "true" + OPENSEARCH_HOME: /stackable/opensearch + configOverrides: + opensearch.yml: + jsonMergePatch: + node.store.allow_mmap: false + cluster.routing.allocation.disk.threshold_enabled: false + roleConfig: + discoveryServiceListenerClass: external-unstable + roleGroups: + cluster-manager: + config: + discoveryServiceExposed: true + nodeRoles: + - cluster_manager + resources: + storage: + data: + capacity: 100Mi + replicas: 3 + data: + config: + discoveryServiceExposed: false + nodeRoles: + - ingest + - data + - remote_cluster_client + listenerClass: cluster-internal + resources: + storage: + data: + capacity: 2Gi + configOverrides: + opensearch.yml: + jsonMergePatch: + node.attr.zone: eu-central-1a + envOverrides: + OPENSEARCH_JAVA_OPTS: -Xms1g -Xmx1g + replicas: 2 + - image: + custom: oci.example.com/namespace/opensearch:3.4.0-custom + productVersion: 3.4.0 + pullPolicy: Always + pullSecrets: + - name: registry-credentials + clusterConfig: + tls: + serverSecretClass: null + security: + enabled: false + nodes: + roleGroups: + default: + replicas: 1 + "#}) + .expect("Failed to parse OpenSearchClusterSpec YAML") } } } From ff2e2466e6db855da1d5c9ce9db9be325bd5d6b9 Mon Sep 17 00:00:00 2001 From: Techassi Date: Wed, 13 May 2026 15:56:51 +0200 Subject: [PATCH 5/5] chore: Update Cargo.nix --- Cargo.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.nix b/Cargo.nix index 7c479ff8..4c2b876b 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -9776,6 +9776,10 @@ rec { } ]; devDependencies = [ + { + name = "indoc"; + packageId = "indoc"; + } { name = "pretty_assertions"; packageId = "pretty_assertions";