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
8 changes: 3 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,8 @@
the logger as well, because a logger discards records before any handler can filter them, so in
that direction the UI and the other destinations open up together and cannot be set apart
([#829]).
- 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 StatefulSet so that the operator immediately recreates it with
the new labels ([#838]).
- Remove the `app.kubernetes.io/component` and `app.kubernetes.io/role-group` labels from the
resources they don't apply to ([#838], [#887]).
- All product containers now run with `securityContext.runAsNonRoot` set to `true` to improve security ([#840]).
- `envOverrides` names are now validated by the shared `EnvVarName` type rather than by
operator-specific validation code ([#838]).
Expand Down Expand Up @@ -105,6 +102,7 @@
[#884]: https://github.com/stackabletech/airflow-operator/pull/884
[#885]: https://github.com/stackabletech/airflow-operator/pull/885
[#886]: https://github.com/stackabletech/airflow-operator/pull/886
[#887]: https://github.com/stackabletech/airflow-operator/pull/887

## [26.7.0] - 2026-07-21

Expand Down
29 changes: 25 additions & 4 deletions rust/operator-binary/src/controller/build/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Builders that assemble Kubernetes resources from the validated cluster.

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

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

Expand All @@ -36,6 +36,10 @@ pub mod properties;
pub mod resource;
pub mod volumes;

// 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}"))]
Expand Down Expand Up @@ -242,14 +246,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 Down Expand Up @@ -420,14 +435,20 @@ mod tests {
use stackable_operator::kube::Resource;

use super::{
build,
UNVERSIONED_PRODUCT_VERSION, build,
test_support::{
app_version_label, celery_executor_cluster, cluster_with_trusted_proxies,
kubernetes_executor_cluster, validated_cluster_with,
},
};
use crate::controller::ValidatedCluster;

#[test]
fn test_constants() {
// Test that dereferencing the constant does not panic.
let _ = *UNVERSIONED_PRODUCT_VERSION;
}

fn sorted_names(resources: &[impl Resource]) -> Vec<&str> {
let mut names: Vec<&str> = resources
.iter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ pub fn build_server_rolegroup_statefulset(
airflow_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(
validated_cluster,
airflow_role,
Expand Down
Loading