diff --git a/CHANGELOG.md b/CHANGELOG.md index 51465826..89c92c68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,11 +34,8 @@ All notable changes to this project will be documented in this file. - All product containers now run with `securityContext.runAsNonRoot` set to `true` to improve security ([#741]). - `envOverrides` names are now validated by the shared `EnvVarName` type rather than by operator-specific validation code ([#748]). -- BREAKING: Remove the `app.kubernetes.io/component` and `app.kubernetes.io/role-group` labels - from the resources they don't apply to (previously set to `none` or a placeholder value). - StatefulSets created by older operator versions cannot be updated in place: after the - operator upgrade, delete each metastore StatefulSet so that the operator immediately recreates it with - the new labels ([#748]). +- Remove the `app.kubernetes.io/component` and `app.kubernetes.io/role-group` labels from the + resources they don't apply to ([#748], [#787]). - Make operations infallible where dependent on static inputs ([#759], [#764]). - Support Vector 0.58.0 ([#776], [#780], [#781]). - test: Update OPA to 1.20.2 in integration tests ([#778]). @@ -79,6 +76,7 @@ All notable changes to this project will be documented in this file. [#781]: https://github.com/stackabletech/hive-operator/pull/781 [#782]: https://github.com/stackabletech/hive-operator/pull/782 [#785]: https://github.com/stackabletech/hive-operator/pull/785 +[#787]: https://github.com/stackabletech/hive-operator/pull/787 ## [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 e8c46c08..be6b70b7 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 turn a `ValidatedCluster` into Kubernetes resources. -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}, }, }; @@ -39,6 +39,10 @@ pub mod opa; 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}"))] @@ -196,14 +200,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, @@ -232,7 +247,10 @@ mod tests { utils::cluster_info::KubernetesClusterInfo, }; - use super::{KubernetesResources, Prepared, RoleGroupName, build, object_meta}; + use super::{ + KubernetesResources, Prepared, RoleGroupName, UNVERSIONED_PRODUCT_VERSION, build, + object_meta, + }; use crate::{ controller::{ build::recommended_labels_for_role_group_resources, @@ -256,6 +274,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_resource_names() { let hive = minimal_hive(DERBY_YAML); diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index 2896464f..481faa32 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -345,8 +345,7 @@ pub(crate) fn build_metastore_rolegroup_statefulset( let recommended_object_labels = recommended_labels_for_role_group_resources(cluster, hive_role, role_group_name); - // 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, hive_role,