From aa95d01ec6b5494c08b86cb51214c2b7cc411e2f Mon Sep 17 00:00:00 2001 From: Andrew Kenworthy Date: Tue, 18 Aug 2026 12:40:17 +0200 Subject: [PATCH 1/6] implement labels and env-var changes in line with op-rs 0.116 --- CHANGELOG.md | 10 +- Cargo.lock | 20 ++-- Cargo.nix | 41 +++++---- Cargo.toml | 2 +- crate-hashes.json | 18 ++-- extra/crds.yaml | 30 ++++-- rust/operator-binary/src/controller.rs | 34 ++++--- rust/operator-binary/src/controller/apply.rs | 8 +- .../src/controller/build/mod.rs | 86 ++++++++++++++---- .../controller/build/resource/config_map.rs | 3 +- .../controller/build/resource/discovery.rs | 7 +- .../src/controller/build/resource/listener.rs | 14 ++- .../src/controller/build/resource/pdb.rs | 10 +- .../src/controller/build/resource/rbac.rs | 25 ++--- .../src/controller/build/resource/service.rs | 21 ++--- .../controller/build/resource/statefulset.rs | 17 +++- .../src/controller/update_status.rs | 4 +- .../src/controller/validate.rs | 76 ++-------------- rust/operator-binary/src/crd/mod.rs | 91 +++++++------------ rust/operator-binary/src/main.rs | 4 +- 20 files changed, 251 insertions(+), 270 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 959c3836..9571c410 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,17 @@ All notable changes to this project will be documented in this file. assembles all relevant Kubernetes resources before anything is applied ([#841]). - The RBAC ServiceAccount and RoleBinding are now built with the operator-rs `v2::rbac` functions and carry the full set of recommended labels ([#846]). -- Bump stackable-operator to 0.114.0 ([#855]). +- Bump stackable-operator to 0.116.0 ([#855], [#865]). - The reconciler now applies resources and derives the cluster status in discrete apply and update_status steps ([#856]). - All product containers now run with `securityContext.runAsNonRoot` set to `true` to improve security ([#860]). +- `envOverrides` names are now validated by the shared `EnvVarName` type rather than by + operator-specific validation code ([#XXX]). +- 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 broker, coordinator and router StatefulSet so that the operator + immediately recreates it with the new labels ([#XXX]). ### Fixed @@ -26,6 +33,7 @@ All notable changes to this project will be documented in this file. [#855]: https://github.com/stackabletech/druid-operator/pull/855 [#856]: https://github.com/stackabletech/druid-operator/pull/856 [#860]: https://github.com/stackabletech/druid-operator/pull/860 +[#XXX]: https://github.com/stackabletech/druid-operator/pull/XXX ## [26.7.0] - 2026-07-21 diff --git a/Cargo.lock b/Cargo.lock index 4e0673df..62d14f10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1729,7 +1729,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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "darling 0.24.0", "regex", @@ -3207,7 +3207,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "const-oid", "ecdsa", @@ -3256,8 +3256,8 @@ 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" +version = "0.116.0" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "base64 0.23.1", "clap", @@ -3301,7 +3301,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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "darling 0.24.0", "proc-macro2", @@ -3312,7 +3312,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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "jiff", "k8s-openapi", @@ -3329,7 +3329,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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "axum", "clap", @@ -3353,7 +3353,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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "kube", "schemars", @@ -3367,7 +3367,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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "convert_case", "convert_case_extras", @@ -3385,7 +3385,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?tag=stackable-operator-0.116.0#7b9f9ac9a76fa425ab27f2821377ef86571ca121" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 745ec3eb..5a7e9c43 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5458,8 +5458,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; libName = "k8s_version"; authors = [ @@ -10466,8 +10466,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; libName = "stackable_certs"; authors = [ @@ -10673,13 +10673,13 @@ rec { }; "stackable-operator" = rec { crateName = "stackable-operator"; - version = "0.115.0"; + version = "0.116.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; libName = "stackable_operator"; authors = [ @@ -10859,7 +10859,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" ]; @@ -10873,8 +10874,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -10908,8 +10909,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; libName = "stackable_shared"; authors = [ @@ -10989,8 +10990,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; libName = "stackable_telemetry"; authors = [ @@ -11099,8 +11100,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; libName = "stackable_versioned"; authors = [ @@ -11149,8 +11150,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -11217,8 +11218,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "fb2d86579f4e3df008f78f0e527a012243483a2d"; - sha256 = "1w57n5xx0ik63r252l1v5ymm51jlsf7v4pj682b902k8vinlhyqb"; + rev = "7b9f9ac9a76fa425ab27f2821377ef86571ca121"; + sha256 = "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9"; }; libName = "stackable_webhook"; authors = [ diff --git a/Cargo.toml b/Cargo.toml index 961e9cc5..aea3394a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ edition = "2024" repository = "https://github.com/stackabletech/druid-operator" [workspace.dependencies] -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.115.0", features = ["crds", "webhook"] } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.116.0", features = ["crds", "webhook"] } anyhow = "1.0" built = { version = "0.8", features = ["chrono", "git2"] } diff --git a/crate-hashes.json b/crate-hashes.json index 43cd4b72..3fae0f9f 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?tag=stackable-operator-0.116.0#k8s-version@0.1.3": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-certs@0.4.1": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-operator-derive@0.3.1": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-operator@0.116.0": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-shared@0.1.2": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-telemetry@0.6.5": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-versioned-macros@0.11.1": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-versioned@0.11.1": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9", + "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.116.0#stackable-webhook@0.9.2": "1p3744fxgvs12sqwvi8hhainwrgvhdfwmbyqf0sp0aq3awq3q1v9" } \ No newline at end of file diff --git a/extra/crds.yaml b/extra/crds.yaml index 0d788ce6..f4dfa3a9 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -433,7 +433,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -927,7 +928,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -2062,7 +2064,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -2556,7 +2559,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -3081,7 +3085,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -3612,7 +3617,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -4156,7 +4162,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -4643,7 +4650,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -5138,7 +5146,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about @@ -5632,7 +5641,8 @@ spec: default: {} description: |- `envOverrides` configure environment variables to be set in the Pods. - It is a map from strings to strings - environment variables and the value to set. + It is a map from environment variable names to their values. The names are validated to be + valid environment variable names. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 9c82983a..52a25b54 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -1,13 +1,14 @@ //! Ensures that `Pod`s are configured and running for each [`DruidCluster`][v1alpha1] //! //! [v1alpha1]: v1alpha1::DruidCluster -use std::{marker::PhantomData, str::FromStr, sync::Arc}; +use std::{marker::PhantomData, sync::Arc}; use const_format::concatcp; use snafu::{ResultExt, Snafu}; use stackable_operator::{ cli::OperatorEnvironmentOptions, cluster_resources::ClusterResourceApplyStrategy, + constant, crd::listener::v1alpha1::Listener, k8s_openapi::api::{ apps::v1::StatefulSet, @@ -27,7 +28,7 @@ use strum::{EnumDiscriminants, IntoStaticStr}; use crate::{ controller::{apply::Applier, update_status::update_status}, - crd::{APP_NAME, OPERATOR_NAME, v1alpha1}, + crd::{APP_NAME, DRUID_OPERATOR_NAME, v1alpha1}, }; mod apply; @@ -38,25 +39,13 @@ mod update_status; pub(crate) mod validate; pub const DRUID_CONTROLLER_NAME: &str = "druidcluster"; -pub const FULL_CONTROLLER_NAME: &str = concatcp!(DRUID_CONTROLLER_NAME, '.', OPERATOR_NAME); +pub const FULL_CONTROLLER_NAME: &str = concatcp!(DRUID_CONTROLLER_NAME, '.', DRUID_OPERATOR_NAME); pub(super) const CONTAINER_IMAGE_BASE_NAME: &str = "druid"; -/// The product name (`druid`) as a type-safe label value. -pub(crate) fn product_name() -> ProductName { - ProductName::from_str(APP_NAME).expect("'druid' 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(DRUID_CONTROLLER_NAME) - .expect("the controller name is a valid label value") -} +constant!(PRODUCT_NAME: ProductName = APP_NAME); +constant!(OPERATOR_NAME: OperatorName = DRUID_OPERATOR_NAME); +constant!(CONTROLLER_NAME: ControllerName = DRUID_CONTROLLER_NAME); pub struct Ctx { pub client: stackable_operator::client::Client, @@ -186,6 +175,7 @@ mod test { use rstest::*; use stackable_operator::v2::types::operator::RoleGroupName; + use super::{CONTROLLER_NAME, OPERATOR_NAME, PRODUCT_NAME}; use crate::{ controller::build::{ properties::ConfigFileName, resource::config_map::build_rolegroup_config_map, @@ -193,6 +183,14 @@ mod test { crd::{DruidRole, PROP_SEGMENT_CACHE_LOCATIONS}, }; + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *PRODUCT_NAME; + let _ = *OPERATOR_NAME; + let _ = *CONTROLLER_NAME; + } + #[rstest] #[case( "segment_cache.yaml", diff --git a/rust/operator-binary/src/controller/apply.rs b/rust/operator-binary/src/controller/apply.rs index 2c3c9775..17be9c17 100644 --- a/rust/operator-binary/src/controller/apply.rs +++ b/rust/operator-binary/src/controller/apply.rs @@ -12,7 +12,7 @@ use stackable_operator::{ use strum::{EnumDiscriminants, IntoStaticStr}; use crate::controller::{ - Applied, KubernetesResources, Prepared, controller_name, operator_name, product_name, + Applied, CONTROLLER_NAME, KubernetesResources, OPERATOR_NAME, PRODUCT_NAME, Prepared, validate::ValidatedCluster, }; @@ -49,9 +49,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 13aabbe7..c344e70b 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -3,7 +3,6 @@ use std::{ collections::{BTreeMap, HashSet}, marker::PhantomData, - str::FromStr, }; use snafu::{ResultExt, Snafu}; @@ -14,13 +13,14 @@ use stackable_operator::{ kvp::Labels, v2::{ builder::meta::ownerreference_from_resource, + kvp::label, types::operator::{RoleGroupName, RoleName}, }, }; use crate::{ controller::{ - KubernetesResources, Prepared, + CONTROLLER_NAME, KubernetesResources, OPERATOR_NAME, PRODUCT_NAME, Prepared, build::resource::{ config_map::build_rolegroup_config_map, discovery::build_discovery_configmap, @@ -36,18 +36,6 @@ use crate::{ internal_secret::build_shared_internal_secret_name, }; -// Placeholder role-group name used for the recommended labels of the role-level discovery -// `ConfigMap` (which is not tied to a single role group). -stackable_operator::constant!(pub(crate) PLACEHOLDER_DISCOVERY_ROLE_GROUP: RoleGroupName = "discovery"); - -// Placeholder role-group name used for the recommended labels of the role-level `Listener` -// (which is not tied to a single role group). -stackable_operator::constant!(pub(crate) NONE_ROLE_GROUP_NAME: RoleGroupName = "none"); - -// Placeholder role name used for the recommended labels of cluster-shared resources like the -// internal Secret (which are not tied to a role at all). -stackable_operator::constant!(NONE_ROLE_NAME: RoleName = "none"); - pub mod authentication; pub mod graceful_shutdown; pub mod jvm; @@ -74,6 +62,70 @@ pub(crate) fn object_meta( builder } +pub(crate) fn recommended_labels_for_cluster_resources(cluster: &ValidatedCluster) -> Labels { + 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 { + 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 { + 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 { + 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 { + label::role_group_selector(&cluster.name, &PRODUCT_NAME, role_name, role_group_name) +} + #[derive(Snafu, Debug)] pub enum Error { #[snafu(display("failed to build ConfigMap for role group {role_group}"))] @@ -259,11 +311,11 @@ fn reemit_internal_secret(cluster: &ValidatedCluster, existing: &Secret) -> Secr /// the two are identical apart from their contents. fn internal_secret_meta(cluster: &ValidatedCluster) -> ObjectMetaBuilder { // The internal Secret is shared by the whole cluster rather than tied to a role or role - // group, so the recommended labels carry `none` for both values (like the RBAC resources). + // group, so it carries the cluster-resource labels (like the RBAC resources). object_meta( cluster, build_shared_internal_secret_name(cluster), - cluster.recommended_labels_for(&NONE_ROLE_NAME, &NONE_ROLE_GROUP_NAME), + recommended_labels_for_cluster_resources(cluster), ) } @@ -558,14 +610,12 @@ mod tests { let expected_labels = BTreeMap::from( [ - ("app.kubernetes.io/component", "none".to_string()), ("app.kubernetes.io/instance", "simple-druid".to_string()), ( "app.kubernetes.io/managed-by", "druid.stackable.tech_druidcluster".to_string(), ), ("app.kubernetes.io/name", "druid".to_string()), - ("app.kubernetes.io/role-group", "none".to_string()), ("app.kubernetes.io/version", app_version_label("30.0.0")), ("stackable.tech/vendor", "Stackable".to_string()), ] 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 e4eee63e..406f69b1 100644 --- a/rust/operator-binary/src/controller/build/resource/config_map.rs +++ b/rust/operator-binary/src/controller/build/resource/config_map.rs @@ -35,6 +35,7 @@ use crate::{ product_logging::{build_log4j2, vector_config_file_content}, runtime_properties, security_properties, }, + recommended_labels_for_role_group_resources, security::add_tls_config_properties, }, validate::{DruidRoleGroupConfig, ValidatedCluster}, @@ -379,7 +380,7 @@ pub fn build_rolegroup_config_map( object_meta( cluster, resource_names.role_group_config_map().to_string(), - cluster.recommended_labels(role, role_group_name), + recommended_labels_for_role_group_resources(cluster, role, role_group_name), ) .build(), ); diff --git a/rust/operator-binary/src/controller/build/resource/discovery.rs b/rust/operator-binary/src/controller/build/resource/discovery.rs index a08e03d0..8304c39e 100644 --- a/rust/operator-binary/src/controller/build/resource/discovery.rs +++ b/rust/operator-binary/src/controller/build/resource/discovery.rs @@ -10,7 +10,7 @@ use stackable_operator::{ use crate::{ controller::{ build::{ - PLACEHOLDER_DISCOVERY_ROLE_GROUP, object_meta, + object_meta, recommended_labels_for_role_resources, resource::listener::build_listener_connection_string, }, validate::ValidatedCluster, @@ -109,12 +109,13 @@ fn reemit_discovery_configmap(cluster: &ValidatedCluster, existing: &ConfigMap) /// Shared metadata for both the freshly built and the re-emitted discovery ConfigMap, so that /// the two are identical apart from their contents. The discovery ConfigMap is named after the -/// cluster itself. +/// cluster itself. Discovery is a role-level object (it exposes the Router role), so it carries +/// the role-level recommended labels. fn discovery_configmap_meta(cluster: &ValidatedCluster) -> ObjectMetaBuilder { object_meta( cluster, cluster.name.to_string(), - cluster.recommended_labels(&DruidRole::Router, &PLACEHOLDER_DISCOVERY_ROLE_GROUP), + recommended_labels_for_role_resources(cluster, &DruidRole::Router), ) } diff --git a/rust/operator-binary/src/controller/build/resource/listener.rs b/rust/operator-binary/src/controller/build/resource/listener.rs index 12e91113..1a52aca6 100644 --- a/rust/operator-binary/src/controller/build/resource/listener.rs +++ b/rust/operator-binary/src/controller/build/resource/listener.rs @@ -20,7 +20,7 @@ use stackable_operator::{ use crate::{ controller::{ - build::{NONE_ROLE_GROUP_NAME, object_meta, security::listener_ports}, + build::{object_meta, recommended_labels_for_role_resources, security::listener_ports}, validate::ValidatedCluster, }, crd::{ @@ -38,13 +38,13 @@ pub fn build_group_listener( listener_group_name: ListenerName, druid_role: &DruidRole, ) -> Listener { - // The group listener is a role-level (not role-group-level) object, so there is no real - // role-group name; the placeholder is used for the recommended labels. + // The group listener is a role-level (not role-group-level) object, so it carries the + // role-level recommended labels. Listener { metadata: object_meta( cluster, listener_group_name.to_string(), - cluster.recommended_labels(druid_role, &NONE_ROLE_GROUP_NAME), + recommended_labels_for_role_resources(cluster, druid_role), ) .build(), spec: listener::v1alpha1::ListenerSpec { @@ -90,7 +90,11 @@ pub fn general_group_listener_name( cluster_name: &ClusterName, druid_role: &DruidRole, ) -> ListenerName { - ListenerName::from_str(&format!("{cluster_name}-{druid_role}")).expect("a valid listener name") + ListenerName::from_str(&format!( + "{cluster_name}-{druid_role}", + druid_role = **druid_role + )) + .expect("a valid listener name") } /// The connection string (`
:`) for the given ingress address, or `None` when the diff --git a/rust/operator-binary/src/controller/build/resource/pdb.rs b/rust/operator-binary/src/controller/build/resource/pdb.rs index 33ab8e9b..41d419a9 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::{controller_name, operator_name, product_name, validate::ValidatedCluster}, + controller::{CONTROLLER_NAME, OPERATOR_NAME, PRODUCT_NAME, validate::ValidatedCluster}, crd::DruidRole, }; @@ -26,10 +26,10 @@ pub fn build_pdb( }); let pdb = pod_disruption_budget_builder_with_role( cluster, - &product_name(), - &role.into(), - &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 77495b11..d42741f8 100644 --- a/rust/operator-binary/src/controller/build/resource/rbac.rs +++ b/rust/operator-binary/src/controller/build/resource/rbac.rs @@ -1,27 +1,20 @@ //! 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::validate::ValidatedCluster; - -stackable_operator::constant!(NONE_ROLE_NAME: RoleName = "none"); -stackable_operator::constant!(NONE_ROLE_GROUP_NAME: RoleGroupName = "none"); +use crate::controller::{ + build::recommended_labels_for_cluster_resources, validate::ValidatedCluster, +}; /// Builds the [`ServiceAccount`] that all role-group Pods run under. 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), ) } @@ -31,12 +24,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 cd2bfca4..2de438c7 100644 --- a/rust/operator-binary/src/controller/build/resource/service.rs +++ b/rust/operator-binary/src/controller/build/resource/service.rs @@ -8,7 +8,10 @@ use stackable_operator::{ use crate::{ controller::{ - build::{object_meta, security::service_ports}, + build::{ + object_meta, recommended_labels_for_role_group_resources, role_group_selector, + security::service_ports, + }, validate::ValidatedCluster, }, crd::{DruidRole, METRICS_PORT, METRICS_PORT_NAME}, @@ -28,7 +31,7 @@ pub fn build_rolegroup_headless_service( .role_group_resource_names(druid_role, role_group_name) .headless_service_name() .to_string(), - cluster.recommended_labels(druid_role, role_group_name), + recommended_labels_for_role_group_resources(cluster, druid_role, role_group_name), ) .build(), spec: Some(ServiceSpec { @@ -39,11 +42,7 @@ pub fn build_rolegroup_headless_service( &cluster.cluster_config.druid_tls_security, druid_role, )), - selector: Some( - cluster - .role_group_selector(druid_role, role_group_name) - .into(), - ), + selector: Some(role_group_selector(cluster, druid_role, role_group_name).into()), publish_not_ready_addresses: Some(true), ..ServiceSpec::default() }), @@ -64,7 +63,7 @@ pub fn build_rolegroup_metrics_service( .role_group_resource_names(druid_role, role_group_name) .metrics_service_name() .to_string(), - cluster.recommended_labels(druid_role, role_group_name), + recommended_labels_for_role_group_resources(cluster, druid_role, role_group_name), ) .with_labels(prometheus_labels(&Scraping::Enabled)) .with_annotations(prometheus_annotations( @@ -79,11 +78,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(druid_role, role_group_name) - .into(), - ), + selector: Some(role_group_selector(cluster, druid_role, role_group_name).into()), publish_not_ready_addresses: Some(true), ..ServiceSpec::default() }), diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index 76ba4b6a..fb6307dd 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -38,10 +38,13 @@ use crate::{ graceful_shutdown::add_graceful_shutdown_config, object_meta, properties::product_logging::MAX_DRUID_LOG_FILES_SIZE, + recommended_labels_for_role_group_resources, + recommended_labels_for_unversioned_role_group_resources, resource::listener::{ LISTENER_VOLUME_DIR, LISTENER_VOLUME_NAME, build_group_listener_pvc, group_listener_name, secret_volume_listener_scope, }, + role_group_selector, security::{ add_tls_volume_and_volume_mounts, build_tls_key_stores_cmd, container_ports, get_tcp_socket_probe, @@ -301,8 +304,10 @@ pub fn build_rolegroup_statefulset( .add_volume_mount(&*LISTENER_VOLUME_NAME, LISTENER_VOLUME_DIR) .context(AddVolumeMountSnafu)?; + // 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. let unversioned_recommended_labels = - cluster.unversioned_recommended_labels(role, role_group_name); + recommended_labels_for_unversioned_role_group_resources(cluster, role, role_group_name); pvcs = Some(vec![build_group_listener_pvc( &group_listener_name, @@ -311,7 +316,11 @@ pub fn build_rolegroup_statefulset( } let metadata = ObjectMetaBuilder::new() - .with_labels(cluster.recommended_labels(role, role_group_name)) + .with_labels(recommended_labels_for_role_group_resources( + cluster, + role, + role_group_name, + )) .build(); pb.image_pull_secrets_from_product_image(resolved_product_image) @@ -352,7 +361,7 @@ pub fn build_rolegroup_statefulset( metadata: object_meta( cluster, resource_names.stateful_set_name().to_string(), - cluster.recommended_labels(role, role_group_name), + recommended_labels_for_role_group_resources(cluster, role, role_group_name), ) .with_label(RESTART_CONTROLLER_ENABLED_LABEL.to_owned()) .build(), @@ -362,7 +371,7 @@ pub fn build_rolegroup_statefulset( // HorizontalPodAutoscaler can own the replica count without the operator fighting it. replicas: rg.replicas.map(i32::from), selector: LabelSelector { - match_labels: Some(cluster.role_group_selector(role, role_group_name).into()), + match_labels: Some(role_group_selector(cluster, role, role_group_name).into()), ..LabelSelector::default() }, service_name: Some(resource_names.headless_service_name().to_string()), diff --git a/rust/operator-binary/src/controller/update_status.rs b/rust/operator-binary/src/controller/update_status.rs index 1ee01c06..357a8a26 100644 --- a/rust/operator-binary/src/controller/update_status.rs +++ b/rust/operator-binary/src/controller/update_status.rs @@ -12,7 +12,7 @@ use strum::{EnumDiscriminants, IntoStaticStr}; use crate::{ controller::{Applied, KubernetesResources}, - crd::{DruidClusterStatus, OPERATOR_NAME, v1alpha1}, + crd::{DRUID_OPERATOR_NAME, DruidClusterStatus, v1alpha1}, }; #[derive(Snafu, Debug, EnumDiscriminants)] @@ -47,7 +47,7 @@ pub async fn update_status( }; client - .apply_patch_status(OPERATOR_NAME, druid, &status) + .apply_patch_status(DRUID_OPERATOR_NAME, druid, &status) .await .context(ApplyStatusSnafu)?; diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index 406432f5..49b7ee9c 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -20,16 +20,14 @@ use stackable_operator::{ database_connections::drivers::jdbc::{JdbcDatabaseConnection, JdbcDatabaseConnectionDetails}, k8s_openapi::api::core::v1::{ConfigMap, Secret, Volume}, kube::{Resource, api::ObjectMeta}, - kvp::Labels, v2::{ HasName, HasUid, NameIsValidLabelValue, controller_utils::{get_cluster_name, get_namespace, get_uid}, - kvp::label::{recommended_labels, role_group_selector}, role_group_utils::ResourceNames, role_utils, types::{ kubernetes::{ListenerClassName, NamespaceName, Uid}, - operator::{ClusterName, ProductVersion, RoleGroupName, RoleName}, + operator::{ClusterName, ProductVersion, RoleGroupName}, }, }, }; @@ -37,7 +35,7 @@ use strum::IntoEnumIterator; use crate::{ authentication::DruidAuthenticationConfig, - controller::{controller_name, dereference::DereferencedObjects, operator_name, product_name}, + controller::{PRODUCT_NAME, dereference::DereferencedObjects}, crd::{ DeepStorageSpec, DruidRole, authentication::AuthenticationClassesResolved, database::MetadataDatabaseConnection, security::DruidTlsSecurity, v1alpha1, @@ -90,9 +88,6 @@ type Result = std::result::Result; /// re-exported here for the build step. pub use crate::crd::DruidRoleGroupConfig; -// Placeholder version label value for resources whose labels must not change after deployment. -stackable_operator::constant!(UNVERSIONED_PRODUCT_VERSION: ProductVersion = "none"); - /// Cluster-wide resolved fields that are not role/rolegroup specific. pub struct ValidatedClusterConfig { pub zookeeper_connection_string: String, @@ -204,59 +199,12 @@ impl ValidatedCluster { .expect("every DruidRole has a validated role config") } - 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, - ) - } - - /// Recommended labels for a resource that is not tied to a concrete [`DruidRole`] (e.g. the - /// cluster-shared RBAC resources), 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 for a role-group resource. - pub fn recommended_labels(&self, role: &DruidRole, role_group_name: &RoleGroupName) -> Labels { - self.recommended_labels_for(&role.into(), 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: &DruidRole, - role_group_name: &RoleGroupName, - ) -> Labels { - self.recommended_labels_with(&UNVERSIONED_PRODUCT_VERSION, &role.into(), role_group_name) - } - - /// Selector labels matching the pods of a role group. - pub fn role_group_selector(&self, role: &DruidRole, role_group_name: &RoleGroupName) -> Labels { - role_group_selector(self, &product_name(), &role.into(), role_group_name) - } - /// Type-safe names for the per-cluster RBAC resources: the ServiceAccount shared by all /// Pods, its (namespaced) RoleBinding, and the operator-deployed ClusterRole it binds. 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(), } } @@ -268,7 +216,7 @@ impl ValidatedCluster { ) -> ResourceNames { ResourceNames { cluster_name: self.name.clone(), - role_name: role.into(), + role_name: (**role).clone(), role_group_name: role_group_name.clone(), } } @@ -588,7 +536,7 @@ spec: #[cfg(test)] mod tests { - use stackable_operator::{cli::OperatorEnvironmentOptions, v2::types::operator::RoleName}; + use stackable_operator::cli::OperatorEnvironmentOptions; use strum::IntoEnumIterator; use super::{ @@ -638,11 +586,11 @@ mod tests { for role in DruidRole::iter() { assert!( validated.role_group_configs.contains_key(&role), - "missing role-group configs for {role}" + "missing role-group configs for {role:?}" ); assert!( validated.role_configs.contains_key(&role), - "missing role config for {role}" + "missing role config for {role:?}" ); } @@ -699,14 +647,4 @@ mod tests { "expected a ClusterIdentity error when the cluster has no uid" ); } - - /// Locks the invariant behind the `expect` in the `From for RoleName` impls: - /// every `DruidRole` variant (present and future) must serialise to a valid `RoleName`. - #[test] - fn every_druid_role_serialises_to_a_valid_role_name() { - for role in DruidRole::iter() { - let _: RoleName = (&role).into(); - let _: RoleName = role.into(); - } - } } diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index dbd2f360..3cc04cd5 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -1,5 +1,6 @@ use std::{ collections::{BTreeMap, HashSet}, + ops::Deref, str::FromStr, }; @@ -18,6 +19,7 @@ use stackable_operator::{ fragment::{Fragment, ValidationError}, merge::Merge, }, + constant, crd::{ authentication::{core, oidc}, s3, @@ -30,19 +32,18 @@ use stackable_operator::{ framework::{create_vector_shutdown_file_command, remove_vector_shutdown_file_command}, spec::Logging, }, - role_utils::{GenericRoleConfig, Role}, + role_utils::GenericRoleConfig, schemars::{self, JsonSchema}, shared::time::Duration, status::condition::{ClusterCondition, HasStatusCondition}, utils::{COMMON_BASH_TRAP_FUNCTIONS, crds::raw_object_list_schema}, v2::{ - builder::pod::container::{EnvVarName, EnvVarSet}, config_overrides::KeyValueConfigOverrides, product_logging::framework::{ STACKABLE_LOG_DIR, ValidatedContainerLogConfigChoice, VectorContainerLogConfig, validate_logging_configuration_for_container, }, - role_utils::{JavaCommonConfig, RoleGroupConfig, with_validated_config}, + role_utils::{JavaCommonConfig, Role, RoleGroupConfig, with_validated_config}, types::{ common::Port, kubernetes::{ConfigMapName, ContainerName, ListenerClassName}, @@ -51,7 +52,7 @@ use stackable_operator::{ }, versioned::versioned, }; -use strum::{Display, EnumIter, EnumString}; +use strum::{Display, EnumIter}; use crate::crd::{ affinity::get_affinity, @@ -72,7 +73,7 @@ pub mod storage; pub mod tls; pub const APP_NAME: &str = "druid"; -pub const OPERATOR_NAME: &str = "druid.stackable.tech"; +pub const DRUID_OPERATOR_NAME: &str = "druid.stackable.tech"; // config directories pub const DRUID_CONFIG_DIRECTORY: &str = "/stackable/config"; @@ -163,12 +164,6 @@ pub enum Error { role_group: String, }, - #[snafu(display("invalid environment variable override name in role group {role_group:?}"))] - ParseEnvVarName { - source: stackable_operator::v2::macros::attributed_string_type::Error, - role_group: String, - }, - #[snafu(display("invalid role group name {role_group:?}"))] ParseRoleGroupName { source: stackable_operator::v2::macros::attributed_string_type::Error, @@ -409,20 +404,6 @@ impl v1alpha1::DruidCluster { .requested_secret_lifetime .context(MissingSecretLifetimeSnafu)?, }; - // Upstream returns env overrides as a `HashMap`; the build step consumes an - // `EnvVarSet`. Convert here, validating each name. (Role/role-group precedence - // is already resolved by `with_validated_config`.) - let mut env_overrides = EnvVarSet::new(); - for (name, value) in validated.config.env_overrides { - env_overrides = env_overrides.with_value( - &EnvVarName::from_str(&name).with_context(|_| { - ParseEnvVarNameSnafu { - role_group: rg_name.clone(), - } - })?, - value, - ); - } let role_group_name = RoleGroupName::from_str(rg_name).with_context(|_| { ParseRoleGroupNameSnafu { role_group: rg_name.clone(), @@ -434,7 +415,7 @@ impl v1alpha1::DruidCluster { replicas: validated.replicas, config: common, config_overrides: validated.config.config_overrides, - env_overrides, + env_overrides: validated.config.env_overrides.into(), cli_overrides: validated.config.cli_overrides, pod_overrides: validated.config.pod_overrides, product_specific_common_config: validated @@ -602,45 +583,32 @@ fn druid_default_listener_class() -> ListenerClassName { ListenerClassName::from_str("cluster-internal").expect("a valid listener class name") } -#[derive( - Clone, - Debug, - Deserialize, - Display, - EnumIter, - Eq, - Hash, - JsonSchema, - Ord, - PartialEq, - PartialOrd, - Serialize, - EnumString, -)] +constant!(COORDINATOR_ROLE_NAME: RoleName = "coordinator"); +constant!(BROKER_ROLE_NAME: RoleName = "broker"); +constant!(HISTORICAL_ROLE_NAME: RoleName = "historical"); +constant!(MIDDLE_MANAGER_ROLE_NAME: RoleName = "middlemanager"); +constant!(ROUTER_ROLE_NAME: RoleName = "router"); + +#[derive(Clone, Debug, EnumIter, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum DruidRole { - #[strum(serialize = "coordinator")] Coordinator, - #[strum(serialize = "broker")] Broker, - #[strum(serialize = "historical")] Historical, - #[strum(serialize = "middlemanager")] MiddleManager, - #[strum(serialize = "router")] Router, } -impl From for RoleName { - fn from(value: DruidRole) -> Self { - RoleName::from_str(&value.to_string()) - .expect("a DruidRole always serializes to a valid role name") - } -} +impl Deref for DruidRole { + type Target = RoleName; -impl From<&DruidRole> for RoleName { - fn from(value: &DruidRole) -> Self { - RoleName::from_str(&value.to_string()) - .expect("a DruidRole always serializes to a valid role name") + fn deref(&self) -> &Self::Target { + match self { + DruidRole::Coordinator => &COORDINATOR_ROLE_NAME, + DruidRole::Broker => &BROKER_ROLE_NAME, + DruidRole::Historical => &HISTORICAL_ROLE_NAME, + DruidRole::MiddleManager => &MIDDLE_MANAGER_ROLE_NAME, + DruidRole::Router => &ROUTER_ROLE_NAME, + } } } @@ -932,8 +900,19 @@ pub fn build_string_list(strings: &[String]) -> String { mod tests { use stackable_operator::versioned::test_utils::RoundtripTestData; + use super::*; use crate::crd::v1alpha1; + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *COORDINATOR_ROLE_NAME; + let _ = *BROKER_ROLE_NAME; + let _ = *HISTORICAL_ROLE_NAME; + let _ = *MIDDLE_MANAGER_ROLE_NAME; + let _ = *ROUTER_ROLE_NAME; + } + impl RoundtripTestData for v1alpha1::DruidClusterSpec { fn roundtrip_test_data() -> Vec { stackable_operator::utils::yaml_from_str_singleton_map(indoc::indoc! {" diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 1bd3d2f7..f3f8c0ef 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -34,7 +34,7 @@ use stackable_operator::{ }; use crate::{ - crd::{DruidCluster, DruidClusterVersion, OPERATOR_NAME, v1alpha1}, + crd::{DRUID_OPERATOR_NAME, DruidCluster, DruidClusterVersion, v1alpha1}, webhooks::conversion::create_webhook_server, }; @@ -94,7 +94,7 @@ async fn main() -> anyhow::Result<()> { .map(anyhow::Ok); let client = stackable_operator::client::initialize_operator( - Some(OPERATOR_NAME.to_string()), + Some(DRUID_OPERATOR_NAME.to_string()), &common.cluster_info, ) .await?; From 21f579cbc51ed74d8ee523b6cb7dff6fe2f41184 Mon Sep 17 00:00:00 2001 From: Andrew Kenworthy Date: Tue, 18 Aug 2026 12:49:50 +0200 Subject: [PATCH 2/6] updated changelog, added missing import --- CHANGELOG.md | 6 +++--- rust/operator-binary/src/controller.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9571c410..b9d5dfc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,12 +15,12 @@ All notable changes to this project will be documented in this file. apply and update_status steps ([#856]). - All product containers now run with `securityContext.runAsNonRoot` set to `true` to improve security ([#860]). - `envOverrides` names are now validated by the shared `EnvVarName` type rather than by - operator-specific validation code ([#XXX]). + operator-specific validation code ([#865]). - 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 broker, coordinator and router StatefulSet so that the operator - immediately recreates it with the new labels ([#XXX]). + immediately recreates it with the new labels ([#865]). ### Fixed @@ -33,7 +33,7 @@ All notable changes to this project will be documented in this file. [#855]: https://github.com/stackabletech/druid-operator/pull/855 [#856]: https://github.com/stackabletech/druid-operator/pull/856 [#860]: https://github.com/stackabletech/druid-operator/pull/860 -[#XXX]: https://github.com/stackabletech/druid-operator/pull/XXX +[#865]: https://github.com/stackabletech/druid-operator/pull/865 ## [26.7.0] - 2026-07-21 diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 52a25b54..c6c2bad6 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -1,7 +1,7 @@ //! Ensures that `Pod`s are configured and running for each [`DruidCluster`][v1alpha1] //! //! [v1alpha1]: v1alpha1::DruidCluster -use std::{marker::PhantomData, sync::Arc}; +use std::{marker::PhantomData, str::FromStr, sync::Arc}; use const_format::concatcp; use snafu::{ResultExt, Snafu}; From a14b60ae3edfda848f0d9da4dce16cb265019b48 Mon Sep 17 00:00:00 2001 From: Andrew Kenworthy Date: Tue, 18 Aug 2026 13:03:34 +0200 Subject: [PATCH 3/6] cargo update due to RUSTSECs --- Cargo.lock | 221 +++++++++++++++++++++++++++-------------------------- 1 file changed, 111 insertions(+), 110 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62d14f10..72f964c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.91" +version = "0.1.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", @@ -316,9 +316,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.4.1" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9066c49992464636f92905fa096ec58baaa4d57ec19a5c096c68d3e25ef3d136" +checksum = "509591b7bcd67f4ef775afad7662703b4935daaa6ec0e5605cfb1090b32a2b6d" dependencies = [ "find-msvc-tools", "jobserver", @@ -631,7 +631,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -910,9 +910,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de" +checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" [[package]] name = "flagset" @@ -974,9 +974,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" dependencies = [ "futures-channel", "futures-core", @@ -989,9 +989,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -999,15 +999,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ "futures-core", "futures-task", @@ -1016,32 +1016,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-macro" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] name = "futures-sink" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-timer" @@ -1051,9 +1051,9 @@ checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" [[package]] name = "futures-util" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures 0.1.31", "futures-channel", @@ -1169,9 +1169,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +checksum = "a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27" dependencies = [ "atomic-waker", "bytes", @@ -1251,9 +1251,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes", "futures-core", @@ -1381,9 +1381,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" dependencies = [ "displaydoc", "potential_utf", @@ -1395,9 +1395,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" dependencies = [ "displaydoc", "litemap", @@ -1408,9 +1408,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -1422,16 +1422,17 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" [[package]] name = "icu_properties" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" dependencies = [ + "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -1442,15 +1443,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" [[package]] name = "icu_provider" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +checksum = "92a7ed671a6aad807a8651a2e1782a6598fda9ce5185dd8158549e95a91c6428" dependencies = [ "displaydoc", "icu_locale_core", @@ -1619,7 +1620,7 @@ dependencies = [ "jni-sys", "log", "simd_cesu8", - "thiserror 2.0.19", + "thiserror 2.0.20", "walkdir", "windows-link", ] @@ -1668,9 +1669,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ "cfg-if", "futures-util", @@ -1687,7 +1688,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -1700,7 +1701,7 @@ dependencies = [ "pest_derive", "regex", "serde_json", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -1773,7 +1774,7 @@ dependencies = [ "base64 0.22.1", "bytes", "either", - "futures 0.3.33", + "futures 0.3.34", "http", "http-body", "http-body-util", @@ -1792,7 +1793,7 @@ dependencies = [ "serde", "serde-saphyr", "serde_json", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio", "tokio-util", "tower", @@ -1816,7 +1817,7 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -1844,7 +1845,7 @@ dependencies = [ "async-stream", "backon", "educe 0.6.0", - "futures 0.3.33", + "futures 0.3.34", "hashbrown 0.16.1", "hostname", "json-patch", @@ -1854,7 +1855,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio", "tokio-util", "tracing", @@ -1907,9 +1908,9 @@ dependencies = [ [[package]] name = "litemap" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" [[package]] name = "lock_api" @@ -2013,9 +2014,9 @@ checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" dependencies = [ "num-traits", ] @@ -2105,7 +2106,7 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.19", + "thiserror 2.0.20", "tracing", ] @@ -2147,7 +2148,7 @@ dependencies = [ "opentelemetry_sdk", "prost", "reqwest", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio", "tonic", "tonic-types", @@ -2185,7 +2186,7 @@ dependencies = [ "percent-encoding", "portable-atomic", "rand 0.9.5", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio", "tokio-stream", ] @@ -2267,9 +2268,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.8" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df728be843c7070fab6ab7c328c4e9e9d78e23bf749c0669c86ee7ebfa050a2" +checksum = "5a07a60cc7a4d00c91f95c685609d1d2f79050e6804b70ebedd7650f0b839bcf" dependencies = [ "memchr", "ucd-trie", @@ -2277,9 +2278,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.8" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e2dd6fc3b26b3462ee188aac870f5a41d398f1cd5e2408d16531bd71c9591fd" +checksum = "b3a83744a5c8455b8b3e0dc5031362780a347c878bdd11584d1a8984228cc88d" dependencies = [ "pest", "pest_generator", @@ -2287,9 +2288,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.8" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a7a9205cfb6f596a9e8b689c0a15f9ceb7a1aafae7aaf788150ac65b29975b6" +checksum = "e0cd3451aa3de60d4b9a1e736885e4dea6b31617598026f12256ad566d63304a" dependencies = [ "pest", "pest_meta", @@ -2300,9 +2301,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.8" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85abd351c0de1e8384fc791a0737111a350394937e92b956b743dac12429f57c" +checksum = "e04d3a0849e241d7dfce834c83b1c5edc8622009e8dd51a12ba1927c32f05496" dependencies = [ "pest", ] @@ -2356,15 +2357,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] name = "portable-atomic" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "portable-atomic-util" @@ -2377,9 +2378,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ "zerovec", ] @@ -2797,9 +2798,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.13" +version = "0.103.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a" dependencies = [ "ring", "rustls-pki-types", @@ -3237,7 +3238,7 @@ dependencies = [ "clap", "const_format", "fnv", - "futures 0.3.33", + "futures 0.3.34", "indoc", "openssl", "pin-project", @@ -3266,7 +3267,7 @@ dependencies = [ "dockerfile-parser", "educe 0.7.6", "either", - "futures 0.3.33", + "futures 0.3.34", "http", "indexmap", "java-properties", @@ -3517,11 +3518,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl 2.0.19", + "thiserror-impl 2.0.20", ] [[package]] @@ -3537,9 +3538,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", @@ -3587,9 +3588,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" dependencies = [ "displaydoc", "zerovec", @@ -3848,7 +3849,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror 2.0.19", + "thiserror 2.0.20", "time", "tracing-subscriber", ] @@ -4013,9 +4014,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.24.0" +version = "1.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" +checksum = "2cefc03fd367c0c6d4305de1b312cf00248c4114f4a0418ce6a6af769e3b0bd9" dependencies = [ "js-sys", "wasm-bindgen", @@ -4075,9 +4076,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if", "once_cell", @@ -4088,9 +4089,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.76" +version = "0.4.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" dependencies = [ "js-sys", "wasm-bindgen", @@ -4098,9 +4099,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4108,9 +4109,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ "bumpalo", "proc-macro2", @@ -4121,18 +4122,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" dependencies = [ "js-sys", "wasm-bindgen", @@ -4324,9 +4325,9 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "writeable" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] name = "x509-cert" @@ -4434,9 +4435,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" dependencies = [ "displaydoc", "yoke", @@ -4445,9 +4446,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +checksum = "94b5c6b5976d66c1d703c4fd17d3f5e43c8cedaacf604961b171adc7130896d8" dependencies = [ "yoke", "zerofrom", @@ -4456,13 +4457,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +checksum = "9f212a141d820099d57ffafb9569be9617a6f27d3dc881fbee8fb56642f917a9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] From 8a337ee9c686bad4ae3c933dfe6d568f610b4782 Mon Sep 17 00:00:00 2001 From: Andrew Kenworthy Date: Tue, 18 Aug 2026 13:38:47 +0200 Subject: [PATCH 4/6] regenerate nix --- Cargo.nix | 256 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 133 insertions(+), 123 deletions(-) diff --git a/Cargo.nix b/Cargo.nix index 5a7e9c43..df86d404 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -489,9 +489,9 @@ rec { }; "async-trait" = rec { crateName = "async-trait"; - version = "0.1.91"; + version = "0.1.92"; edition = "2021"; - sha256 = "1v3cm8mzg66037wm392p1vsdx0lq8bid6y2ivr7z03lpfx0xqdmf"; + sha256 = "0rqn5iga1hlv2lm8xzav1zhar46jb4dvx89i6kfv93kb53maxxl2"; procMacro = true; libName = "async_trait"; authors = [ @@ -989,9 +989,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.4.1"; + version = "1.4.3"; edition = "2021"; - sha256 = "0dniydgf5lv8dh4mr6n1gvas9albqmp0kyh557wkcij6jacw8rlh"; + sha256 = "0v9b5arr047vbihfbh3fmbd3aj9vf1i7dbdgfpvlwzynpjvr35ah"; dependencies = [ { name = "find-msvc-tools"; @@ -1903,7 +1903,7 @@ rec { dependencies = [ { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } ]; features = { @@ -2794,9 +2794,9 @@ rec { }; "find-msvc-tools" = rec { crateName = "find-msvc-tools"; - version = "0.1.10"; + version = "0.1.11"; edition = "2021"; - sha256 = "1pp1612g5k6im9732g16j6a87czhb35xcyzlrpq2mkgdwrrkbdr6"; + sha256 = "145qpfb9r4ml2klr8v4byvrkikp61qyiks9n69b8z0vbscbb0pfl"; libName = "find_msvc_tools"; }; @@ -2951,11 +2951,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "use_std" "with-deprecated" ]; }; - "futures 0.3.33" = rec { + "futures 0.3.34" = rec { crateName = "futures"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "066j5aqz8an05xh4hn5ljdnjn80z3g335v4grx4gaifr57wg3358"; + sha256 = "18yhwmbdalhz2z9i1vm10hy2v0cfm82dkgcb6vr2msxazfix4ccs"; dependencies = [ { name = "futures-channel"; @@ -3015,9 +3015,9 @@ rec { }; "futures-channel" = rec { crateName = "futures-channel"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "1bn5hlhfkl1sgypmiachaqcgwmr6wmjal7dyhfyb1zkazvs90996"; + sha256 = "1i4kwcanpaphn1ax62ci3nx176kglxqx0gnhzqpqdr1rkpbf7ydi"; libName = "futures_channel"; dependencies = [ { @@ -3043,9 +3043,9 @@ rec { }; "futures-core" = rec { crateName = "futures-core"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "1iqdbvcdlplfr2g43h7xrfkv2sg5p1a26x8acz1xgxl07i3hrm9c"; + sha256 = "0pjgv4fx0np6hrs5sz5a2phabwv0z70yr51v03injbi44bjrkmlj"; libName = "futures_core"; features = { "default" = [ "std" ]; @@ -3056,9 +3056,9 @@ rec { }; "futures-executor" = rec { crateName = "futures-executor"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "0n3lpkmcfrsnh40i4armn040gnqbpd257hz5qs46zipjr6f8fm37"; + sha256 = "0cjl3y7jgg60wwb96ikxj23r6q91ylvx8v675yychv1w3b7lf6q3"; libName = "futures_executor"; dependencies = [ { @@ -3086,9 +3086,9 @@ rec { }; "futures-io" = rec { crateName = "futures-io"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "0yjx13qdm9b2p4w00ddw85k6yccnnmqrlrrz8yfmi5jg7jmfqxs5"; + sha256 = "1v9z6wj92ra18kpv0xig21hgpzrvcwmcr8fszyzh64yyay0zmh2k"; libName = "futures_io"; features = { "default" = [ "std" ]; @@ -3097,9 +3097,9 @@ rec { }; "futures-macro" = rec { crateName = "futures-macro"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "02xiyd5y1nk9b805aympj4wq2czgvxnhcml9w9xkc665d3g3qv9d"; + sha256 = "0i0czvcvsqq4hrccibq2f23004si5z34zjwdxfmqhlrmm15nbfcz"; procMacro = true; libName = "futures_macro"; dependencies = [ @@ -3113,7 +3113,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.119"; + packageId = "syn 3.0.3"; features = [ "full" ]; } ]; @@ -3121,9 +3121,9 @@ rec { }; "futures-sink" = rec { crateName = "futures-sink"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "01z38z344hpryw84b6r0rbwcb669d8pyvl2szg10aqwx96n1hi73"; + sha256 = "07cfvrgc3vxk6sw5g8a8dnrm1mzg6d5mwy08ywa1sgyhyxml4i0r"; libName = "futures_sink"; features = { "default" = [ "std" ]; @@ -3133,9 +3133,9 @@ rec { }; "futures-task" = rec { crateName = "futures-task"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "02f1y1yvjg1cv998zkgl1706pi9y4fyc9045l1hlmyqyhclfscdj"; + sha256 = "1zfilqs8nwlfqz4prk7ihvpp5avvzins87ibzlxzq5fhs7ipshfd"; libName = "futures_task"; features = { "default" = [ "std" ]; @@ -3160,9 +3160,9 @@ rec { }; "futures-util" = rec { crateName = "futures-util"; - version = "0.3.33"; + version = "0.3.34"; edition = "2018"; - sha256 = "1anyg40j5www5l22r2jbn1birsafz4q1w9qmcjk4vqzwasi90ym7"; + sha256 = "1g3r9ghzq7c2fh34lis43i72xavk9p84npgfwgb5vfpqcwjajl0d"; libName = "futures_util"; dependencies = [ { @@ -3649,9 +3649,9 @@ rec { }; "h2" = rec { crateName = "h2"; - version = "0.4.15"; + version = "0.4.16"; edition = "2021"; - sha256 = "0mgilh1g8gydcchqi6acs5l6j0gwg5jwpa64sj4b3ncb9v497c3c"; + sha256 = "09syqqhvh36b3rwyn8vjhiz597hfki1hcz3hwagb3cs1ifapmwx9"; authors = [ "Carl Lerche " "Sean McArthur " @@ -3889,9 +3889,9 @@ rec { }; "http-body-util" = rec { crateName = "http-body-util"; - version = "0.1.4"; + version = "0.1.5"; edition = "2018"; - sha256 = "1wizkqx9a75x8v5lm7cawpammz8sfvd7cngnkp34wkcfl3b1zx79"; + sha256 = "07773iilap808wjp6vywlq15zkgwnswqzrv270zxvg2z9biry5i3"; libName = "http_body_util"; authors = [ "Carl Lerche " @@ -4399,9 +4399,9 @@ rec { }; "icu_collections" = rec { crateName = "icu_collections"; - version = "2.2.0"; - edition = "2021"; - sha256 = "070r7xd0pynm0hnc1v2jzlbxka6wf50f81wybf9xg0y82v6x3119"; + version = "2.3.0"; + edition = "2024"; + sha256 = "04x59h6vdq0cnpippim1nr471ivlsnnn470sj1d5v864h48d4s7s"; authors = [ "The ICU4X Project Developers" ]; @@ -4449,9 +4449,9 @@ rec { }; "icu_locale_core" = rec { crateName = "icu_locale_core"; - version = "2.2.0"; - edition = "2021"; - sha256 = "0a9cmin5w1x3bg941dlmgszn33qgq428k7qiqn5did72ndi9n8cj"; + version = "2.3.0"; + edition = "2024"; + sha256 = "1sqdj16wwl7h9y6r7j394av4kpdb7zryz9h169ffwbm9imc2hvnm"; authors = [ "The ICU4X Project Developers" ]; @@ -4501,9 +4501,9 @@ rec { }; "icu_normalizer" = rec { crateName = "icu_normalizer"; - version = "2.2.0"; - edition = "2021"; - sha256 = "1d7krxr0xpc4x9635k1100a24nh0nrc59n65j6yk6gbfkplmwvn5"; + version = "2.3.0"; + edition = "2024"; + sha256 = "0vv43ixk2wmbxrx7kl33cwkhx1wdyb1q3pa18qkyshan4dgwzy8j"; authors = [ "The ICU4X Project Developers" ]; @@ -4555,9 +4555,9 @@ rec { }; "icu_normalizer_data" = rec { crateName = "icu_normalizer_data"; - version = "2.2.0"; - edition = "2021"; - sha256 = "0f5d5d5fhhr9937m2z6z38fzh6agf14z24kwlr6lyczafypf0fys"; + version = "2.3.0"; + edition = "2024"; + sha256 = "1811h0ppb7lwq1q2492p5x6lcmlwmhbmkf69fhyvzcz0scgdlqqm"; authors = [ "The ICU4X Project Developers" ]; @@ -4565,13 +4565,18 @@ rec { }; "icu_properties" = rec { crateName = "icu_properties"; - version = "2.2.0"; - edition = "2021"; - sha256 = "1pkh3s837808cbwxvfagwc28cvwrz2d9h5rl02jwrhm51ryvdqxy"; + version = "2.3.0"; + edition = "2024"; + sha256 = "0j51hi8qgf0l6a7qzvnwsc61598w2fpnsklicld6ci9immva4z3y"; authors = [ "The ICU4X Project Developers" ]; dependencies = [ + { + name = "displaydoc"; + packageId = "displaydoc"; + usesDefaultFeatures = false; + } { name = "icu_collections"; packageId = "icu_collections"; @@ -4613,6 +4618,7 @@ rec { "datagen" = [ "serde" "dep:databake" "zerovec/databake" "icu_collections/databake" "icu_locale_core/databake" "zerotrie/databake" "icu_provider/export" ]; "default" = [ "compiled_data" ]; "harfbuzz_traits" = [ "dep:harfbuzz-traits" ]; + "log" = [ "dep:log" ]; "serde" = [ "dep:serde" "icu_locale_core/serde" "zerovec/serde" "icu_collections/serde" "icu_provider/serde" "zerotrie/serde" ]; "unicode_bidi" = [ "dep:unicode-bidi" ]; }; @@ -4620,9 +4626,9 @@ rec { }; "icu_properties_data" = rec { crateName = "icu_properties_data"; - version = "2.2.0"; - edition = "2021"; - sha256 = "052awny0qwkbcbpd5jg2cd7vl5ry26pq4hz1nfsgf10c3qhbnawf"; + version = "2.3.0"; + edition = "2024"; + sha256 = "1akw1gp5rcaiz377xzsnkx8f92qax4kh3lfn9y4rcjj6q4wg1475"; authors = [ "The ICU4X Project Developers" ]; @@ -4630,9 +4636,9 @@ rec { }; "icu_provider" = rec { crateName = "icu_provider"; - version = "2.2.0"; - edition = "2021"; - sha256 = "08dl8pxbwr8zsz4c5vphqb7xw0hykkznwi4rw7bk6pwb3krlr70k"; + version = "2.3.0"; + edition = "2024"; + sha256 = "0a343jlrb7jlb20xv1airslzv63559wf38jihrx81bba39kyv9wj"; authors = [ "The ICU4X Project Developers" ]; @@ -5131,7 +5137,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } { name = "windows-link"; @@ -5249,9 +5255,9 @@ rec { }; "js-sys" = rec { crateName = "js-sys"; - version = "0.3.103"; + version = "0.3.104"; edition = "2021"; - sha256 = "00lib0b6hqmw56r2hjp7xrv730qacslirbkdlhvmi39zvgy4pd2k"; + sha256 = "0fjsgady7wbv7bbyy6c8qhrd93bnx11qbl83l1g7bb9a4601030f"; libName = "js_sys"; authors = [ "The wasm-bindgen Developers" @@ -5311,7 +5317,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } ]; devDependencies = [ @@ -5360,7 +5366,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } ]; @@ -5637,7 +5643,7 @@ rec { } { name = "futures"; - packageId = "futures 0.3.33"; + packageId = "futures 0.3.34"; optional = true; usesDefaultFeatures = false; features = [ "std" ]; @@ -5737,7 +5743,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } { name = "tokio"; @@ -5773,7 +5779,7 @@ rec { devDependencies = [ { name = "futures"; - packageId = "futures 0.3.33"; + packageId = "futures 0.3.34"; usesDefaultFeatures = false; features = [ "async-await" ]; } @@ -5903,7 +5909,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } ]; devDependencies = [ @@ -6010,7 +6016,7 @@ rec { } { name = "futures"; - packageId = "futures 0.3.33"; + packageId = "futures 0.3.34"; usesDefaultFeatures = false; features = [ "async-await" ]; } @@ -6055,7 +6061,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } { name = "tokio"; @@ -6234,9 +6240,9 @@ rec { }; "litemap" = rec { crateName = "litemap"; - version = "0.8.2"; + version = "0.8.3"; edition = "2021"; - sha256 = "1w7628bc7wwcxc4n4s5kw0610xk06710nh2hn5kwwk2wa91z9nlj"; + sha256 = "1bpgpj87560hmckh3875fbahpmfxbk4g8pzns84h3ykf3nfx3na7"; authors = [ "The ICU4X Project Developers" ]; @@ -6554,9 +6560,9 @@ rec { }; "num-integer" = rec { crateName = "num-integer"; - version = "0.1.46"; + version = "0.1.47"; edition = "2018"; - sha256 = "13w5g54a9184cqlbsq80rnxw4jj4s0d8wv75jsq5r2lms8gncsbr"; + sha256 = "02z1p3azy6p10n99skrab4a6hhfd4amf2i9gm8sxqd1p9dfxkqkw"; libName = "num_integer"; authors = [ "The Rust Project Developers" @@ -6808,7 +6814,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; optional = true; usesDefaultFeatures = false; } @@ -6978,7 +6984,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; usesDefaultFeatures = false; } { @@ -7185,7 +7191,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; usesDefaultFeatures = false; } { @@ -7486,9 +7492,9 @@ rec { }; "pest" = rec { crateName = "pest"; - version = "2.8.8"; + version = "2.9.0"; edition = "2021"; - sha256 = "18jhl2zpxvl6kikc0jgp7gi7i7cy9s634z5bnvx70w1whjz2ixvx"; + sha256 = "1kwvhc5hyrfpxpmp0jw0wr891xyjs44mcs2wz68hrl54qw6ac1ss"; authors = [ "Dragoș Tiselice " ]; @@ -7515,9 +7521,9 @@ rec { }; "pest_derive" = rec { crateName = "pest_derive"; - version = "2.8.8"; + version = "2.9.0"; edition = "2021"; - sha256 = "1zcijlfdf6sk2s6l1qnm3j7kj7d4ymqcial8w4p4dcr67gydcbcy"; + sha256 = "13f8ihi8928s9mc13pcbhxy382kqc89h7i8d7s5mnif8lm23ga5k"; procMacro = true; authors = [ "Dragoș Tiselice " @@ -7543,9 +7549,9 @@ rec { }; "pest_generator" = rec { crateName = "pest_generator"; - version = "2.8.8"; + version = "2.9.0"; edition = "2021"; - sha256 = "1dkmk6r6bb2hh5wayymfmwd7mswwbyhw12dnx2lrdxdnrw2r4yka"; + sha256 = "0jihcdnmdban4bqjd02r2wbb79nywj2nhwqyk95hvrixm98k9kg0"; authors = [ "Dragoș Tiselice " ]; @@ -7581,9 +7587,9 @@ rec { }; "pest_meta" = rec { crateName = "pest_meta"; - version = "2.8.8"; + version = "2.9.0"; edition = "2021"; - sha256 = "0z7m54jc3nj3nxbbk4kyjfa06d8s24vhf6krzj2867nyq18x7aw5"; + sha256 = "15jly0r7r4m15fhm3pg814h65j7dqnqq6k43rvgxfhg29443lkg0"; authors = [ "Dragoș Tiselice " ]; @@ -7714,9 +7720,9 @@ rec { }; "pkg-config" = rec { crateName = "pkg-config"; - version = "0.3.33"; - edition = "2018"; - sha256 = "17jnqmcbxsnwhg9gjf0nh6dj5k0x3hgwi3mb9krjnmfa9v435w8r"; + version = "0.3.34"; + edition = "2021"; + sha256 = "0j05h08nzg0q8rf6lzw7nry0b7kn7x97vc9n4hwrl52fqzxn9d7n"; libName = "pkg_config"; authors = [ "Alex Crichton " @@ -7725,9 +7731,9 @@ rec { }; "portable-atomic" = rec { crateName = "portable-atomic"; - version = "1.14.0"; + version = "1.15.0"; edition = "2018"; - sha256 = "1hyfma9n2cs2ibazpfwrbv61zwg7cv86g0pr5yjkg07qgr4xa81x"; + sha256 = "11csag858ndk5w4yz17h91vy53ynh67r2903gwwdn2cnilzbdj05"; libName = "portable_atomic"; features = { "critical-section" = [ "dep:critical-section" ]; @@ -7758,9 +7764,9 @@ rec { }; "potential_utf" = rec { crateName = "potential_utf"; - version = "0.1.5"; + version = "0.1.6"; edition = "2021"; - sha256 = "0r0518fr32xbkgzqap509s3r60cr0iancsg9j1jgf37cyz7b20q1"; + sha256 = "0qbndl2fpphq7mph41m11vaixs05xrh1s451wxlgap4fdnybjgnq"; authors = [ "The ICU4X Project Developers" ]; @@ -9228,9 +9234,9 @@ rec { }; "rustls-webpki" = rec { crateName = "rustls-webpki"; - version = "0.103.13"; + version = "0.103.14"; edition = "2021"; - sha256 = "0vkm7z9pnxz5qz66p2kmyy2pwx0g4jnsbqk5xzfhs4czcjl2ki31"; + sha256 = "0njk28gvbqrsfg1b5r35y4f80n37kcjylj72fpc0k0g60n3529q5"; libName = "webpki"; dependencies = [ { @@ -9254,7 +9260,7 @@ rec { "alloc" = [ "ring?/alloc" "pki-types/alloc" ]; "aws-lc-rs" = [ "dep:aws-lc-rs" "aws-lc-rs/aws-lc-sys" "aws-lc-rs/prebuilt-nasm" ]; "aws-lc-rs-fips" = [ "dep:aws-lc-rs" "aws-lc-rs/fips" ]; - "aws-lc-rs-unstable" = [ "aws-lc-rs" "aws-lc-rs/unstable" ]; + "aws-lc-rs-unstable" = [ "aws-lc-rs" ]; "default" = [ "std" ]; "ring" = [ "dep:ring" ]; "std" = [ "alloc" "pki-types/std" ]; @@ -10596,7 +10602,7 @@ rec { } { name = "futures"; - packageId = "futures 0.3.33"; + packageId = "futures 0.3.34"; features = [ "compat" ]; } { @@ -10719,7 +10725,7 @@ rec { } { name = "futures"; - packageId = "futures 0.3.33"; + packageId = "futures 0.3.34"; } { name = "http"; @@ -11601,18 +11607,18 @@ rec { ]; }; - "thiserror 2.0.19" = rec { + "thiserror 2.0.20" = rec { crateName = "thiserror"; - version = "2.0.19"; + version = "2.0.20"; edition = "2021"; - sha256 = "1ngwxsjsa64v1n7vb90h2b0i3fqk1piwaf0z6fqdacqfhjc3b909"; + sha256 = "0kxs6p295jffxhzaxpxv1dwaaf5iqlm6sx8h0djp6ancbxgj71pc"; authors = [ "David Tolnay " ]; dependencies = [ { name = "thiserror-impl"; - packageId = "thiserror-impl 2.0.19"; + packageId = "thiserror-impl 2.0.20"; } ]; features = { @@ -11646,11 +11652,11 @@ rec { ]; }; - "thiserror-impl 2.0.19" = rec { + "thiserror-impl 2.0.20" = rec { crateName = "thiserror-impl"; - version = "2.0.19"; + version = "2.0.20"; edition = "2021"; - sha256 = "1ka10pqy1g8zy5al9m8yadg30jp8hx0q80j8awmd8131yw6gxjs3"; + sha256 = "1bwjc94gi0xn5jz26h1a8bjj1wdkvvr6jifamyc4mp9n28zcs15w"; procMacro = true; libName = "thiserror_impl"; authors = [ @@ -11799,9 +11805,9 @@ rec { }; "tinystr" = rec { crateName = "tinystr"; - version = "0.8.3"; + version = "0.8.4"; edition = "2021"; - sha256 = "0vfr8x285w6zsqhna0a9jyhylwiafb2kc8pj2qaqaahw48236cn8"; + sha256 = "0hzncw8rgk4syla79qscfml46jm7ll1zdp7kdacc42cj8n8prqmi"; authors = [ "The ICU4X Project Developers" ]; @@ -12882,7 +12888,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.19"; + packageId = "thiserror 2.0.20"; } { name = "time"; @@ -13417,9 +13423,9 @@ rec { }; "uuid" = rec { crateName = "uuid"; - version = "1.24.0"; + version = "1.24.1"; edition = "2021"; - sha256 = "0faj5x0zgri8m3i8dv9qgyhiwqwdyhbl2g351cp3iin4ynk26fdz"; + sha256 = "1n8b7fg7dbx6ws64387l2i0qq900rw9b7qax63acdh37sczw1vrc"; authors = [ "Ashley Mannix" "Dylan DPC" @@ -13583,9 +13589,9 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.126"; + version = "0.2.127"; edition = "2021"; - sha256 = "197rma4qg1kb8l4bl7857pgszzval8s1w740g9myyjh92467q1jb"; + sha256 = "0w6fa1mkbb6qlkffgy4qaz0hdf496zbjkyiyvs4lvmpd8xbr6w0v"; libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" @@ -13634,9 +13640,9 @@ rec { }; "wasm-bindgen-futures" = rec { crateName = "wasm-bindgen-futures"; - version = "0.4.76"; + version = "0.4.77"; edition = "2021"; - sha256 = "0799v92cpaprapnmpaflc51sdnz362q2fsjdqnwiq8ij1wsg2bf6"; + sha256 = "0l3r8m335kb2p8yj65kb0biwlypcx3ay4g750hafkl13rkapfxvb"; libName = "wasm_bindgen_futures"; authors = [ "The wasm-bindgen Developers" @@ -13662,9 +13668,9 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.126"; + version = "0.2.127"; edition = "2021"; - sha256 = "1cda6wl5zyiy7777cfgrix7fhpaqba55l5zpqj4zig7ng7jyaz0n"; + sha256 = "1hcvlb6bv771fvgifd367wd0cm4giyar8fq5i4h705vj7y7myxvp"; procMacro = true; libName = "wasm_bindgen_macro"; authors = [ @@ -13686,9 +13692,9 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.126"; + version = "0.2.127"; edition = "2021"; - sha256 = "03iq412frl2py55skwb3ya08xha0cf6q22zr5kqlwbr675w7r6gk"; + sha256 = "112j4d7dv8y2sk9yy9czrl9fpjx9388ywnn7icdv2bywazw367g1"; libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" @@ -13722,10 +13728,10 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.126"; + version = "0.2.127"; edition = "2021"; links = "wasm_bindgen"; - sha256 = "097a3kbjls447s1lwr41l21x5crrh5vq3h6zsxccz7slrjq4q6yw"; + sha256 = "1gywp6xv8a27fvm3ga9xby93xyic3hc2s626b9z9rw2xqny4vxky"; libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" @@ -13740,9 +13746,9 @@ rec { }; "web-sys" = rec { crateName = "web-sys"; - version = "0.3.103"; + version = "0.3.104"; edition = "2021"; - sha256 = "0hb1zdnrp99p5r5q66jagsddmwha460yv2wklvzrzk0b3jvdq8l6"; + sha256 = "0c0acbvaqzqf21q5vdff2g74fvb7afi91xjplmclybq4d24k6df4"; libName = "web_sys"; authors = [ "The wasm-bindgen Developers" @@ -13998,6 +14004,10 @@ rec { "MouseEvent" = [ "Event" "UiEvent" ]; "MouseScrollEvent" = [ "Event" "MouseEvent" "UiEvent" ]; "MutationEvent" = [ "Event" ]; + "NavigateEvent" = [ "Event" ]; + "Navigation" = [ "EventTarget" ]; + "NavigationCurrentEntryChangeEvent" = [ "Event" ]; + "NavigationHistoryEntry" = [ "EventTarget" ]; "NetworkInformation" = [ "EventTarget" ]; "Node" = [ "EventTarget" ]; "Notification" = [ "EventTarget" ]; @@ -15120,9 +15130,9 @@ rec { }; "writeable" = rec { crateName = "writeable"; - version = "0.6.3"; + version = "0.6.4"; edition = "2021"; - sha256 = "1i54d13h9bpap2hf13xcry1s4lxh7ap3923g8f3c0grd7c9fbyhz"; + sha256 = "1p3r4s4wbf3dksfpj3xyrn7id5p0f7r74mj6qx6ngjfd6cm2vn1s"; authors = [ "The ICU4X Project Developers" ]; @@ -15432,9 +15442,9 @@ rec { }; "zerotrie" = rec { crateName = "zerotrie"; - version = "0.2.4"; + version = "0.2.5"; edition = "2021"; - sha256 = "1gr0pkcn3qsr6in6iixqyp0vbzwf2j1jzyvh7yl2yydh3p9m548g"; + sha256 = "0gss16krjzk22m57dz5hkdjg99ibj6pa41qr68na7w1jpp1nk8jf"; authors = [ "The ICU4X Project Developers" ]; @@ -15472,9 +15482,9 @@ rec { }; "zerovec" = rec { crateName = "zerovec"; - version = "0.11.6"; + version = "0.11.7"; edition = "2021"; - sha256 = "0fdjsy6b31q9i0d73sl7xjd12xadbwi45lkpfgqnmasrqg5i3ych"; + sha256 = "1n4n109wgbbin5hljq6gmbnqqg74yp9igzf40gbw2rkdjyswddcl"; authors = [ "The ICU4X Project Developers" ]; @@ -15518,9 +15528,9 @@ rec { }; "zerovec-derive" = rec { crateName = "zerovec-derive"; - version = "0.11.3"; + version = "0.11.5"; edition = "2021"; - sha256 = "0m85qj92mmfvhjra6ziqky5b1p4kcmp5069k7kfadp5hr8jw8pb2"; + sha256 = "1a8pz516ddcgxvxq3j1xgprac5wnprlrbyzsgzarj0423la2l8cz"; procMacro = true; libName = "zerovec_derive"; authors = [ @@ -15537,7 +15547,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.119"; + packageId = "syn 3.0.3"; features = [ "extra-traits" ]; } ]; From c2300ad15be7d1b7d47b0301a89bdc0c28ecb4e2 Mon Sep 17 00:00:00 2001 From: Andrew Kenworthy <1712947+adwk67@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:47:09 +0200 Subject: [PATCH 5/6] Update rust/operator-binary/src/controller/build/resource/listener.rs Co-authored-by: maltesander --- rust/operator-binary/src/controller/build/resource/listener.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/operator-binary/src/controller/build/resource/listener.rs b/rust/operator-binary/src/controller/build/resource/listener.rs index 1a52aca6..3ca8bf3b 100644 --- a/rust/operator-binary/src/controller/build/resource/listener.rs +++ b/rust/operator-binary/src/controller/build/resource/listener.rs @@ -92,7 +92,7 @@ pub fn general_group_listener_name( ) -> ListenerName { ListenerName::from_str(&format!( "{cluster_name}-{druid_role}", - druid_role = **druid_role + druid_role = druid_role.as_ref() )) .expect("a valid listener name") } From 6e781ea0accd91f2d735eaf1e6b353e5e5e8e4e4 Mon Sep 17 00:00:00 2001 From: Andrew Kenworthy Date: Tue, 18 Aug 2026 14:50:27 +0200 Subject: [PATCH 6/6] corrected env-var handling, added constant usage and tests --- CHANGELOG.md | 4 + Cargo.nix | 7 +- rust/operator-binary/Cargo.toml | 1 + .../controller/build/authentication/mod.rs | 37 +++--- .../controller/build/authentication/oidc.rs | 49 ++++---- .../src/controller/build/mod.rs | 46 +++++--- .../src/controller/build/resource/listener.rs | 6 + .../controller/build/resource/statefulset.rs | 111 ++++++++++++++++-- .../src/controller/build/security.rs | 12 ++ .../src/controller/dereference.rs | 8 +- rust/operator-binary/src/crd/mod.rs | 10 +- rust/operator-binary/src/crd/security.rs | 28 ++++- rust/operator-binary/src/internal_secret.rs | 36 ++---- 13 files changed, 251 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9d5dfc8..9f2f9c82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ 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 ([#860]). - `envOverrides` names are now validated by the shared `EnvVarName` type rather than by operator-specific validation code ([#865]). +- Environment variable overrides (`envOverrides`) are now applied after all environment + variables set by the operator. In particular, `CONTAINERDEBUG_LOG_DIRECTORY` and the + authentication-related environment variables can now be overridden, whereas previously the + operator's values always took precedence ([#865]). - 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 diff --git a/Cargo.nix b/Cargo.nix index df86d404..e3dea6df 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -10674,6 +10674,11 @@ rec { name = "serde_yaml"; packageId = "serde_yaml"; } + { + name = "stackable-operator"; + packageId = "stackable-operator"; + features = [ "crds" "webhook" "test-support" ]; + } ]; }; @@ -10871,7 +10876,7 @@ rec { "time" = [ "stackable-shared/time" ]; "webhook" = [ "dep:stackable-webhook" ]; }; - resolvedDefaultFeatures = [ "crds" "default" "webhook" ]; + resolvedDefaultFeatures = [ "crds" "default" "test-support" "webhook" ]; }; "stackable-operator-derive" = rec { crateName = "stackable-operator-derive"; diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 225c5d44..ebd1b76a 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -34,3 +34,4 @@ built.workspace = true [dev-dependencies] rstest.workspace = true serde_yaml.workspace = true +stackable-operator = { workspace = true, features = ["test-support"] } diff --git a/rust/operator-binary/src/controller/build/authentication/mod.rs b/rust/operator-binary/src/controller/build/authentication/mod.rs index 0726bb07..d0c18ab9 100644 --- a/rust/operator-binary/src/controller/build/authentication/mod.rs +++ b/rust/operator-binary/src/controller/build/authentication/mod.rs @@ -10,22 +10,24 @@ use std::collections::BTreeMap; use snafu::Snafu; use stackable_operator::{ builder::pod::{PodBuilder, container::ContainerBuilder}, - k8s_openapi::api::core::v1::EnvVar, + v2::builder::pod::container::EnvVarSet, }; use crate::{ authentication::DruidAuthenticationConfig, controller::validate::ValidatedCluster, - crd::{DruidRole, env_var_reference, security::INTERNAL_INITIAL_CLIENT_PASSWORD_ENV}, - internal_secret::{build_shared_internal_secret_name, env_var_from_secret}, + crd::{ + DruidRole, env_var_reference, + security::{ + INTERNAL_INITIAL_CLIENT_PASSWORD_ENV, INTERNAL_INITIAL_CLIENT_PASSWORD_SECRET_KEY, + }, + }, + internal_secret::build_shared_internal_secret_name, }; pub mod ldap; pub mod oidc; -// It seems this needs to be the same password for Druid to work, so we re-use the existing env variable. -const ESCALATOR_INTERNAL_CLIENT_PASSWORD_ENV: &str = INTERNAL_INITIAL_CLIENT_PASSWORD_ENV; - // Authorizer/authenticator names and types used in the Druid runtime.properties auth config. // These are shared across the LDAP and OIDC providers (in the child modules). const DRUID_SYSTEM_AUTHORIZER: &str = "DruidSystemAuthorizer"; @@ -147,19 +149,18 @@ pub fn get_env_var_mounts( auth: &DruidAuthenticationConfig, cluster: &ValidatedCluster, role: &DruidRole, -) -> Vec { - let mut envs = vec![]; - let internal_secret_name = build_shared_internal_secret_name(cluster); - envs.push(env_var_from_secret( +) -> EnvVarSet { + let internal_secret_name = build_shared_internal_secret_name(&cluster.name); + let mut env_vars = EnvVarSet::new().with_secret_key_ref( + &INTERNAL_INITIAL_CLIENT_PASSWORD_ENV, &internal_secret_name, - None, - INTERNAL_INITIAL_CLIENT_PASSWORD_ENV, - )); + &INTERNAL_INITIAL_CLIENT_PASSWORD_SECRET_KEY, + ); if let DruidAuthenticationConfig::Oidc { oidc, .. } = auth { - envs.extend(oidc::get_env_var_mounts(role, oidc, &internal_secret_name)) + env_vars = env_vars.merge(oidc::get_env_var_mounts(role, oidc, &internal_secret_name)); } - envs + env_vars } pub fn add_volumes_and_mounts( @@ -196,7 +197,7 @@ fn add_druid_system_authenticator_config(config: &mut BTreeMap) config.insert( "druid.auth.authenticator.DruidSystemAuthenticator.initialInternalClientPassword" .to_string(), - env_var_reference(INTERNAL_INITIAL_CLIENT_PASSWORD_ENV), + env_var_reference(&*INTERNAL_INITIAL_CLIENT_PASSWORD_ENV), ); config.insert( "druid.auth.authenticator.DruidSystemAuthenticator.authorizerName".to_string(), @@ -221,7 +222,9 @@ fn add_escalator_config(config: &mut BTreeMap) { ); config.insert( "druid.escalator.internalClientPassword".to_string(), - env_var_reference(ESCALATOR_INTERNAL_CLIENT_PASSWORD_ENV), + // The escalator needs the same password for Druid to work, so the existing env + // variable is re-used. + env_var_reference(&*INTERNAL_INITIAL_CLIENT_PASSWORD_ENV), ); config.insert( "druid.escalator.authorizerName".to_string(), diff --git a/rust/operator-binary/src/controller/build/authentication/oidc.rs b/rust/operator-binary/src/controller/build/authentication/oidc.rs index 50c42d0c..c233abcd 100644 --- a/rust/operator-binary/src/controller/build/authentication/oidc.rs +++ b/rust/operator-binary/src/controller/build/authentication/oidc.rs @@ -4,17 +4,16 @@ use snafu::ResultExt; use stackable_operator::{ builder::pod::{PodBuilder, container::ContainerBuilder}, crd::authentication::oidc, - k8s_openapi::api::core::v1::EnvVar, + v2::{builder::pod::container::EnvVarSet, types::kubernetes::SecretName}, }; use super::{AddOidcVolumesSnafu, ConstructOidcWellKnownUrlSnafu, Error}; use crate::{ authentication::DruidClientAuthenticationOptions, crd::{ - COOKIE_PASSPHRASE_ENV, DruidRole, env_var_reference, + COOKIE_PASSPHRASE_ENV, COOKIE_PASSPHRASE_SECRET_KEY, DruidRole, env_var_reference, security::add_cert_to_jvm_trust_store_cmd, }, - internal_secret::env_var_from_secret, }; const OIDC_AUTHORIZER: &str = "OidcAuthorizer"; @@ -47,7 +46,7 @@ fn add_authenticator_config( ); config.insert( "druid.auth.pac4j.cookiePassphrase".to_string(), - env_var_reference(COOKIE_PASSPHRASE_ENV), + env_var_reference(&*COOKIE_PASSPHRASE_ENV), ); config.insert( "druid.auth.pac4j.oidc.clientID".to_string(), @@ -116,25 +115,28 @@ pub(super) fn main_container_commands( pub(super) fn get_env_var_mounts( role: &DruidRole, oidc: &DruidClientAuthenticationOptions, - internal_secret_name: &str, -) -> Vec { - let mut envs = vec![]; + internal_secret_name: &SecretName, +) -> EnvVarSet { + let mut env_vars = EnvVarSet::new(); match role { DruidRole::MiddleManager => (), _ => { - envs.extend( - oidc::v1alpha1::AuthenticationProvider::client_credentials_env_var_mounts( - oidc.client_credentials_secret_ref.to_owned(), - ), - ); - envs.push(env_var_from_secret( + for env_var in oidc::v1alpha1::AuthenticationProvider::client_credentials_env_var_mounts( + oidc.client_credentials_secret_ref.to_owned(), + ) { + env_vars = env_vars.with_env_var(env_var).expect( + "env_var name is valid because it is either OIDC_<16-hex-characters>_CLIENT_ID \ + or OIDC_<16-hex-characters>_CLIENT_SECRET", + ); + } + env_vars = env_vars.with_secret_key_ref( + &COOKIE_PASSPHRASE_ENV, internal_secret_name, - None, - COOKIE_PASSPHRASE_ENV, - )) + &COOKIE_PASSPHRASE_SECRET_KEY, + ); } } - envs + env_vars } pub(super) fn add_volumes_and_mounts( @@ -281,14 +283,18 @@ mod tests { assert!(config.contains_key("druid.auth.authorizers")); } + fn internal_secret_name() -> SecretName { + SecretName::from_str_unsafe("internal-secret") + } + /// The MiddleManager mounts no OIDC env vars (OIDC is not configured on it). #[test] fn middlemanager_gets_no_oidc_env_vars() { let oidc = test_options(); - let envs = get_env_var_mounts(&DruidRole::MiddleManager, &oidc, "internal-secret"); + let envs = get_env_var_mounts(&DruidRole::MiddleManager, &oidc, &internal_secret_name()); - assert!(envs.is_empty()); + assert!(envs.iter().next().is_none()); } /// Non-MiddleManager roles mount the OIDC credentials and the cookie-passphrase env var. @@ -296,11 +302,10 @@ mod tests { fn non_middlemanager_gets_oidc_env_vars() { let oidc = test_options(); - let envs = get_env_var_mounts(&DruidRole::Broker, &oidc, "internal-secret"); + let envs = get_env_var_mounts(&DruidRole::Broker, &oidc, &internal_secret_name()); assert!( - envs.iter() - .any(|e| e.name.as_str() == COOKIE_PASSPHRASE_ENV), + envs.get(&COOKIE_PASSPHRASE_ENV).is_some(), "expected the cookie passphrase env var to be mounted" ); } diff --git a/rust/operator-binary/src/controller/build/mod.rs b/rust/operator-binary/src/controller/build/mod.rs index c344e70b..b93ed917 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -14,7 +14,10 @@ use stackable_operator::{ v2::{ builder::meta::ownerreference_from_resource, kvp::label, - types::operator::{RoleGroupName, RoleName}, + types::{ + kubernetes::SecretKey, + operator::{RoleGroupName, RoleName}, + }, }, }; @@ -32,7 +35,7 @@ use crate::{ }, validate::ValidatedCluster, }, - crd::{COOKIE_PASSPHRASE_ENV, security::INTERNAL_INITIAL_CLIENT_PASSWORD_ENV}, + crd::{COOKIE_PASSPHRASE_SECRET_KEY, security::INTERNAL_INITIAL_CLIENT_PASSWORD_SECRET_KEY}, internal_secret::build_shared_internal_secret_name, }; @@ -250,9 +253,9 @@ fn build_internal_secret(cluster: &ValidatedCluster) -> Secret { .unwrap_or_default() .into_keys() .collect(); - if let Some(missing_key) = INTERNAL_SECRET_KEYS - .iter() - .find(|key| !current_keys.contains(**key)) + if let Some(missing_key) = internal_secret_keys() + .into_iter() + .find(|key| !current_keys.contains(key.as_ref())) { let secret = build_shared_internal_secret(cluster); tracing::warn!( @@ -272,11 +275,15 @@ fn build_internal_secret(cluster: &ValidatedCluster) -> Secret { /// The keys the shared internal Secret must contain. Single source for both /// [`build_shared_internal_secret`] and the missing-key check in [`build_internal_secret`]. -const INTERNAL_SECRET_KEYS: [&str; 2] = - [INTERNAL_INITIAL_CLIENT_PASSWORD_ENV, COOKIE_PASSPHRASE_ENV]; +fn internal_secret_keys() -> [&'static SecretKey; 2] { + [ + &INTERNAL_INITIAL_CLIENT_PASSWORD_SECRET_KEY, + &COOKIE_PASSPHRASE_SECRET_KEY, + ] +} fn build_shared_internal_secret(cluster: &ValidatedCluster) -> Secret { - let internal_secret: BTreeMap = INTERNAL_SECRET_KEYS + let internal_secret: BTreeMap = internal_secret_keys() .iter() .map(|key| (key.to_string(), get_random_base64())) .collect(); @@ -314,7 +321,7 @@ fn internal_secret_meta(cluster: &ValidatedCluster) -> ObjectMetaBuilder { // group, so it carries the cluster-resource labels (like the RBAC resources). object_meta( cluster, - build_shared_internal_secret_name(cluster), + build_shared_internal_secret_name(&cluster.name).to_string(), recommended_labels_for_cluster_resources(cluster), ) } @@ -338,7 +345,7 @@ mod tests { kube::{Resource, api::ObjectMeta}, }; - use super::{INTERNAL_SECRET_KEYS, KubernetesResources, Prepared, build}; + use super::{KubernetesResources, Prepared, SecretKey, build, internal_secret_keys}; use crate::{ controller::validate::test_support::{ MINIMAL_DRUID_YAML, druid_from_yaml, validated_cluster, @@ -483,7 +490,7 @@ mod tests { /// An existing shared internal Secret carrying the given keys in `data`, shaped as the /// dereference step fetches it from the cluster. - fn internal_secret_with_keys(keys: &[&str]) -> Secret { + fn internal_secret_with_keys(keys: &[&SecretKey]) -> Secret { Secret { data: Some( keys.iter() @@ -511,9 +518,9 @@ mod tests { .string_data .as_ref() .expect("the built secret carries generated contents"); - for key in INTERNAL_SECRET_KEYS { + for key in internal_secret_keys() { assert!( - data.contains_key(key), + data.contains_key(key.as_ref()), "generated secret must contain {key}" ); } @@ -524,7 +531,7 @@ mod tests { fn build_replaces_the_internal_secret_when_a_required_key_is_missing() { let druid = druid_from_yaml(MINIMAL_DRUID_YAML); let mut cluster = validated_cluster(&druid); - cluster.internal_secret = Some(internal_secret_with_keys(&INTERNAL_SECRET_KEYS[..1])); + cluster.internal_secret = Some(internal_secret_with_keys(&internal_secret_keys()[..1])); let resources = build(&cluster).expect("build succeeds"); @@ -533,8 +540,11 @@ mod tests { .string_data .as_ref() .expect("the replacement carries generated contents"); - for key in INTERNAL_SECRET_KEYS { - assert!(data.contains_key(key), "replacement must contain {key}"); + for key in internal_secret_keys() { + assert!( + data.contains_key(key.as_ref()), + "replacement must contain {key}" + ); } } @@ -545,7 +555,7 @@ mod tests { fn reemits_existing_internal_secret_when_complete() { let druid = druid_from_yaml(MINIMAL_DRUID_YAML); let mut cluster = validated_cluster(&druid); - cluster.internal_secret = Some(internal_secret_with_keys(&INTERNAL_SECRET_KEYS)); + cluster.internal_secret = Some(internal_secret_with_keys(&internal_secret_keys())); let resources = build(&cluster).expect("build succeeds"); @@ -556,7 +566,7 @@ mod tests { ); assert_eq!( secret.data, - internal_secret_with_keys(&INTERNAL_SECRET_KEYS).data, + internal_secret_with_keys(&internal_secret_keys()).data, "the fetched values must be carried over unchanged" ); assert!( diff --git a/rust/operator-binary/src/controller/build/resource/listener.rs b/rust/operator-binary/src/controller/build/resource/listener.rs index 3ca8bf3b..969dcd4b 100644 --- a/rust/operator-binary/src/controller/build/resource/listener.rs +++ b/rust/operator-binary/src/controller/build/resource/listener.rs @@ -143,6 +143,12 @@ mod tests { validated_cluster(&druid_from_yaml(MINIMAL_DRUID_YAML)) } + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *LISTENER_VOLUME_NAME; + } + #[test] fn group_listener_name_only_for_externally_reachable_roles() { let cluster_name = cluster().name; diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index fb6307dd..4adca08d 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -22,7 +22,7 @@ use stackable_operator::{ }, product_logging, v2::{ - builder::pod::container::{EnvVarSet, new_container_builder}, + builder::pod::container::{EnvVarName, EnvVarSet, new_container_builder}, product_logging::framework::{ STACKABLE_LOG_DIR, ValidatedContainerLogConfigChoice, vector_container, }, @@ -66,6 +66,9 @@ stackable_operator::constant!(LOG_CONFIG_VOLUME_NAME: VolumeName = "log-config") stackable_operator::constant!(LOG_VOLUME_NAME: VolumeName = "log"); stackable_operator::constant!(RW_CONFIG_VOLUME_NAME: VolumeName = "rwconfig"); +// Needed for the `containerdebug` process to log its tracing information to. +stackable_operator::constant!(CONTAINERDEBUG_LOG_DIRECTORY: EnvVarName = "CONTAINERDEBUG_LOG_DIRECTORY"); + // volume mount directory (not a volume name) const USERDATA_MOUNTPOINT: &str = "/stackable/userdata"; @@ -230,25 +233,37 @@ pub fn build_rolegroup_statefulset( .build(), ); - metadata_database_connection_details.add_to_container(&mut cb_druid); + // All operator-set environment variables of the druid container, collected into an + // `EnvVarSet` so that every name occurs only once. + let mut env_vars = EnvVarSet::new(); - // rest of env: the validated env overrides, rendered in sorted-by-name order. - let mut rest_env: Vec = rg.env_overrides.clone().into(); + for env_var in metadata_database_connection_details + .username_env + .iter() + .chain(metadata_database_connection_details.password_env.iter()) + { + env_vars = env_vars.with_env_var(env_var.clone()).expect( + "the database credential env var names are generated by operator-rs from the \ + unique database name and are therefore valid", + ); + } if let Some(auth_config) = druid_auth_config { - rest_env.extend(authentication::get_env_var_mounts( + env_vars = env_vars.merge(authentication::get_env_var_mounts( auth_config, cluster, role, - )) + )); } - // Needed for the `containerdebug` process to log it's tracing information to. - rest_env.push(EnvVar { - name: "CONTAINERDEBUG_LOG_DIRECTORY".to_string(), - value: Some(format!("{STACKABLE_LOG_DIR}/containerdebug")), - value_from: None, - }); + env_vars = env_vars.with_value( + &CONTAINERDEBUG_LOG_DIRECTORY, + format!("{STACKABLE_LOG_DIR}/containerdebug"), + ); + + // Environment variable overrides (highest precedence), merged from role and role group. + // They are merged in last so that they override any operator-set environment variable. + let env_vars = env_vars.merge(rg.env_overrides.clone()); main_container_commands.push(role.main_container_start_command()); cb_druid @@ -261,7 +276,7 @@ pub fn build_rolegroup_statefulset( "-c".to_string(), ]) .args(vec![main_container_commands.join("\n")]) - .add_env_vars(rest_env) + .add_env_vars(Vec::::from(env_vars)) .add_container_ports(container_ports(druid_tls_security, role)) .add_container_port(METRICS_PORT_NAME, METRICS_PORT.into()) // 10s * 30 = 300s to come up @@ -483,3 +498,73 @@ fn add_log_volume_and_volume_mounts( Ok(()) } + +#[cfg(test)] +mod tests { + use stackable_operator::v2::types::operator::RoleGroupName; + + use super::*; + use crate::controller::validate::test_support::{ + MINIMAL_DRUID_YAML, druid_from_yaml, validated_cluster, + }; + + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *DRUID_CONFIG_VOLUME_NAME; + let _ = *HDFS_CONFIG_VOLUME_NAME; + let _ = *LOG_CONFIG_VOLUME_NAME; + let _ = *LOG_VOLUME_NAME; + let _ = *RW_CONFIG_VOLUME_NAME; + let _ = *CONTAINERDEBUG_LOG_DIRECTORY; + } + + /// The user-supplied `envOverrides` must be merged in after all operator-set environment + /// variables, so that they can override any of them. `CONTAINERDEBUG_LOG_DIRECTORY` is used + /// as the example here because it is set unconditionally by the operator. + #[test] + fn env_overrides_override_operator_set_env_vars() { + let druid = druid_from_yaml(MINIMAL_DRUID_YAML); + let cluster = validated_cluster(&druid); + let role_group_name = RoleGroupName::from_str("default").expect("valid role group name"); + let mut rg = cluster + .role_group_configs + .get(&DruidRole::Broker) + .expect("broker role groups") + .get(&role_group_name) + .expect("default role group") + .clone(); + rg.env_overrides = EnvVarSet::new().with_value( + &EnvVarName::from_str("CONTAINERDEBUG_LOG_DIRECTORY").expect("valid env var name"), + "/custom/log/dir", + ); + + let stateful_set = + build_rolegroup_statefulset(&cluster, &DruidRole::Broker, &role_group_name, &rg) + .expect("the StatefulSet builds"); + + let env = stateful_set + .spec + .expect("the StatefulSet has a spec") + .template + .spec + .expect("the pod template has a spec") + .containers + .into_iter() + .find(|container| container.name == "druid") + .expect("the druid container exists") + .env + .expect("the druid container has env vars"); + + let containerdebug: Vec<_> = env + .iter() + .filter(|env_var| env_var.name == "CONTAINERDEBUG_LOG_DIRECTORY") + .collect(); + assert_eq!( + containerdebug.len(), + 1, + "the override must replace the operator-set value, not duplicate it" + ); + assert_eq!(containerdebug[0].value.as_deref(), Some("/custom/log/dir")); + } +} diff --git a/rust/operator-binary/src/controller/build/security.rs b/rust/operator-binary/src/controller/build/security.rs index 5b27a7ef..61b13505 100644 --- a/rust/operator-binary/src/controller/build/security.rs +++ b/rust/operator-binary/src/controller/build/security.rs @@ -400,3 +400,15 @@ pub fn get_tcp_socket_probe( ..Default::default() } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *TLS_VOLUME_NAME; + let _ = *TLS_MOUNT_VOLUME_NAME; + } +} diff --git a/rust/operator-binary/src/controller/dereference.rs b/rust/operator-binary/src/controller/dereference.rs index 5db50896..447ad4f3 100644 --- a/rust/operator-binary/src/controller/dereference.rs +++ b/rust/operator-binary/src/controller/dereference.rs @@ -218,11 +218,13 @@ pub async fn dereference( listener_name: listener_name.as_ref(), })?; - let secret_name = build_shared_internal_secret_name(druid); + let secret_name = build_shared_internal_secret_name(&cluster_name); let internal_secret = client - .get_opt::(&secret_name, namespace) + .get_opt::(secret_name.as_ref(), namespace) .await - .context(GetInternalSecretSnafu { secret_name })?; + .context(GetInternalSecretSnafu { + secret_name: secret_name.as_ref(), + })?; // The discovery ConfigMap is named after the cluster itself. let discovery_config_map = client diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 3cc04cd5..2d0bdd34 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -38,6 +38,7 @@ use stackable_operator::{ status::condition::{ClusterCondition, HasStatusCondition}, utils::{COMMON_BASH_TRAP_FUNCTIONS, crds::raw_object_list_schema}, v2::{ + builder::pod::container::EnvVarName, config_overrides::KeyValueConfigOverrides, product_logging::framework::{ STACKABLE_LOG_DIR, ValidatedContainerLogConfigChoice, VectorContainerLogConfig, @@ -46,7 +47,7 @@ use stackable_operator::{ role_utils::{JavaCommonConfig, Role, RoleGroupConfig, with_validated_config}, types::{ common::Port, - kubernetes::{ConfigMapName, ContainerName, ListenerClassName}, + kubernetes::{ConfigMapName, ContainerName, ListenerClassName, SecretKey}, operator::{RoleGroupName, RoleName}, }, }, @@ -97,7 +98,10 @@ pub const PROP_SEGMENT_CACHE_LOCATIONS: &str = "druid.segmentCache.locations"; pub const METRICS_PORT_NAME: &str = "metrics"; pub const METRICS_PORT: Port = Port(9090); -pub const COOKIE_PASSPHRASE_ENV: &str = "OIDC_COOKIE_PASSPHRASE"; +// The env var that carries the OIDC cookie passphrase, and the key of the shared internal +// Secret it is mounted from (the same string, as the env var name is used as the Secret key). +constant!(pub COOKIE_PASSPHRASE_ENV: EnvVarName = "OIDC_COOKIE_PASSPHRASE"); +constant!(pub COOKIE_PASSPHRASE_SECRET_KEY: SecretKey = "OIDC_COOKIE_PASSPHRASE"); /// Formats a Druid [dynamic config](https://druid.apache.org/docs/latest/operations/dynamic-config-provider) /// reference to an environment variable, i.e. `${env:NAME}`. @@ -911,6 +915,8 @@ mod tests { let _ = *HISTORICAL_ROLE_NAME; let _ = *MIDDLE_MANAGER_ROLE_NAME; let _ = *ROUTER_ROLE_NAME; + let _ = *COOKIE_PASSPHRASE_ENV; + let _ = *COOKIE_PASSPHRASE_SECRET_KEY; } impl RoundtripTestData for v1alpha1::DruidClusterSpec { diff --git a/rust/operator-binary/src/crd/security.rs b/rust/operator-binary/src/crd/security.rs index a10dafbe..95eb75b8 100644 --- a/rust/operator-binary/src/crd/security.rs +++ b/rust/operator-binary/src/crd/security.rs @@ -1,4 +1,12 @@ -use stackable_operator::v2::types::kubernetes::SecretClassName; +use std::str::FromStr; + +use stackable_operator::{ + constant, + v2::{ + builder::pod::container::EnvVarName, + types::kubernetes::{SecretClassName, SecretKey}, + }, +}; use crate::crd::{ STACKABLE_TRUST_STORE_PASSWORD, TRUST_STORE_FILE, @@ -22,7 +30,11 @@ pub const TLS_PORT_NAME: &str = "https"; // Misc TLS (shared with the build-side renderer and the LDAP authentication module) pub const STACKABLE_TLS_DIR: &str = "/stackable/tls"; -pub const INTERNAL_INITIAL_CLIENT_PASSWORD_ENV: &str = "INTERNAL_INITIAL_CLIENT_PASSWORD"; +// The env var that carries the internal initial client password, and the key of the shared +// internal Secret it is mounted from (the same string, as the env var name is used as the +// Secret key). +constant!(pub INTERNAL_INITIAL_CLIENT_PASSWORD_ENV: EnvVarName = "INTERNAL_INITIAL_CLIENT_PASSWORD"); +constant!(pub INTERNAL_INITIAL_CLIENT_PASSWORD_SECRET_KEY: SecretKey = "INTERNAL_INITIAL_CLIENT_PASSWORD"); impl DruidTlsSecurity { #[cfg(test)] @@ -93,3 +105,15 @@ pub fn add_cert_to_trust_store_cmd( pub fn add_cert_to_jvm_trust_store_cmd(cert_file: &str) -> Vec { add_cert_to_trust_store_cmd(cert_file, "/stackable", STACKABLE_TRUST_STORE_PASSWORD) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *INTERNAL_INITIAL_CLIENT_PASSWORD_ENV; + let _ = *INTERNAL_INITIAL_CLIENT_PASSWORD_SECRET_KEY; + } +} diff --git a/rust/operator-binary/src/internal_secret.rs b/rust/operator-binary/src/internal_secret.rs index 81369586..eaeac691 100644 --- a/rust/operator-binary/src/internal_secret.rs +++ b/rust/operator-binary/src/internal_secret.rs @@ -1,30 +1,14 @@ -//! Pure helpers around the shared internal Secret: its name and the env vars that reference -//! it. The Secret itself is produced by `build_internal_secret` in the build step on every -//! reconcile run and applied in the apply step. +//! Pure helper around the shared internal Secret: its name. The Secret itself is produced by +//! `build_internal_secret` in the build step on every reconcile run and applied in the apply +//! step. -use stackable_operator::{ - k8s_openapi::api::core::v1::{EnvVar, EnvVarSource, SecretKeySelector}, - kube::ResourceExt, -}; +use std::str::FromStr; -pub fn build_shared_internal_secret_name(owner: &T) -> String { - format!("{}-shared-internal-secret", owner.name_any()) -} +use stackable_operator::v2::types::{kubernetes::SecretName, operator::ClusterName}; -/// Give a secret name and an optional key in the secret to use. -/// The value from the key will be set into the given env var name. -/// If not secret key is given, the env var name will be used as the secret key. -pub fn env_var_from_secret(secret_name: &str, secret_key: Option<&str>, env_var: &str) -> EnvVar { - EnvVar { - name: env_var.to_string(), - value_from: Some(EnvVarSource { - secret_key_ref: Some(SecretKeySelector { - optional: Some(false), - name: secret_name.to_string(), - key: secret_key.unwrap_or(env_var).to_string(), - }), - ..EnvVarSource::default() - }), - ..EnvVar::default() - } +pub fn build_shared_internal_secret_name(cluster_name: &ClusterName) -> SecretName { + SecretName::from_str(&format!("{cluster_name}-shared-internal-secret")).expect( + "the shared internal secret name is a valid Secret name, because a ClusterName is at \ + most 40 characters long, so the suffixed name stays within the length limit", + ) }