Skip to content

Commit 547a22f

Browse files
committed
refactor: assemble Kafka container env vars via a single EnvVarSet
1 parent 9513480 commit 547a22f

1 file changed

Lines changed: 69 additions & 104 deletions

File tree

rust/operator-binary/src/controller/build/resource/statefulset.rs

Lines changed: 69 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ use stackable_operator::{
55
builder::{
66
meta::ObjectMetaBuilder,
77
pod::{
8-
PodBuilder, container::ContainerBuilder, resources::ResourceRequirementsBuilder,
9-
security::PodSecurityContextBuilder, volume::VolumeBuilder,
8+
PodBuilder,
9+
container::{ContainerBuilder, FieldPathEnvVar},
10+
resources::ResourceRequirementsBuilder,
11+
security::PodSecurityContextBuilder,
12+
volume::VolumeBuilder,
1013
},
1114
},
1215
commons::product_image_selection::ResolvedProductImage,
@@ -16,9 +19,8 @@ use stackable_operator::{
1619
api::{
1720
apps::v1::{StatefulSet, StatefulSetSpec, StatefulSetUpdateStrategy},
1821
core::v1::{
19-
ConfigMapKeySelector, ConfigMapVolumeSource, ContainerPort, EnvVar, EnvVarSource,
20-
ExecAction, ObjectFieldSelector, PodSpec, Probe, ServiceAccount, TCPSocketAction,
21-
Volume,
22+
ConfigMapVolumeSource, ContainerPort, EnvVar, EnvVarSource, ExecAction,
23+
ObjectFieldSelector, PodSpec, Probe, ServiceAccount, TCPSocketAction, Volume,
2224
},
2325
},
2426
apimachinery::pkg::{apis::meta::v1::LabelSelector, util::intstr::IntOrString},
@@ -29,7 +31,7 @@ use stackable_operator::{
2931
builder::{
3032
meta::ownerreference_from_resource,
3133
pod::{
32-
container::EnvVarSet,
34+
container::{EnvVarName, EnvVarSet},
3335
volume::{ListenerReference, listener_operator_volume_source_builder_build_pvc},
3436
},
3537
},
@@ -38,7 +40,7 @@ use stackable_operator::{
3840
STACKABLE_LOG_DIR, ValidatedContainerLogConfigChoice, vector_container,
3941
},
4042
role_group_utils::ResourceNames,
41-
types::kubernetes::{ContainerName, PersistentVolumeClaimName, VolumeName},
43+
types::kubernetes::{ConfigMapKey, ContainerName, PersistentVolumeClaimName, VolumeName},
4244
},
4345
};
4446

@@ -84,6 +86,46 @@ stackable_operator::constant!(VECTOR_LOG_VOLUME_NAME: VolumeName = "log");
8486
/// Name of both the env var and the ZooKeeper discovery ConfigMap key holding the
8587
/// ZooKeeper connection string.
8688
const ZOOKEEPER_ENV_VAR_NAME: &str = "ZOOKEEPER";
89+
90+
/// Parses a compile-time-known env var name; panics only on a programming error (a malformed
91+
/// literal in this file).
92+
fn env_var_name(name: &str) -> EnvVarName {
93+
EnvVarName::from_str(name).expect("a static env var name is valid")
94+
}
95+
96+
/// Environment variables the operator sets on the Kafka container that are common to broker and
97+
/// controller role groups.
98+
///
99+
/// These form the base; the caller merges the user's `envOverrides` on top (see
100+
/// [`build_broker_rolegroup_statefulset`] and [`build_controller_rolegroup_statefulset`]), so a
101+
/// user override wins on a name collision. Using an [`EnvVarSet`] (a name-keyed map) makes that
102+
/// precedence explicit and de-duplicates by name, rather than relying on append order.
103+
fn common_operator_env_vars(
104+
validated_cluster: &ValidatedCluster,
105+
kafka_security: &ValidatedKafkaSecurity,
106+
) -> EnvVarSet {
107+
let mut env = EnvVarSet::new()
108+
.with_field_path(&env_var_name("POD_NAME"), &FieldPathEnvVar::Name)
109+
.with_value(
110+
&env_var_name("KAFKA_CLIENT_PORT"),
111+
kafka_security.client_port().to_string(),
112+
);
113+
114+
// Present in ZooKeeper mode only: brokers use it to connect, controllers for migration.
115+
if let Some(zookeeper_config_map_name) =
116+
&validated_cluster.cluster_config.zookeeper_config_map_name
117+
{
118+
env = env.with_config_map_key_ref(
119+
&env_var_name(ZOOKEEPER_ENV_VAR_NAME),
120+
zookeeper_config_map_name,
121+
&ConfigMapKey::from_str(ZOOKEEPER_ENV_VAR_NAME)
122+
.expect("a static config map key is valid"),
123+
);
124+
}
125+
126+
env
127+
}
128+
87129
const POD_MANAGEMENT_POLICY_PARALLEL: &str = "Parallel";
88130

89131
#[derive(Snafu, Debug)]
@@ -212,36 +254,10 @@ pub fn build_broker_rolegroup_statefulset(
212254
.context(AddKerberosConfigSnafu)?;
213255
}
214256

215-
let mut env = Vec::<EnvVar>::from(validated_rg.env_overrides.clone());
216-
217-
if let Some(zookeeper_config_map_name) =
218-
&validated_cluster.cluster_config.zookeeper_config_map_name
219-
{
220-
env.push(EnvVar {
221-
name: ZOOKEEPER_ENV_VAR_NAME.to_string(),
222-
value_from: Some(EnvVarSource {
223-
config_map_key_ref: Some(ConfigMapKeySelector {
224-
name: zookeeper_config_map_name.to_string(),
225-
key: ZOOKEEPER_ENV_VAR_NAME.to_string(),
226-
..ConfigMapKeySelector::default()
227-
}),
228-
..EnvVarSource::default()
229-
}),
230-
..EnvVar::default()
231-
})
232-
};
233-
234-
env.push(EnvVar {
235-
name: "POD_NAME".to_string(),
236-
value_from: Some(EnvVarSource {
237-
field_ref: Some(ObjectFieldSelector {
238-
api_version: Some("v1".to_string()),
239-
field_path: "metadata.name".to_string(),
240-
}),
241-
..EnvVarSource::default()
242-
}),
243-
..EnvVar::default()
244-
});
257+
// Operator-set env vars first; the user's `envOverrides` are merged on top and win.
258+
let env: Vec<EnvVar> = common_operator_env_vars(validated_cluster, kafka_security)
259+
.merge(validated_rg.env_overrides.clone())
260+
.into();
245261

246262
cb_kafka
247263
.image_from_product_image(resolved_product_image)
@@ -274,10 +290,6 @@ pub fn build_broker_rolegroup_statefulset(
274290
)?;
275291

276292
cb_kafka
277-
.add_env_var(
278-
"KAFKA_CLIENT_PORT".to_string(),
279-
kafka_security.client_port().to_string(),
280-
)
281293
.add_env_vars(env)
282294
.add_container_ports(container_ports(kafka_security))
283295
.add_volume_mount(LOG_DIRS_VOLUME_NAME, STACKABLE_DATA_DIR)
@@ -458,67 +470,21 @@ pub fn build_controller_rolegroup_statefulset(
458470

459471
let mut pod_builder = PodBuilder::new();
460472

461-
let mut env = Vec::<EnvVar>::from(validated_rg.env_overrides.clone());
462-
463-
env.push(EnvVar {
464-
name: "NAMESPACE".to_string(),
465-
value_from: Some(EnvVarSource {
466-
field_ref: Some(ObjectFieldSelector {
467-
api_version: Some("v1".to_string()),
468-
field_path: "metadata.namespace".to_string(),
469-
}),
470-
..EnvVarSource::default()
471-
}),
472-
..EnvVar::default()
473-
});
474-
475-
env.push(EnvVar {
476-
name: "POD_NAME".to_string(),
477-
value_from: Some(EnvVarSource {
478-
field_ref: Some(ObjectFieldSelector {
479-
api_version: Some("v1".to_string()),
480-
field_path: "metadata.name".to_string(),
481-
}),
482-
..EnvVarSource::default()
483-
}),
484-
..EnvVar::default()
485-
});
486-
487-
env.push(EnvVar {
488-
name: "ROLEGROUP_HEADLESS_SERVICE_NAME".to_string(),
489-
value: Some(resource_names.headless_service_name().to_string()),
490-
..EnvVar::default()
491-
});
492-
493-
env.push(EnvVar {
494-
name: "CLUSTER_DOMAIN".to_string(),
495-
value: Some(validated_cluster.cluster_domain.to_string()),
496-
..EnvVar::default()
497-
});
498-
499-
env.push(EnvVar {
500-
name: "KAFKA_CLIENT_PORT".to_string(),
501-
value: Some(kafka_security.client_port().to_string()),
502-
..EnvVar::default()
503-
});
504-
505-
// Controllers need the ZooKeeper connection string for migration
506-
if let Some(zookeeper_config_map_name) =
507-
&validated_cluster.cluster_config.zookeeper_config_map_name
508-
{
509-
env.push(EnvVar {
510-
name: ZOOKEEPER_ENV_VAR_NAME.to_string(),
511-
value_from: Some(EnvVarSource {
512-
config_map_key_ref: Some(ConfigMapKeySelector {
513-
name: zookeeper_config_map_name.to_string(),
514-
key: ZOOKEEPER_ENV_VAR_NAME.to_string(),
515-
..ConfigMapKeySelector::default()
516-
}),
517-
..EnvVarSource::default()
518-
}),
519-
..EnvVar::default()
520-
})
521-
};
473+
// Operator-set env vars first (common + controller-specific); the user's `envOverrides`
474+
// are merged on top and win.
475+
let env: Vec<EnvVar> = common_operator_env_vars(validated_cluster, kafka_security)
476+
.with_field_path(&env_var_name("NAMESPACE"), &FieldPathEnvVar::Namespace)
477+
.with_value(
478+
&env_var_name("ROLEGROUP_HEADLESS_SERVICE_NAME"),
479+
resource_names.headless_service_name().to_string(),
480+
)
481+
.with_value(
482+
&env_var_name("CLUSTER_DOMAIN"),
483+
validated_cluster.cluster_domain.to_string(),
484+
)
485+
.with_value(&env_var_name("PRE_STOP_CONTROLLER_SLEEP_SECONDS"), "10")
486+
.merge(validated_rg.env_overrides.clone())
487+
.into();
522488

523489
cb_kafka
524490
.image_from_product_image(resolved_product_image)
@@ -534,8 +500,7 @@ pub fn build_controller_rolegroup_statefulset(
534500
.pod_descriptors(Some(kafka_role))
535501
.context(BuildPodDescriptorsSnafu)?,
536502
&resolved_product_image.product_version,
537-
)])
538-
.add_env_var("PRE_STOP_CONTROLLER_SLEEP_SECONDS", "10");
503+
)]);
539504

540505
add_common_kafka_env(
541506
&mut cb_kafka,

0 commit comments

Comments
 (0)