Skip to content

Commit 58c9d03

Browse files
adwk67claude
andcommitted
refactor: move rolegroup ConfigMap build into controller/build/config_map
Extracts build_rolegroup_config_map out of airflow_controller into a dedicated controller/build/config_map module with its own error enum, matching the controller/build/config_map.rs layout in hdfs- and trino-operator. The controller now wraps it via a single BuildConfigMap error variant; the ConfigMap-only error variants move into the new module. No behaviour change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 0fed7d5 commit 58c9d03

4 files changed

Lines changed: 135 additions & 94 deletions

File tree

rust/operator-binary/src/airflow_controller.rs

Lines changed: 16 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,7 @@ use stackable_operator::{
5555
},
5656
kvp::{Annotation, Label, LabelError, Labels, ObjectLabels},
5757
logging::controller::ReconcilerError,
58-
product_logging::{
59-
self,
60-
framework::LoggingError,
61-
spec::{ContainerLogConfig, Logging},
62-
},
58+
product_logging::{self, framework::LoggingError, spec::ContainerLogConfig},
6359
role_utils::RoleGroupRef,
6460
shared::time::Duration,
6561
status::condition::{
@@ -71,14 +67,14 @@ use stackable_operator::{
7167
use strum::{EnumDiscriminants, IntoStaticStr};
7268

7369
use crate::{
74-
config,
70+
controller::build::config_map,
7571
controller_commons::{self, CONFIG_VOLUME_NAME, LOG_CONFIG_VOLUME_NAME, LOG_VOLUME_NAME},
7672
crd::{
77-
self, AIRFLOW_CONFIG_FILENAME, APP_NAME, AirflowClusterStatus, AirflowConfig,
78-
AirflowExecutor, AirflowExecutorCommonConfiguration, AirflowRole, CONFIG_PATH, Container,
79-
ExecutorConfig, HTTP_PORT, HTTP_PORT_NAME, LISTENER_VOLUME_DIR, LISTENER_VOLUME_NAME,
80-
LOG_CONFIG_DIR, METRICS_PORT, METRICS_PORT_NAME, OPERATOR_NAME, STACKABLE_LOG_DIR,
81-
TEMPLATE_LOCATION, TEMPLATE_NAME, TEMPLATE_VOLUME_NAME,
73+
self, APP_NAME, AirflowClusterStatus, AirflowConfig, AirflowExecutor,
74+
AirflowExecutorCommonConfiguration, AirflowRole, CONFIG_PATH, Container, ExecutorConfig,
75+
HTTP_PORT, HTTP_PORT_NAME, LISTENER_VOLUME_DIR, LISTENER_VOLUME_NAME, LOG_CONFIG_DIR,
76+
METRICS_PORT, METRICS_PORT_NAME, OPERATOR_NAME, STACKABLE_LOG_DIR, TEMPLATE_LOCATION,
77+
TEMPLATE_NAME, TEMPLATE_VOLUME_NAME,
8278
authentication::{
8379
AirflowAuthenticationClassResolved, AirflowClientAuthenticationDetailsResolved,
8480
},
@@ -96,7 +92,6 @@ use crate::{
9692
},
9793
pdb::add_pdbs,
9894
},
99-
product_logging::extend_config_map_with_log_config,
10095
service::{
10196
build_rolegroup_headless_service, build_rolegroup_metrics_service,
10297
stateful_set_service_name,
@@ -157,16 +152,9 @@ pub enum Error {
157152
source: stackable_operator::commons::rbac::Error,
158153
},
159154

160-
#[snafu(display("failed to build webserver config for {rolegroup}"))]
161-
BuildWebserverConfig {
162-
source: config::webserver_config::Error,
163-
rolegroup: RoleGroupRef<v1alpha2::AirflowCluster>,
164-
},
165-
166-
#[snafu(display("failed to build ConfigMap for {rolegroup}"))]
167-
BuildRoleGroupConfig {
168-
source: stackable_operator::builder::configmap::Error,
169-
rolegroup: RoleGroupRef<v1alpha2::AirflowCluster>,
155+
#[snafu(display("failed to build rolegroup ConfigMap"))]
156+
BuildConfigMap {
157+
source: crate::controller::build::config_map::Error,
170158
},
171159

172160
#[snafu(display("failed to resolve and merge config for role and role group"))]
@@ -193,12 +181,6 @@ pub enum Error {
193181
#[snafu(display("vector agent is enabled but vector aggregator ConfigMap is missing"))]
194182
VectorAggregatorConfigMapMissing,
195183

196-
#[snafu(display("failed to add the logging configuration to the ConfigMap [{cm_name}]"))]
197-
InvalidLoggingConfig {
198-
source: crate::product_logging::Error,
199-
cm_name: String,
200-
},
201-
202184
#[snafu(display("failed to update status"))]
203185
ApplyStatus {
204186
source: stackable_operator::client::Error,
@@ -558,7 +540,7 @@ pub async fn reconcile_airflow(
558540
rolegroup: rolegroup.clone(),
559541
})?;
560542

561-
let rg_configmap = build_rolegroup_config_map(
543+
let rg_configmap = config_map::build_rolegroup_config_map(
562544
airflow,
563545
&validated.image,
564546
&rolegroup,
@@ -567,7 +549,8 @@ pub async fn reconcile_airflow(
567549
&validated.authorization_config,
568550
&validated_rg_config.merged_config.logging,
569551
&Container::Airflow,
570-
)?;
552+
)
553+
.context(BuildConfigMapSnafu)?;
571554
cluster_resources
572555
.add(client, rg_configmap)
573556
.await
@@ -643,7 +626,7 @@ async fn build_executor_template(
643626
role_group: "kubernetes".into(),
644627
};
645628

646-
let rg_configmap = build_rolegroup_config_map(
629+
let rg_configmap = config_map::build_rolegroup_config_map(
647630
airflow,
648631
resolved_product_image,
649632
&rolegroup,
@@ -652,7 +635,8 @@ async fn build_executor_template(
652635
authorization_config,
653636
&merged_executor_config.logging,
654637
&Container::Base,
655-
)?;
638+
)
639+
.context(BuildConfigMapSnafu)?;
656640
cluster_resources
657641
.add(client, rg_configmap)
658642
.await
@@ -699,68 +683,6 @@ async fn build_executor_template(
699683
Ok(())
700684
}
701685

702-
/// The rolegroup [`ConfigMap`] configures the rolegroup based on the configuration given by the administrator
703-
#[allow(clippy::too_many_arguments)]
704-
fn build_rolegroup_config_map(
705-
airflow: &v1alpha2::AirflowCluster,
706-
resolved_product_image: &ResolvedProductImage,
707-
rolegroup: &RoleGroupRef<v1alpha2::AirflowCluster>,
708-
config_file_overrides: &BTreeMap<String, String>,
709-
authentication_config: &AirflowClientAuthenticationDetailsResolved,
710-
authorization_config: &AirflowAuthorizationResolved,
711-
logging: &Logging<Container>,
712-
container: &Container,
713-
) -> Result<ConfigMap, Error> {
714-
let config_file = config::webserver_config::build(
715-
authentication_config,
716-
authorization_config,
717-
&resolved_product_image.product_version,
718-
config_file_overrides,
719-
)
720-
.with_context(|_| BuildWebserverConfigSnafu {
721-
rolegroup: rolegroup.clone(),
722-
})?;
723-
724-
let mut cm_builder = ConfigMapBuilder::new();
725-
726-
cm_builder
727-
.metadata(
728-
ObjectMetaBuilder::new()
729-
.name_and_namespace(airflow)
730-
.name(rolegroup.object_name())
731-
.ownerreference_from_resource(airflow, None, Some(true))
732-
.context(ObjectMissingMetadataForOwnerRefSnafu)?
733-
.with_recommended_labels(&build_recommended_labels(
734-
airflow,
735-
AIRFLOW_CONTROLLER_NAME,
736-
&resolved_product_image.app_version_label_value,
737-
&rolegroup.role,
738-
&rolegroup.role_group,
739-
))
740-
.context(ObjectMetaSnafu)?
741-
.build(),
742-
)
743-
.add_data(AIRFLOW_CONFIG_FILENAME, config_file);
744-
745-
extend_config_map_with_log_config(
746-
rolegroup,
747-
logging,
748-
container,
749-
&Container::Vector,
750-
&mut cm_builder,
751-
resolved_product_image,
752-
)
753-
.context(InvalidLoggingConfigSnafu {
754-
cm_name: rolegroup.object_name(),
755-
})?;
756-
757-
cm_builder
758-
.build()
759-
.with_context(|_| BuildRoleGroupConfigSnafu {
760-
rolegroup: rolegroup.clone(),
761-
})
762-
}
763-
764686
fn build_rolegroup_metadata(
765687
airflow: &v1alpha2::AirflowCluster,
766688
resolved_product_image: &&ResolvedProductImage,
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//! Builds the rolegroup [`ConfigMap`]: the rendered `webserver_config.py` plus the
2+
//! logging/vector configuration.
3+
4+
use std::collections::BTreeMap;
5+
6+
use snafu::{ResultExt, Snafu};
7+
use stackable_operator::{
8+
builder::{configmap::ConfigMapBuilder, meta::ObjectMetaBuilder},
9+
commons::product_image_selection::ResolvedProductImage,
10+
k8s_openapi::api::core::v1::ConfigMap,
11+
product_logging::spec::Logging,
12+
role_utils::RoleGroupRef,
13+
};
14+
15+
use crate::{
16+
airflow_controller::AIRFLOW_CONTROLLER_NAME,
17+
config::webserver_config,
18+
crd::{
19+
AIRFLOW_CONFIG_FILENAME, Container,
20+
authentication::AirflowClientAuthenticationDetailsResolved,
21+
authorization::AirflowAuthorizationResolved, build_recommended_labels, v1alpha2,
22+
},
23+
product_logging::extend_config_map_with_log_config,
24+
};
25+
26+
#[derive(Snafu, Debug)]
27+
pub enum Error {
28+
#[snafu(display("failed to build webserver config for {rolegroup}"))]
29+
BuildWebserverConfig {
30+
source: webserver_config::Error,
31+
rolegroup: RoleGroupRef<v1alpha2::AirflowCluster>,
32+
},
33+
34+
#[snafu(display("object is missing metadata to build owner reference"))]
35+
ObjectMissingMetadataForOwnerRef {
36+
source: stackable_operator::builder::meta::Error,
37+
},
38+
39+
#[snafu(display("failed to build object meta"))]
40+
ObjectMeta {
41+
source: stackable_operator::builder::meta::Error,
42+
},
43+
44+
#[snafu(display("failed to add the logging configuration to the ConfigMap [{cm_name}]"))]
45+
InvalidLoggingConfig {
46+
source: crate::product_logging::Error,
47+
cm_name: String,
48+
},
49+
50+
#[snafu(display("failed to build ConfigMap for {rolegroup}"))]
51+
BuildConfigMap {
52+
source: stackable_operator::builder::configmap::Error,
53+
rolegroup: RoleGroupRef<v1alpha2::AirflowCluster>,
54+
},
55+
}
56+
57+
/// The rolegroup [`ConfigMap`] configures the rolegroup based on the configuration given by the administrator
58+
#[allow(clippy::too_many_arguments)]
59+
pub fn build_rolegroup_config_map(
60+
airflow: &v1alpha2::AirflowCluster,
61+
resolved_product_image: &ResolvedProductImage,
62+
rolegroup: &RoleGroupRef<v1alpha2::AirflowCluster>,
63+
config_file_overrides: &BTreeMap<String, String>,
64+
authentication_config: &AirflowClientAuthenticationDetailsResolved,
65+
authorization_config: &AirflowAuthorizationResolved,
66+
logging: &Logging<Container>,
67+
container: &Container,
68+
) -> Result<ConfigMap, Error> {
69+
let config_file = webserver_config::build(
70+
authentication_config,
71+
authorization_config,
72+
&resolved_product_image.product_version,
73+
config_file_overrides,
74+
)
75+
.with_context(|_| BuildWebserverConfigSnafu {
76+
rolegroup: rolegroup.clone(),
77+
})?;
78+
79+
let mut cm_builder = ConfigMapBuilder::new();
80+
81+
cm_builder
82+
.metadata(
83+
ObjectMetaBuilder::new()
84+
.name_and_namespace(airflow)
85+
.name(rolegroup.object_name())
86+
.ownerreference_from_resource(airflow, None, Some(true))
87+
.context(ObjectMissingMetadataForOwnerRefSnafu)?
88+
.with_recommended_labels(&build_recommended_labels(
89+
airflow,
90+
AIRFLOW_CONTROLLER_NAME,
91+
&resolved_product_image.app_version_label_value,
92+
&rolegroup.role,
93+
&rolegroup.role_group,
94+
))
95+
.context(ObjectMetaSnafu)?
96+
.build(),
97+
)
98+
.add_data(AIRFLOW_CONFIG_FILENAME, config_file);
99+
100+
extend_config_map_with_log_config(
101+
rolegroup,
102+
logging,
103+
container,
104+
&Container::Vector,
105+
&mut cm_builder,
106+
resolved_product_image,
107+
)
108+
.context(InvalidLoggingConfigSnafu {
109+
cm_name: rolegroup.object_name(),
110+
})?;
111+
112+
cm_builder.build().with_context(|_| BuildConfigMapSnafu {
113+
rolegroup: rolegroup.clone(),
114+
})
115+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//! Builders that assemble Kubernetes resources from the validated cluster.
2+
3+
pub mod config_map;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
pub mod build;
12
pub mod dereference;
23
pub mod validate;

0 commit comments

Comments
 (0)