Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ All notable changes to this project will be documented in this file.
- The discovery ConfigMap is now always written, with empty `ZOOKEEPER` and `ZOOKEEPER_HOSTS` while
the listener publishes no addresses ([#1069]).
- All product containers now run with `securityContext.runAsNonRoot` set to `true` to improve security ([#1070]).
- 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 the placeholder value
`discovery`).
Server StatefulSets created by older operator versions cannot be updated in place: after the operator
upgrade, delete each server StatefulSet so that the operator immediately recreates it with the new labels ([#1077]).
- 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 the placeholder value `discovery`)
([#1077], [#1102]).
- Environment variable overrides (`envOverrides`) are now merged into the operator-set
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
Expand Down Expand Up @@ -69,6 +67,7 @@ All notable changes to this project will be documented in this file.
[#1099]: https://github.com/stackabletech/zookeeper-operator/pull/1099
[#1100]: https://github.com/stackabletech/zookeeper-operator/pull/1100
[#1101]: https://github.com/stackabletech/zookeeper-operator/pull/1101
[#1102]: https://github.com/stackabletech/zookeeper-operator/pull/1102

## [26.7.0] - 2026-07-21

Expand Down
29 changes: 25 additions & 4 deletions rust/operator-binary/src/zk_controller/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! remaining submodules ([`command`], [`graceful_shutdown`], [`jvm`],
//! [`properties`]) produce fragments that those resource builders assemble.

use std::marker::PhantomData;
use std::{marker::PhantomData, str::FromStr};

use snafu::{ResultExt, Snafu};
use stackable_operator::{
Expand All @@ -19,7 +19,7 @@ use stackable_operator::{
v2::{
builder::meta::ownerreference_from_resource,
kvp::label,
types::operator::{RoleGroupName, RoleName},
types::operator::{ProductVersion, RoleGroupName, RoleName},
},
};

Expand Down Expand Up @@ -48,6 +48,10 @@ pub mod jvm;
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 {rolegroup}"))]
Expand Down Expand Up @@ -211,14 +215,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,
Expand All @@ -239,7 +254,7 @@ pub(crate) fn role_group_selector(
mod tests {
use stackable_operator::kube::Resource;

use super::build;
use super::{UNVERSIONED_PRODUCT_VERSION, build};
use crate::zk_controller::test_support::{cluster_info, minimal_zk, validated_cluster};

/// Collects the `.metadata.name`s of the given resources, sorted for stable comparison.
Expand All @@ -252,6 +267,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 zookeeper_yaml = r#"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ pub fn build_server_rolegroup_statefulset(
let mut cb_zookeeper = new_container_builder(&ZOOKEEPER_CONTAINER_NAME);
let mut pod_builder = PodBuilder::new();

// 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, zk_role, role_group_name);

Expand Down
Loading