Skip to content

Commit d98d95d

Browse files
Use attributed string type for EnvVarName
1 parent f0a4027 commit d98d95d

2 files changed

Lines changed: 50 additions & 60 deletions

File tree

crates/stackable-operator/src/v2/builder/pod/container.rs

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::{
22
collections::{BTreeMap, btree_map},
3-
fmt::Display,
43
str::FromStr,
54
};
65

76
use snafu::Snafu;
87
use strum::{EnumDiscriminants, IntoStaticStr};
98

109
use crate::{
10+
attributed_string_type,
1111
builder::pod::container::{ContainerBuilder, FieldPathEnvVar},
1212
k8s_openapi::api::core::v1::{ConfigMapKeySelector, EnvVar, EnvVarSource, ObjectFieldSelector},
1313
v2::types::kubernetes::{ConfigMapKey, ConfigMapName, ContainerName},
@@ -28,40 +28,13 @@ pub fn new_container_builder(container_name: &ContainerName) -> ContainerBuilder
2828
ContainerBuilder::new(container_name.as_ref()).expect("should be a valid container name")
2929
}
3030

31-
// TODO Use attributed_string_type instead
32-
/// Validated environment variable name
33-
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
34-
pub struct EnvVarName(String);
35-
36-
impl EnvVarName {
37-
/// Creates an [`EnvVarName`] from the given string and panics if the validation failed
38-
///
39-
/// Use this only with constant names that are also tested in unit tests!
40-
pub fn from_str_unsafe(s: &str) -> Self {
41-
Self::from_str(s).expect("should be a valid environment variable name")
42-
}
43-
}
44-
45-
impl Display for EnvVarName {
46-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47-
self.0.fmt(f)
48-
}
49-
}
50-
51-
impl FromStr for EnvVarName {
52-
type Err = Error;
53-
54-
fn from_str(s: &str) -> Result<Self, Self::Err> {
55-
// The length of environment variable names seems not to be restricted.
56-
57-
if !s.is_empty() && s.chars().all(|c| matches!(c, ' '..='<' | '>'..='~')) {
58-
Ok(Self(s.to_owned()))
59-
} else {
60-
Err(Error::ParseEnvVarName {
61-
env_var_name: s.to_owned(),
62-
})
63-
}
64-
}
31+
attributed_string_type! {
32+
EnvVarName,
33+
"The name of an environment variable",
34+
"MY_ENV_VAR",
35+
(min_length = 1),
36+
(regex = "^[ -<>-~]+$")
37+
// The maximum length of environment variable names seems not to be restricted.
6538
}
6639

6740
/// A set of [`EnvVar`]s

crates/stackable-operator/src/v2/product_logging/framework.rs

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,17 @@ pub const STACKABLE_LOG_DIR: &str = "/stackable/log";
4242
constant!(VECTOR_AGGREGATOR_CM_KEY: ConfigMapKey = "ADDRESS");
4343

4444
// Copy of the private constant `stackable_operator::product_logging::framework::VECTOR_AGGREGATOR_ADDRESS`
45-
constant!(VECTOR_AGGREGATOR_ENV_NAME: EnvVarName = "VECTOR_AGGREGATOR_ADDRESS");
45+
constant!(ENV_VAR_NAME_VECTOR_AGGREGATOR_ADDRESS: EnvVarName = "VECTOR_AGGREGATOR_ADDRESS");
46+
47+
constant!(ENV_VAR_NAME_CLUSTER_NAME: EnvVarName = "CLUSTER_NAME");
48+
constant!(ENV_VAR_NAME_DATA_DIR: EnvVarName = "DATA_DIR");
49+
constant!(ENV_VAR_NAME_LOG_DIR: EnvVarName = "LOG_DIR");
50+
constant!(ENV_VAR_NAME_NAMESPACE: EnvVarName = "NAMESPACE");
51+
constant!(ENV_VAR_NAME_ROLE_GROUP_NAME: EnvVarName = "ROLE_GROUP_NAME");
52+
constant!(ENV_VAR_NAME_ROLE_NAME: EnvVarName = "ROLE_NAME");
53+
constant!(ENV_VAR_NAME_VECTOR_CONFIG_YAML: EnvVarName = "VECTOR_CONFIG_YAML");
54+
constant!(ENV_VAR_NAME_VECTOR_FILE_LOG_LEVEL: EnvVarName = "VECTOR_FILE_LOG_LEVEL");
55+
constant!(ENV_VAR_NAME_VECTOR_LOG: EnvVarName = "VECTOR_LOG");
4656

4757
#[derive(Debug, EnumDiscriminants, Snafu)]
4858
#[strum_discriminants(derive(IntoStaticStr))]
@@ -109,7 +119,6 @@ where
109119
}
110120

