diff --git a/CHANGELOG.md b/CHANGELOG.md index e4839503..b90627c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ - Environment variable overrides (`envOverrides`) are now applied after all environment variables set by the operator. In particular, `CONTAINERDEBUG_LOG_DIRECTORY` can now be overridden, whereas previously the operator's value always took precedence ([#838]). -- Make operations infallible where appropriate ([#852]). +- Make operations infallible where appropriate ([#852], [#860]). ### Fixed @@ -60,6 +60,7 @@ [#847]: https://github.com/stackabletech/airflow-operator/pull/847 [#849]: https://github.com/stackabletech/airflow-operator/pull/849 [#852]: https://github.com/stackabletech/airflow-operator/pull/852 +[#860]: https://github.com/stackabletech/airflow-operator/pull/860 ## [26.7.0] - 2026-07-21 diff --git a/rust/operator-binary/src/controller/build/resource/executor.rs b/rust/operator-binary/src/controller/build/resource/executor.rs index e2844c9e..1c062434 100644 --- a/rust/operator-binary/src/controller/build/resource/executor.rs +++ b/rust/operator-binary/src/controller/build/resource/executor.rs @@ -108,7 +108,7 @@ pub fn build_executor_template_config_map( // N.B. this "base" name is an airflow requirement and should not be changed! // See https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.4.0/kubernetes_executor.html#base-image - let mut airflow_container = new_container_builder(&Container::Base.to_container_name()); + let mut airflow_container = new_container_builder(Container::Base.name()); airflow_container .image_from_product_image(resolved_product_image) diff --git a/rust/operator-binary/src/controller/build/resource/pod.rs b/rust/operator-binary/src/controller/build/resource/pod.rs index 7a7930b7..87201892 100644 --- a/rust/operator-binary/src/controller/build/resource/pod.rs +++ b/rust/operator-binary/src/controller/build/resource/pod.rs @@ -2,27 +2,28 @@ //! and the Kubernetes-executor pod template): authentication volumes, git-sync resources and the //! Vector log-collection sidecar. -use std::{collections::BTreeSet, str::FromStr}; +use std::collections::BTreeSet; use snafu::{ResultExt, Snafu}; use stackable_operator::{ builder::pod::{PodBuilder, container::ContainerBuilder}, commons::product_image_selection::ResolvedProductImage, - constant, crd::{authentication::ldap, git_sync}, k8s_openapi::api::core::v1::Container as K8sContainer, v2::{ builder::pod::container::EnvVarSet, product_logging::framework::{VectorContainerLogConfig, vector_container}, role_group_utils::ResourceNames, - types::kubernetes::ContainerName, }, }; use crate::{ controller::build::volumes::{CONFIG_VOLUME_NAME, LOG_VOLUME_NAME}, - crd::authentication::{ - AirflowAuthenticationClassResolved, AirflowClientAuthenticationDetailsResolved, + crd::{ + Container, + authentication::{ + AirflowAuthenticationClassResolved, AirflowClientAuthenticationDetailsResolved, + }, }, }; @@ -130,8 +131,6 @@ pub(crate) fn add_git_sync_resources( Ok(()) } -constant!(VECTOR_CONTAINER_NAME: ContainerName = "vector"); - /// Builds the Vector log-collection sidecar container from the up-front-validated logging config. pub(crate) fn build_logging_container( resolved_product_image: &ResolvedProductImage, @@ -139,7 +138,7 @@ pub(crate) fn build_logging_container( resource_names: &ResourceNames, ) -> K8sContainer { vector_container( - &VECTOR_CONTAINER_NAME, + Container::Vector.name(), resolved_product_image, vector_log_config, resource_names, @@ -148,14 +147,3 @@ pub(crate) fn build_logging_container( EnvVarSet::new(), ) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_constants() { - // Test that dereferencing the constants does not panic. - let _ = *VECTOR_CONTAINER_NAME; - } -} diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index 6f646f1d..9e7f4488 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -157,7 +157,7 @@ pub fn build_server_rolegroup_statefulset( .build(), ); - let mut airflow_container = new_container_builder(&Container::Airflow.to_container_name()); + let mut airflow_container = new_container_builder(Container::Airflow.name()); add_graceful_shutdown_config(merged_airflow_config.graceful_shutdown_timeout, &mut pb) .context(GracefulShutdownSnafu)?; diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 5cecd0b3..3e0216fd 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -96,6 +96,8 @@ pub const HTTP_PORT_NAME: &str = "http"; pub const HTTP_PORT: Port = Port(8080); pub const METRICS_PORT_NAME: &str = "metrics"; pub const METRICS_PORT: Port = Port(9102); +// The metrics container has no logging configuration, so it is not a `Container` variant and +// carries its name directly. constant!(pub METRICS_CONTAINER_NAME: ContainerName = "metrics"); const DEFAULT_AIRFLOW_GRACEFUL_SHUTDOWN_TIMEOUT: Duration = Duration::from_minutes_unchecked(2); @@ -887,11 +889,22 @@ pub enum Container { GitSync, } +// Typed container names. They must match the strum `Display` (kebab-case) of the variants above, +// which is pinned by a unit test. +constant!(AIRFLOW_CONTAINER_NAME: ContainerName = "airflow"); +constant!(VECTOR_CONTAINER_NAME: ContainerName = "vector"); +constant!(BASE_CONTAINER_NAME: ContainerName = "base"); +constant!(GIT_SYNC_CONTAINER_NAME: ContainerName = "git-sync"); + impl Container { - /// The type-safe container name for this variant (matching its kebab-case serialization). - pub fn to_container_name(&self) -> ContainerName { - ContainerName::from_str(&self.to_string()) - .expect("a Container variant name is a valid container name") + /// The typed container name of this variant. + pub fn name(&self) -> &'static ContainerName { + match self { + Container::Airflow => &AIRFLOW_CONTAINER_NAME, + Container::Vector => &VECTOR_CONTAINER_NAME, + Container::Base => &BASE_CONTAINER_NAME, + Container::GitSync => &GIT_SYNC_CONTAINER_NAME, + } } } @@ -1057,6 +1070,19 @@ mod tests { let _ = *TEMPLATE_VOLUME_NAME; let _ = *LISTENER_PVC_NAME; let _ = *METRICS_CONTAINER_NAME; + let _ = *AIRFLOW_CONTAINER_NAME; + let _ = *VECTOR_CONTAINER_NAME; + let _ = *BASE_CONTAINER_NAME; + let _ = *GIT_SYNC_CONTAINER_NAME; + } + + /// The typed container names returned by `name` must agree with the strum `Display` + /// of `Container`, which the logging configuration still uses as the per-container key. + #[test] + fn container_names_match_display() { + for container in Container::iter() { + assert_eq!(container.name().to_string(), container.to_string()); + } } #[test]