From e8f05f336239977aed97e9faf78d5053c607bedd Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Fri, 30 Oct 2026 16:42:58 +0100 Subject: [PATCH] fix: Keep the "none" version label on unversioned role-group resources --- CHANGELOG.md | 8 ++--- .../src/controller/build/mod.rs | 29 ++++++++++++++++--- .../controller/build/resource/statefulset.rs | 3 +- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f95ed4d2..d356bced 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,12 +28,7 @@ variables set by the operator, whereas previously the operator's values always took precedence ([#779]). - The role-level group `Listener` now carries the recommended labels for role resources; - the `app.kubernetes.io/role-group: none` placeholder label is no longer set ([#779]). -- BREAKING: The listener PVC template of the `node` StatefulSet no longer carries an - `app.kubernetes.io/version` label (previously set to the placeholder value `none`). - Since `volumeClaimTemplates` cannot be updated in place, StatefulSets created by older - operator versions cannot be updated after the upgrade: delete the `node` StatefulSet(s) - so that the operator immediately recreates them with the new labels ([#779]). + the `app.kubernetes.io/role-group: none` placeholder label is no longer set ([#779], [#809]). - Make operations infallible where dependent on static inputs ([#785], [#788]). - Internal operator refactoring: the validated cluster carries each role's configuration in its own typed fields instead of maps keyed by role, and only the node role carries a listener class and a @@ -79,6 +74,7 @@ [#804]: https://github.com/stackabletech/superset-operator/pull/804 [#805]: https://github.com/stackabletech/superset-operator/pull/805 [#807]: https://github.com/stackabletech/superset-operator/pull/807 +[#809]: https://github.com/stackabletech/superset-operator/pull/809 ## [26.7.0] - 2026-07-21 diff --git a/rust/operator-binary/src/controller/build/mod.rs b/rust/operator-binary/src/controller/build/mod.rs index e485f7f4..03941114 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -1,6 +1,6 @@ //! Builders that assemble Kubernetes resources for superset rolegroups. -use std::marker::PhantomData; +use std::{marker::PhantomData, str::FromStr}; use snafu::{ResultExt, Snafu}; use stackable_operator::{ @@ -10,7 +10,7 @@ use stackable_operator::{ v2::{ builder::meta::ownerreference_from_resource, kvp::label, - types::operator::{RoleGroupName, RoleName}, + types::operator::{ProductVersion, RoleGroupName, RoleName}, }, }; @@ -35,6 +35,10 @@ pub mod command; pub mod properties; 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"); + #[derive(Snafu, Debug)] pub enum Error { #[snafu(display("failed to build ConfigMap for role group {role_group}"))] @@ -238,14 +242,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, @@ -320,7 +335,13 @@ pub(crate) mod test_support { mod tests { use stackable_operator::kube::Resource; - use super::{build, test_support::validated_cluster}; + use super::{UNVERSIONED_PRODUCT_VERSION, build, test_support::validated_cluster}; + + #[test] + fn test_constants() { + // Test that dereferencing the constant does not panic. + let _ = *UNVERSIONED_PRODUCT_VERSION; + } /// The group listener is a role-level object, so it carries the recommended labels for role /// resources: a `component` label for the role, but no `role-group` label. diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index 1a7e54f7..b2ca0d90 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -100,8 +100,7 @@ pub fn build_node_rolegroup_statefulset( let resource_names = validated.role_group_resource_names(superset_role, role_group_name); let recommended_object_labels = recommended_labels_for_role_group_resources(validated, superset_role, role_group_name); - // Used for PVC templates that cannot be modified once they are deployed (omitting the - // version label keeps the labels 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( validated, superset_role,