111121
/// Builds the Vector container
112-
#[expect(clippy::too_many_lines)]
113122
pub fn vector_container(
114123
container_name: &ContainerName,
115124
image: &ResolvedProductImage,
@@ -140,44 +149,32 @@ pub fn vector_container(
140149
};
141150

142151
let env_vars = EnvVarSet::new()
152+
.with_value(&ENV_VAR_NAME_CLUSTER_NAME, &resource_names.cluster_name)
143153
.with_value(
144-
&EnvVarName::from_str_unsafe("CLUSTER_NAME"),
145-
&resource_names.cluster_name,
146-
)
147-
.with_value(
148-
&EnvVarName::from_str_unsafe("DATA_DIR"),
154+
&ENV_VAR_NAME_DATA_DIR,
149155
format!("{STACKABLE_LOG_DIR}/{VECTOR_STATE_DIR}"),
150156
)
151-
.with_value(&EnvVarName::from_str_unsafe("LOG_DIR"), STACKABLE_LOG_DIR)
152-
.with_field_path(
153-
&EnvVarName::from_str_unsafe("NAMESPACE"),
154-
&FieldPathEnvVar::Namespace,
155-
)
157+
.with_value(&ENV_VAR_NAME_LOG_DIR, STACKABLE_LOG_DIR)
158+
.with_field_path(&ENV_VAR_NAME_NAMESPACE, &FieldPathEnvVar::Namespace)
156159
.with_value(
157-
&EnvVarName::from_str_unsafe("ROLE_GROUP_NAME"),
160+
&ENV_VAR_NAME_ROLE_GROUP_NAME,
158161
&resource_names.role_group_name,
159162
)
160-
.with_value(
161-
&EnvVarName::from_str_unsafe("ROLE_NAME"),
162-
&resource_names.role_name,
163-
)
163+
.with_value(&ENV_VAR_NAME_ROLE_NAME, &resource_names.role_name)
164164
.with_config_map_key_ref(
165-
&VECTOR_AGGREGATOR_ENV_NAME,
165+
&ENV_VAR_NAME_VECTOR_AGGREGATOR_ADDRESS,
166166
&vector_container_log_config.vector_aggregator_config_map_name,
167167
&VECTOR_AGGREGATOR_CM_KEY,
168168
)
169169
.with_value(
170-
&EnvVarName::from_str_unsafe("VECTOR_CONFIG_YAML"),
170+
&ENV_VAR_NAME_VECTOR_CONFIG_YAML,
171171
format!("{STACKABLE_CONFIG_DIR}/{VECTOR_CONFIG_FILE}"),
172172
)
173173
.with_value(
174-
&EnvVarName::from_str_unsafe("VECTOR_FILE_LOG_LEVEL"),
174+
&ENV_VAR_NAME_VECTOR_FILE_LOG_LEVEL,
175175
vector_file_log_level.to_vector_literal(),
176176
)
177-
.with_value(
178-
&EnvVarName::from_str_unsafe("VECTOR_LOG"),
179-
log_level.to_vector_literal(),
180-
)
177+
.with_value(&ENV_VAR_NAME_VECTOR_LOG, log_level.to_vector_literal())
181178
.merge(extra_env_vars);
182179

183180
let resources = ResourceRequirementsBuilder::new()
@@ -237,7 +234,11 @@ mod tests {
237234
use serde_json::json;
238235

239236
use super::{
240-
ErrorDiscriminants, ValidatedContainerLogConfigChoice, VectorContainerLogConfig,
237+
ENV_VAR_NAME_CLUSTER_NAME, ENV_VAR_NAME_DATA_DIR, ENV_VAR_NAME_LOG_DIR,
238+
ENV_VAR_NAME_NAMESPACE, ENV_VAR_NAME_ROLE_GROUP_NAME, ENV_VAR_NAME_ROLE_NAME,
239+
ENV_VAR_NAME_VECTOR_AGGREGATOR_ADDRESS, ENV_VAR_NAME_VECTOR_CONFIG_YAML,
240+
ENV_VAR_NAME_VECTOR_FILE_LOG_LEVEL, ENV_VAR_NAME_VECTOR_LOG, ErrorDiscriminants,
241+
VECTOR_AGGREGATOR_CM_KEY, ValidatedContainerLogConfigChoice, VectorContainerLogConfig,
241242
validate_logging_configuration_for_container, vector_container,
242243
};
243244
use crate::{
@@ -257,6 +258,22 @@ mod tests {
257258
},
258259
};
259260

261+
#[test]
262+
fn test_constants() {
263+
// Test that dereferencing the constants does not panic.
264+
let _ = VECTOR_AGGREGATOR_CM_KEY;
265+
let _ = ENV_VAR_NAME_VECTOR_AGGREGATOR_ADDRESS;
266+
let _ = ENV_VAR_NAME_CLUSTER_NAME;
267+
let _ = ENV_VAR_NAME_DATA_DIR;
268+
let _ = ENV_VAR_NAME_LOG_DIR;
269+
let _ = ENV_VAR_NAME_NAMESPACE;
270+
let _ = ENV_VAR_NAME_ROLE_GROUP_NAME;
271+
let _ = ENV_VAR_NAME_ROLE_NAME;
272+
let _ = ENV_VAR_NAME_VECTOR_CONFIG_YAML;
273+
let _ = ENV_VAR_NAME_VECTOR_FILE_LOG_LEVEL;
274+
let _ = ENV_VAR_NAME_VECTOR_LOG;
275+
}
276+
260277
#[test]
261278
fn test_validate_logging_configuration_for_container_ok_automatic_log_config() {
262279
let logging = Logging {

0 commit comments

Comments
 (0)