diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d5acca3..9dfc83bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,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]). +- 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`) ([#838]). - All product containers now run with `securityContext.runAsNonRoot` set to `true` to improve security ([#840]). ### Fixed @@ -39,6 +41,7 @@ [#829]: https://github.com/stackabletech/airflow-operator/pull/829 [#834]: https://github.com/stackabletech/airflow-operator/pull/834 [#835]: https://github.com/stackabletech/airflow-operator/pull/835 +[#838]: https://github.com/stackabletech/airflow-operator/pull/838 [#840]: https://github.com/stackabletech/airflow-operator/pull/840 ## [26.7.0] - 2026-07-21 diff --git a/Cargo.lock b/Cargo.lock index 7540e3ae..5b07d09f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1714,7 +1714,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "darling 0.24.0", "regex", @@ -3177,7 +3177,7 @@ dependencies = [ [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "const-oid", "ecdsa", @@ -3201,7 +3201,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.115.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "base64 0.23.1", "clap", @@ -3245,7 +3245,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "darling 0.24.0", "proc-macro2", @@ -3256,7 +3256,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.1.2" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "jiff", "k8s-openapi", @@ -3273,7 +3273,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "axum", "clap", @@ -3297,7 +3297,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "kube", "schemars", @@ -3311,7 +3311,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "convert_case", "convert_case_extras", @@ -3329,7 +3329,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.9.2" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#fb2d86579f4e3df008f78f0e527a012243483a2d" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#ab0579876d3af6e238c0a8513b09f9c3d185de44" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 25187a5e..806b8014 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5432,9 +5432,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; libName = "k8s_version"; authors = [ @@ -10427,9 +10427,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; libName = "stackable_certs"; authors = [ @@ -10530,9 +10530,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; libName = "stackable_operator"; authors = [ @@ -10712,7 +10712,8 @@ rec { "client-feature-gates" = [ "dep:winnow" ]; "crds" = [ "dep:stackable-versioned" ]; "default" = [ "crds" ]; - "full" = [ "client-feature-gates" "crds" "certs" "test-support" "time" "webhook" "kube-ws" ]; + "full" = [ "client-feature-gates" "crds" "certs" "test-support" "time" "webhook" "kube-ws" "kube-cel" ]; + "kube-cel" = [ "kube/cel" ]; "kube-ws" = [ "kube/ws" ]; "time" = [ "stackable-shared/time" ]; "webhook" = [ "dep:stackable-webhook" ]; @@ -10725,9 +10726,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -10760,9 +10761,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; libName = "stackable_shared"; authors = [ @@ -10841,9 +10842,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; libName = "stackable_telemetry"; authors = [ @@ -10951,9 +10952,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; libName = "stackable_versioned"; authors = [ @@ -11001,9 +11002,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -11069,9 +11070,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "ab0579876d3af6e238c0a8513b09f9c3d185de44"; + sha256 = "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1"; }; libName = "stackable_webhook"; authors = [ diff --git a/Cargo.toml b/Cargo.toml index 70bb8663..8ddf5080 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,5 +33,5 @@ tokio = { version = "1.53", features = ["full"] } tracing = "0.1" [patch."https://github.com/stackabletech/operator-rs.git"] -# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" } +stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feat/smooth-operator/recommended-labels" } # stackable-operator = { path = "../operator-rs/crates/stackable-operator" } diff --git a/crate-hashes.json b/crate-hashes.json index 43cd4b72..32358383 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,11 +1,11 @@ { - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#k8s-version@0.1.3": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-certs@0.4.1": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-operator-derive@0.3.1": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-operator@0.115.0": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-shared@0.1.2": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-telemetry@0.6.5": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-versioned-macros@0.11.1": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-versioned@0.11.1": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.115.0#stackable-webhook@0.9.2": "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb" + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#k8s-version@0.1.3": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-certs@0.4.1": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-operator-derive@0.3.1": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-operator@0.115.0": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-shared@0.1.2": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-telemetry@0.6.5": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-versioned-macros@0.11.1": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-versioned@0.11.1": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fsmooth-operator%2Frecommended-labels#stackable-webhook@0.9.2": "0f72i9h8v8n5f0v41zgp070bvb5w7gcqvx2h01dhl2jizkarwcs1" } \ No newline at end of file diff --git a/rust/operator-binary/src/controller/apply.rs b/rust/operator-binary/src/controller/apply.rs index c3be9c58..fda5881a 100644 --- a/rust/operator-binary/src/controller/apply.rs +++ b/rust/operator-binary/src/controller/apply.rs @@ -14,8 +14,8 @@ use strum::{EnumDiscriminants, IntoStaticStr}; use crate::{ controller::{ - Applied, KubernetesResources, Prepared, ValidatedCluster, controller_name, operator_name, - product_name, + Applied, CONTROLLER_NAME, KubernetesResources, OPERATOR_NAME, PRODUCT_NAME, Prepared, + ValidatedCluster, }, crd::internal_secret::{ FERNET_KEY_SECRET_KEY, INTERNAL_SECRET_SECRET_KEY, JWT_SECRET_SECRET_KEY, @@ -60,9 +60,9 @@ impl<'a> Applier<'a> { object_overrides: &'a ObjectOverrides, ) -> Applier<'a> { let cluster_resources = cluster_resources_new( - &product_name(), - &operator_name(), - &controller_name(), + &PRODUCT_NAME, + &OPERATOR_NAME, + &CONTROLLER_NAME, &cluster.name, &cluster.namespace, &cluster.uid, diff --git a/rust/operator-binary/src/controller/build/mod.rs b/rust/operator-binary/src/controller/build/mod.rs index 5d36cbb4..2c58809d 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -6,12 +6,16 @@ use snafu::{ResultExt, Snafu}; use stackable_operator::{ builder::meta::ObjectMetaBuilder, kvp::Labels, - v2::{builder::meta::ownerreference_from_resource, types::operator::RoleGroupName}, + v2::{ + builder::meta::ownerreference_from_resource, + types::operator::{RoleGroupName, RoleName}, + }, }; use crate::{ controller::{ - KubernetesResources, Prepared, ValidatedCluster, + CONTROLLER_NAME, KubernetesResources, OPERATOR_NAME, PRODUCT_NAME, Prepared, + ValidatedCluster, build::resource::{ config_map::build_rolegroup_config_map, executor::build_executor_template_config_map, @@ -122,7 +126,7 @@ pub fn build(cluster: &ValidatedCluster) -> Result config_maps.push( build_rolegroup_config_map( cluster, - &ValidatedCluster::role_name(role), + role, role_group_name, &rg_config.config_overrides, logging, @@ -178,6 +182,75 @@ pub(crate) fn object_meta( builder } +pub(crate) fn recommended_labels_for_cluster_resources(cluster: &ValidatedCluster) -> Labels { + stackable_operator::v2::kvp::label::recommended_labels_for_cluster_resources( + &cluster.name, + &PRODUCT_NAME, + &cluster.product_version, + &OPERATOR_NAME, + &CONTROLLER_NAME, + ) +} + +pub(crate) fn recommended_labels_for_role_resources( + cluster: &ValidatedCluster, + role_name: &RoleName, +) -> Labels { + stackable_operator::v2::kvp::label::recommended_labels_for_role_resources( + &cluster.name, + &PRODUCT_NAME, + &cluster.product_version, + &OPERATOR_NAME, + &CONTROLLER_NAME, + role_name, + ) +} + +pub(crate) fn recommended_labels_for_role_group_resources( + cluster: &ValidatedCluster, + role_name: &RoleName, + role_group_name: &RoleGroupName, +) -> Labels { + stackable_operator::v2::kvp::label::recommended_labels_for_role_group_resources( + &cluster.name, + &PRODUCT_NAME, + &cluster.product_version, + &OPERATOR_NAME, + &CONTROLLER_NAME, + role_name, + role_group_name, + ) +} + +pub(crate) fn recommended_labels_for_unversioned_role_group_resources( + cluster: &ValidatedCluster, + role_name: &RoleName, + role_group_name: &RoleGroupName, +) -> Labels { + stackable_operator::v2::kvp::label::recommended_labels_for_unversioned_role_group_resources( + &cluster.name, + &PRODUCT_NAME, + &OPERATOR_NAME, + &CONTROLLER_NAME, + role_name, + role_group_name, + ) +} + +/// Selector labels matching the pods of a role group. +pub(crate) fn role_group_selector( + cluster: &ValidatedCluster, + role_name: &RoleName, + role_group_name: &RoleGroupName, +) -> Labels { + stackable_operator::v2::kvp::label::role_group_selector( + &cluster.name, + &PRODUCT_NAME, + role_name, + role_group_name, + ) +} + #[cfg(test)] pub(crate) mod test_support { use crate::{ @@ -475,14 +548,12 @@ mod tests { let expected_labels = BTreeMap::from( [ - ("app.kubernetes.io/component", "none"), ("app.kubernetes.io/instance", "my-airflow"), ( "app.kubernetes.io/managed-by", "airflow.stackable.tech_airflowcluster", ), ("app.kubernetes.io/name", "airflow"), - ("app.kubernetes.io/role-group", "none"), ("app.kubernetes.io/version", &app_version_label("3.1.6")), ("stackable.tech/vendor", "Stackable"), ] diff --git a/rust/operator-binary/src/controller/build/resource/config_map.rs b/rust/operator-binary/src/controller/build/resource/config_map.rs index 5b8dcacc..fc0d15c4 100644 --- a/rust/operator-binary/src/controller/build/resource/config_map.rs +++ b/rust/operator-binary/src/controller/build/resource/config_map.rs @@ -24,6 +24,7 @@ use crate::{ product_logging::{create_airflow_config, vector_config_file_content}, webserver_config, }, + recommended_labels_for_role_group_resources, }, }, crd::{AirflowConfigOverrides, Container}, @@ -72,7 +73,11 @@ pub fn build_rolegroup_config_map( .role_group_resource_names(role_name, role_group_name) .role_group_config_map() .to_string(), - validated_cluster.recommended_labels_for(role_name, role_group_name), + recommended_labels_for_role_group_resources( + validated_cluster, + role_name, + role_group_name, + ), ) .build(), ) diff --git a/rust/operator-binary/src/controller/build/resource/executor.rs b/rust/operator-binary/src/controller/build/resource/executor.rs index 6ed1e617..4dddce7f 100644 --- a/rust/operator-binary/src/controller/build/resource/executor.rs +++ b/rust/operator-binary/src/controller/build/resource/executor.rs @@ -28,6 +28,7 @@ use crate::{ graceful_shutdown::add_graceful_shutdown_config, object_meta, properties::env_vars::build_airflow_template_envs, + recommended_labels_for_role_group_resources, resource::pod::{ add_authentication_volumes_and_volume_mounts, add_git_sync_resources, build_logging_container, @@ -88,13 +89,13 @@ pub fn build_executor_template_config_map( let git_sync_resources = &executor_config.git_sync_resources; let mut pb = PodBuilder::new(); - let pb_metadata = - ObjectMetaBuilder::new() - .with_labels(cluster.recommended_labels_for( - &executor_role_name(), - &executor_template_role_group_name(), - )) - .build(); + let pb_metadata = ObjectMetaBuilder::new() + .with_labels(recommended_labels_for_role_group_resources( + cluster, + &executor_role_name(), + &executor_template_role_group_name(), + )) + .build(); pb.metadata(pb_metadata) .image_pull_secrets_from_product_image(resolved_product_image) @@ -192,7 +193,8 @@ pub fn build_executor_template_config_map( object_meta( cluster, cluster.executor_template_configmap_name(), - cluster.recommended_labels_for( + recommended_labels_for_role_group_resources( + cluster, &executor_role_name(), &executor_template_role_group_name(), ), diff --git a/rust/operator-binary/src/controller/build/resource/listener.rs b/rust/operator-binary/src/controller/build/resource/listener.rs index e346eb25..d8abe9f4 100644 --- a/rust/operator-binary/src/controller/build/resource/listener.rs +++ b/rust/operator-binary/src/controller/build/resource/listener.rs @@ -1,22 +1,16 @@ -use std::str::FromStr; - use stackable_operator::{ crd::listener, - v2::types::{ - kubernetes::{ListenerClassName, ListenerName}, - operator::RoleGroupName, - }, + v2::types::kubernetes::{ListenerClassName, ListenerName}, }; use crate::{ - controller::{ValidatedCluster, build::object_meta}, + controller::{ + ValidatedCluster, + build::{object_meta, recommended_labels_for_role_resources}, + }, crd::{AirflowRole, HTTP_PORT, HTTP_PORT_NAME}, }; -// The group listener is a role-level object, so a constant `none` role-group is used as the -// role-group label value. -stackable_operator::constant!(NONE_ROLE_GROUP_NAME: RoleGroupName = "none"); - pub fn build_group_listener( cluster: &ValidatedCluster, role: &AirflowRole, @@ -27,8 +21,7 @@ pub fn build_group_listener( metadata: object_meta( cluster, listener_group_name, - cluster - .recommended_labels_for(&ValidatedCluster::role_name(role), &NONE_ROLE_GROUP_NAME), + recommended_labels_for_role_resources(cluster, role), ) .build(), spec: listener::v1alpha1::ListenerSpec { diff --git a/rust/operator-binary/src/controller/build/resource/pdb.rs b/rust/operator-binary/src/controller/build/resource/pdb.rs index 22d82556..f56a7802 100644 --- a/rust/operator-binary/src/controller/build/resource/pdb.rs +++ b/rust/operator-binary/src/controller/build/resource/pdb.rs @@ -4,7 +4,7 @@ use stackable_operator::{ }; use crate::{ - controller::{ValidatedCluster, controller_name, operator_name, product_name}, + controller::{CONTROLLER_NAME, OPERATOR_NAME, PRODUCT_NAME, ValidatedCluster}, crd::{AirflowExecutor, AirflowRole}, }; @@ -37,10 +37,10 @@ pub fn build_pdb( let pdb = pod_disruption_budget_builder_with_role( cluster, - &product_name(), - &ValidatedCluster::role_name(role), - &operator_name(), - &controller_name(), + &PRODUCT_NAME, + role, + &OPERATOR_NAME, + &CONTROLLER_NAME, ) .with_max_unavailable(max_unavailable) .build(); diff --git a/rust/operator-binary/src/controller/build/resource/rbac.rs b/rust/operator-binary/src/controller/build/resource/rbac.rs index 7bbb3aa7..8bf95cfc 100644 --- a/rust/operator-binary/src/controller/build/resource/rbac.rs +++ b/rust/operator-binary/src/controller/build/resource/rbac.rs @@ -1,20 +1,11 @@ //! Builds the RBAC resources (ServiceAccount + RoleBinding) shared by all role groups. -use std::str::FromStr; - use stackable_operator::{ k8s_openapi::api::{core::v1::ServiceAccount, rbac::v1::RoleBinding}, - kvp::Labels, - v2::{ - rbac, - types::operator::{RoleGroupName, RoleName}, - }, + v2::rbac, }; -use crate::controller::ValidatedCluster; - -stackable_operator::constant!(NONE_ROLE_NAME: RoleName = "none"); -stackable_operator::constant!(NONE_ROLE_GROUP_NAME: RoleGroupName = "none"); +use crate::controller::{ValidatedCluster, build::recommended_labels_for_cluster_resources}; /// Builds the [`ServiceAccount`] that the role-group Pods and the Kubernetes-executor Pods run /// under. @@ -22,7 +13,7 @@ pub fn build_service_account(cluster: &ValidatedCluster) -> ServiceAccount { rbac::build_service_account( cluster, &cluster.cluster_resource_names(), - rbac_labels(cluster), + recommended_labels_for_cluster_resources(cluster), ) } @@ -32,12 +23,6 @@ pub fn build_role_binding(cluster: &ValidatedCluster) -> RoleBinding { rbac::build_role_binding( cluster, &cluster.cluster_resource_names(), - rbac_labels(cluster), + recommended_labels_for_cluster_resources(cluster), ) } - -/// Both resources are shared by the whole cluster rather than tied to a role or role group, so -/// the recommended labels carry `none` for both values. -fn rbac_labels(cluster: &ValidatedCluster) -> Labels { - cluster.recommended_labels_for(&NONE_ROLE_NAME, &NONE_ROLE_GROUP_NAME) -} diff --git a/rust/operator-binary/src/controller/build/resource/service.rs b/rust/operator-binary/src/controller/build/resource/service.rs index 6bab8c0c..363ab9f4 100644 --- a/rust/operator-binary/src/controller/build/resource/service.rs +++ b/rust/operator-binary/src/controller/build/resource/service.rs @@ -7,7 +7,10 @@ use stackable_operator::{ }; use crate::{ - controller::{ValidatedCluster, build::object_meta}, + controller::{ + ValidatedCluster, + build::{object_meta, recommended_labels_for_role_group_resources, role_group_selector}, + }, crd::{AirflowRole, HTTP_PORT, HTTP_PORT_NAME, METRICS_PORT, METRICS_PORT_NAME}, }; @@ -22,10 +25,10 @@ pub fn build_rolegroup_headless_service( metadata: object_meta( cluster, cluster - .role_group_resource_names(&ValidatedCluster::role_name(role), role_group_name) + .role_group_resource_names(role, role_group_name) .headless_service_name() .to_string(), - cluster.recommended_labels(role, role_group_name), + recommended_labels_for_role_group_resources(cluster, role, role_group_name), ) .build(), spec: Some(ServiceSpec { @@ -33,7 +36,7 @@ pub fn build_rolegroup_headless_service( type_: Some("ClusterIP".to_string()), cluster_ip: Some("None".to_string()), ports: Some(headless_service_ports()), - selector: Some(cluster.role_group_selector(role, role_group_name).into()), + selector: Some(role_group_selector(cluster, role, role_group_name).into()), publish_not_ready_addresses: Some(true), ..ServiceSpec::default() }), @@ -51,10 +54,10 @@ pub fn build_rolegroup_metrics_service( metadata: object_meta( cluster, cluster - .role_group_resource_names(&ValidatedCluster::role_name(role), role_group_name) + .role_group_resource_names(role, role_group_name) .metrics_service_name() .to_string(), - cluster.recommended_labels(role, role_group_name), + recommended_labels_for_role_group_resources(cluster, role, role_group_name), ) .with_labels(prometheus_labels(&Scraping::Enabled)) .with_annotations(prometheus_annotations( @@ -69,7 +72,7 @@ pub fn build_rolegroup_metrics_service( type_: Some("ClusterIP".to_string()), cluster_ip: Some("None".to_string()), ports: Some(metrics_service_ports()), - selector: Some(cluster.role_group_selector(role, role_group_name).into()), + selector: Some(role_group_selector(cluster, role, role_group_name).into()), publish_not_ready_addresses: Some(true), ..ServiceSpec::default() }), @@ -85,7 +88,7 @@ pub fn stateful_set_service_name( ) -> Option { Some( cluster - .role_group_resource_names(&ValidatedCluster::role_name(role), role_group_name) + .role_group_resource_names(role, role_group_name) .headless_service_name() .to_string(), ) diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index 81915cab..89d5eee3 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -35,6 +35,8 @@ use crate::{ graceful_shutdown::add_graceful_shutdown_config, object_meta, properties::env_vars, + recommended_labels_for_role_group_resources, + recommended_labels_for_unversioned_role_group_resources, resource::{ pod::{ add_authentication_volumes_and_volume_mounts, add_git_sync_resources, @@ -42,6 +44,7 @@ use crate::{ }, service::stateful_set_service_name, }, + role_group_selector, volumes::{self, CONFIG_VOLUME_NAME, LOG_CONFIG_VOLUME_NAME, LOG_VOLUME_NAME}, }, }, @@ -94,7 +97,7 @@ fn build_rolegroup_metadata( object_meta( cluster, name, - cluster.recommended_labels(role, role_group_name), + recommended_labels_for_role_group_resources(cluster, role, role_group_name), ) .with_label(prometheus_label) .build() @@ -119,15 +122,20 @@ pub fn build_server_rolegroup_statefulset( let executor = &validated_cluster.cluster_config.executor; let mut pb = PodBuilder::new(); - let resource_names = validated_cluster - .role_group_resource_names(&ValidatedCluster::role_name(airflow_role), role_group_name); + let resource_names = validated_cluster.role_group_resource_names(airflow_role, role_group_name); - let recommended_object_labels = - validated_cluster.recommended_labels(airflow_role, role_group_name); + let recommended_object_labels = recommended_labels_for_role_group_resources( + validated_cluster, + airflow_role, + role_group_name, + ); // Used for PVC templates that cannot be modified once they are deployed (a constant "none" // version keeps the labels stable across version upgrades). - let unversioned_recommended_labels = - validated_cluster.unversioned_recommended_labels(airflow_role, role_group_name); + let unversioned_recommended_labels = recommended_labels_for_unversioned_role_group_resources( + validated_cluster, + airflow_role, + role_group_name, + ); let pb_metadata = ObjectMetaBuilder::new() .with_labels(recommended_object_labels) @@ -349,7 +357,7 @@ pub fn build_server_rolegroup_statefulset( ); let statefulset_match_labels = - validated_cluster.role_group_selector(airflow_role, role_group_name); + role_group_selector(validated_cluster, airflow_role, role_group_name); let statefulset_spec = StatefulSetSpec { pod_management_policy: Some( diff --git a/rust/operator-binary/src/controller/mod.rs b/rust/operator-binary/src/controller/mod.rs index 93058b42..dbcace68 100644 --- a/rust/operator-binary/src/controller/mod.rs +++ b/rust/operator-binary/src/controller/mod.rs @@ -10,6 +10,7 @@ use stackable_operator::{ product_image_selection::ResolvedProductImage, resources::{NoRuntimeLimits, Resources}, }, + constant, crd::{git_sync, listener}, database_connections::{ TemplatingMechanism, @@ -25,12 +26,10 @@ use stackable_operator::{ rbac::v1::RoleBinding, }, kube::{Resource, ResourceExt, api::ObjectMeta}, - kvp::Labels, product_logging::spec::ContainerLogConfig, shared::time::Duration, v2::{ HasName, HasUid, NameIsValidLabelValue, - kvp::label::{recommended_labels, role_group_selector}, product_logging::framework::{ValidatedContainerLogConfigChoice, VectorContainerLogConfig}, role_group_utils::ResourceNames, role_utils, @@ -49,8 +48,8 @@ use stackable_operator::{ use crate::{ airflow_controller::AIRFLOW_CONTROLLER_NAME, crd::{ - APP_NAME, AirflowConfig, AirflowConfigOverrides, AirflowExecutor, AirflowRole, - AirflowStorageConfig, ExecutorConfig, OPERATOR_NAME, + self, APP_NAME, AirflowConfig, AirflowConfigOverrides, AirflowExecutor, AirflowRole, + AirflowStorageConfig, ExecutorConfig, authentication::AirflowClientAuthenticationDetailsResolved, authorization::AirflowAuthorizationResolved, databases::{ @@ -68,7 +67,9 @@ pub mod update_status; pub mod validate; // Placeholder version label value for resources whose labels must not change after deployment. -stackable_operator::constant!(UNVERSIONED_PRODUCT_VERSION: ProductVersion = "none"); +constant!(PRODUCT_NAME: ProductName = APP_NAME); +constant!(OPERATOR_NAME: OperatorName = crd::OPERATOR_NAME); +constant!(CONTROLLER_NAME: ControllerName = AIRFLOW_CONTROLLER_NAME); /// Marker for prepared Kubernetes resources which are not applied yet. pub struct Prepared; @@ -344,7 +345,7 @@ impl ValidatedCluster { pub fn cluster_resource_names(&self) -> role_utils::ResourceNames { role_utils::ResourceNames { cluster_name: self.name.clone(), - product_name: product_name(), + product_name: PRODUCT_NAME.clone(), } } @@ -360,95 +361,6 @@ impl ValidatedCluster { role_group_name: role_group_name.clone(), } } - - /// The type-safe role name for an Airflow role. - /// - /// Infallible: every `AirflowRole` serialises to a short, valid role name. - pub fn role_name(role: &AirflowRole) -> RoleName { - role.to_string() - .parse() - .expect("an AirflowRole serialises to a valid RoleName") - } - - /// Recommended labels for a role-group resource. - pub fn recommended_labels( - &self, - role: &AirflowRole, - role_group_name: &RoleGroupName, - ) -> Labels { - self.recommended_labels_for(&Self::role_name(role), role_group_name) - } - - /// Recommended labels for a resource that is not tied to a concrete [`AirflowRole`] (e.g. the - /// Kubernetes executor pod template), using a free-form role/role-group label value. - pub fn recommended_labels_for( - &self, - role_name: &RoleName, - role_group_name: &RoleGroupName, - ) -> Labels { - self.recommended_labels_with(&self.product_version, role_name, role_group_name) - } - - /// Recommended labels with the constant [`UNVERSIONED_PRODUCT_VERSION`], for PVC templates - /// that cannot be modified after deployment (keeps the labels stable across version upgrades). - pub fn unversioned_recommended_labels( - &self, - role: &AirflowRole, - role_group_name: &RoleGroupName, - ) -> Labels { - self.recommended_labels_with( - &UNVERSIONED_PRODUCT_VERSION, - &Self::role_name(role), - role_group_name, - ) - } - - fn recommended_labels_with( - &self, - product_version: &ProductVersion, - role_name: &RoleName, - role_group_name: &RoleGroupName, - ) -> Labels { - recommended_labels( - self, - &product_name(), - product_version, - &operator_name(), - &controller_name(), - role_name, - role_group_name, - ) - } - - /// Selector labels matching the pods of a role group. - pub fn role_group_selector( - &self, - role: &AirflowRole, - role_group_name: &RoleGroupName, - ) -> Labels { - role_group_selector( - self, - &product_name(), - &Self::role_name(role), - role_group_name, - ) - } -} - -/// The product name (`airflow`) as a type-safe label value. -pub(crate) fn product_name() -> ProductName { - ProductName::from_str(APP_NAME).expect("'airflow' is a valid product name") -} - -/// The operator name as a type-safe label value. -pub(crate) fn operator_name() -> OperatorName { - OperatorName::from_str(OPERATOR_NAME).expect("the operator name is a valid label value") -} - -/// The controller name as a type-safe label value. -pub(crate) fn controller_name() -> ControllerName { - ControllerName::from_str(AIRFLOW_CONTROLLER_NAME) - .expect("the controller name is a valid label value") } /// Pseudo role/role-group names for the Kubernetes executor's resources (it is not a real @@ -530,17 +442,13 @@ impl HasUid for ValidatedCluster { #[cfg(test)] mod tests { - use strum::IntoEnumIterator; + use super::*; - use super::ValidatedCluster; - use crate::crd::AirflowRole; - - /// Locks the invariant behind the `expect` in [`ValidatedCluster::role_name`]: every - /// `AirflowRole` variant (present and future) must serialise to a valid `RoleName`. #[test] - fn every_airflow_role_serialises_to_a_valid_role_name() { - for role in AirflowRole::iter() { - ValidatedCluster::role_name(&role); - } + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *PRODUCT_NAME; + let _ = *OPERATOR_NAME; + let _ = *CONTROLLER_NAME; } } diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 6ce8ca0c..fc4ede94 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeSet, str::FromStr}; +use std::{collections::BTreeSet, ops::Deref, str::FromStr}; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; @@ -18,6 +18,7 @@ use stackable_operator::{ fragment::{self, Fragment, ValidationError}, merge::Merge, }, + constant, crd::git_sync, deep_merger::ObjectOverrides, k8s_openapi::{ @@ -47,6 +48,7 @@ use stackable_operator::{ ConfigMapName, ContainerName, ListenerClassName, ListenerName, PersistentVolumeClaimName, SecretName, VolumeName, }, + operator::RoleName, }, }, versioned::versioned, @@ -104,6 +106,12 @@ pub const MAX_LOG_FILES_SIZE: MemoryQuantity = MemoryQuantity { unit: BinaryMultiple::Mebi, }; +constant!(WEBSERVER_ROLE_NAME: RoleName = "webserver"); +constant!(SCHEDULER_ROLE_NAME: RoleName = "scheduler"); +constant!(WORKER_ROLE_NAME: RoleName = "worker"); +constant!(DAG_PROCESSOR_ROLE_NAME: RoleName = "dagprocessor"); +constant!(TRIGGERER_ROLE_NAME: RoleName = "triggerer"); + pub type AirflowRoleType = Role; @@ -524,35 +532,12 @@ pub struct AirflowOpaConfig { pub cache: UserInformationCache, } -#[derive( - Clone, - Debug, - Deserialize, - Display, - EnumIter, - Eq, - Hash, - JsonSchema, - Ord, - PartialEq, - PartialOrd, - Serialize, - EnumString, -)] +#[derive(Clone, Debug, EnumIter, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum AirflowRole { - #[strum(serialize = "webserver")] Webserver, - - #[strum(serialize = "scheduler")] Scheduler, - - #[strum(serialize = "worker")] Worker, - - #[strum(serialize = "dagprocessor")] DagProcessor, - - #[strum(serialize = "triggerer")] Triggerer, } @@ -812,6 +797,20 @@ impl AirflowRole { } } +impl Deref for AirflowRole { + type Target = RoleName; + + fn deref(&self) -> &Self::Target { + match self { + AirflowRole::Webserver => &WEBSERVER_ROLE_NAME, + AirflowRole::Scheduler => &SCHEDULER_ROLE_NAME, + AirflowRole::Worker => &WORKER_ROLE_NAME, + AirflowRole::DagProcessor => &DAG_PROCESSOR_ROLE_NAME, + AirflowRole::Triggerer => &TRIGGERER_ROLE_NAME, + } + } +} + fn container_debug_command() -> String { format!("containerdebug --output={STACKABLE_LOG_DIR}/containerdebug-state.json --loop &") } @@ -1036,10 +1035,18 @@ mod tests { versioned::test_utils::RoundtripTestData, }; - use crate::{ - crd::{AirflowRole, trusted_proxies::TrustedProxy}, - v1alpha1, v1alpha2, - }; + use super::*; + use crate::{v1alpha1, v1alpha2}; + + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *WEBSERVER_ROLE_NAME; + let _ = *SCHEDULER_ROLE_NAME; + let _ = *WORKER_ROLE_NAME; + let _ = *DAG_PROCESSOR_ROLE_NAME; + let _ = *TRIGGERER_ROLE_NAME; + } #[test] fn test_cluster_config() { @@ -1216,7 +1223,7 @@ mod tests { role.trusted_proxies(&cluster) .expect("no proxies to parse") .is_empty(), - "role {role} must not have trusted proxies" + "role {role:?} must not have trusted proxies" ); } }