From 077a9c2b9b9b45b0bbb8759decafa829e5d1848f Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Fri, 30 Oct 2026 13:51:08 +0100 Subject: [PATCH] fix: Keep the "none" version label on unversioned role-group resources --- CHANGELOG.md | 9 ++---- rust/operator-binary/src/controller/build.rs | 31 ++++++++++++++++--- .../controller/build/resource/statefulset.rs | 3 +- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e082d4ff..235d2b96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,12 +39,8 @@ All notable changes to this project will be documented in this file. environment variables by name, so an override replaces the operator's value instead of producing a duplicated entry whose precedence depended on Kubernetes' duplicate-name handling ([#984]). -- BREAKING: Remove the `app.kubernetes.io/component` and `app.kubernetes.io/role-group` labels - from the resources they don't apply to, and the `app.kubernetes.io/version` label from PVC - templates (all previously set to the placeholder value `none`). Because the PVC templates of - a StatefulSet are immutable, StatefulSets created by older operator versions cannot be - updated in place: after the operator upgrade, delete each node StatefulSet so that the - operator immediately recreates it with the new labels ([#984]). +- Remove the `app.kubernetes.io/component` and `app.kubernetes.io/role-group` labels from the + resources they don't apply to ([#984], [#1017]). - Make operations infallible where dependent on static inputs ([#990]). - Deprecate support for 2.9.0 ([#997]). - Support Vector 0.58.0 ([#1006], [#1012], [#1013]). @@ -85,6 +81,7 @@ All notable changes to this project will be documented in this file. [#1012]: https://github.com/stackabletech/nifi-operator/pull/1012 [#1013]: https://github.com/stackabletech/nifi-operator/pull/1013 [#1015]: https://github.com/stackabletech/nifi-operator/pull/1015 +[#1017]: https://github.com/stackabletech/nifi-operator/pull/1017 ## [26.7.0] - 2026-07-21 diff --git a/rust/operator-binary/src/controller/build.rs b/rust/operator-binary/src/controller/build.rs index 405e933f..e1aa18b1 100644 --- a/rust/operator-binary/src/controller/build.rs +++ b/rust/operator-binary/src/controller/build.rs @@ -2,7 +2,7 @@ //! //! [`ValidatedCluster`]: crate::controller::ValidatedCluster -use std::marker::PhantomData; +use std::{marker::PhantomData, str::FromStr}; use snafu::{ResultExt, Snafu}; use stackable_operator::{ @@ -13,7 +13,7 @@ use stackable_operator::{ kvp::label, types::{ common::Port, - operator::{RoleGroupName, RoleName}, + operator::{ProductVersion, RoleGroupName, RoleName}, }, }, }; @@ -42,6 +42,10 @@ pub mod properties; pub mod proxy_hosts; pub mod resource; +// Placeholder value for the `app.kubernetes.io/version` label on resources whose labels are +// immutable once deployed. See `recommended_labels_for_unversioned_role_group_resources`. +stackable_operator::constant!(UNVERSIONED_PRODUCT_VERSION: ProductVersion = "none"); + pub const HTTPS_PORT_NAME: &str = "https"; pub const HTTPS_PORT: Port = Port(8443); pub const PROTOCOL_PORT_NAME: &str = "protocol"; @@ -209,14 +213,25 @@ pub(crate) fn recommended_labels_for_role_group_resources( ) } +/// The recommended labels for role-group resources that carry no product version. +/// +/// The `app.kubernetes.io/version` label is set to the placeholder `none` rather than being +/// omitted, because that is what operator versions up to 26.7 wrote. Omitting it would change the +/// `volumeClaimTemplates` of already deployed StatefulSets, and since those templates are +/// immutable, Kubernetes rejects the update and the operator can no longer reconcile the +/// StatefulSet. +/// +/// This is also why `label::recommended_labels_for_unversioned_role_group_resources`, which drops +/// the label entirely, is not used here. pub(crate) fn recommended_labels_for_unversioned_role_group_resources( cluster: &ValidatedCluster, role_name: &RoleName, role_group_name: &RoleGroupName, ) -> Labels { - label::recommended_labels_for_unversioned_role_group_resources( + label::recommended_labels_for_role_group_resources( &cluster.name, &PRODUCT_NAME, + &UNVERSIONED_PRODUCT_VERSION, &OPERATOR_NAME, &CONTROLLER_NAME, role_name, @@ -237,7 +252,9 @@ pub(crate) fn role_group_selector( mod tests { use stackable_operator::kube::Resource; - use super::{build, properties::test_support::minimal_validated_cluster}; + use super::{ + UNVERSIONED_PRODUCT_VERSION, build, properties::test_support::minimal_validated_cluster, + }; fn sorted_names(resources: &[impl Resource]) -> Vec<&str> { let mut names: Vec<&str> = resources @@ -248,6 +265,12 @@ mod tests { names } + #[test] + fn test_constants() { + // Test that dereferencing the constant does not panic. + let _ = *UNVERSIONED_PRODUCT_VERSION; + } + #[test] fn build_produces_expected_resources() { let cluster = minimal_validated_cluster(); diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index 4f729c98..df60260d 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -731,8 +731,7 @@ fn get_volume_claim_templates( ), ]; - // Used for PVC templates, which cannot be modified once they are deployed. The version label - // is omitted so the labels stay stable across version upgrades. + // The PVC template is immutable once deployed, so its labels must stay stable. let unversioned_recommended_labels = recommended_labels_for_unversioned_role_group_resources( cluster, &NifiRole::Node,