Skip to content

Commit 262333b

Browse files
maltesanderclaude
andcommitted
feat: Vendor framework::role_utils (mirrors trino)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a551755 commit 262333b

3 files changed

Lines changed: 155 additions & 0 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//! Local framework helpers that mirror the work-in-progress upstream
2+
//! `stackable_operator::v2::*` modules.
3+
//!
4+
//! We vendor `role_utils` because the upstream `v2::role_utils` requires
5+
//! `CommonConfig: Merge` and uses `EnvVarSet` for `env_overrides`. Hive (like
6+
//! trino) uses `JavaCommonConfig`, whose JVM-argument merge is fallible and so
7+
//! does not implement `Merge`; we also want `env_overrides` as a plain
8+
//! `BTreeMap<String, String>`.
9+
//!
10+
//! Follow-up: replace with `stackable_operator::v2::role_utils::*` once upstream
11+
//! relaxes the `Merge` bound.
12+
13+
pub mod role_utils;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
//! Vendored variant of `stackable_operator::v2::role_utils` from the
2+
//! `smooth-operator` branch, with simplifications appropriate for hive-operator.
3+
//!
4+
//! Differences from upstream:
5+
//! - `env_overrides` is `BTreeMap<String, String>` instead of `EnvVarSet`.
6+
//! - No `cli_overrides_to_vec` helper, `ResourceNames`, or service-account helpers.
7+
//! - The `CommonConfig` (a.k.a. `product_specific_common_config`) does NOT need to
8+
//! implement `Merge`. Hive uses `JavaCommonConfig`, which intentionally does not
9+
//! implement `Merge` because its inner `JvmArgumentOverrides::try_merge` is
10+
//! fallible (regex validation). The `RoleGroupConfig::product_specific_common_config`
11+
//! field here simply carries the role-group level value through.
12+
//!
13+
//! Replace with `stackable_operator::v2::role_utils::*` once upstream relaxes the
14+
//! `Merge` bound.
15+
16+
use std::collections::BTreeMap;
17+
18+
use serde::Serialize;
19+
use stackable_operator::{
20+
config::{
21+
fragment::{self, FromFragment},
22+
merge::{Merge, merge},
23+
},
24+
k8s_openapi::{DeepMerge, api::core::v1::PodTemplateSpec},
25+
role_utils::{Role, RoleGroup},
26+
schemars::JsonSchema,
27+
};
28+
29+
/// Hive-friendly view of a validated, merged `RoleGroup`.
30+
#[derive(Clone, Debug, PartialEq)]
31+
pub struct RoleGroupConfig<Config, CommonConfig, ConfigOverrides> {
32+
pub replicas: u16,
33+
pub config: Config,
34+
pub config_overrides: ConfigOverrides,
35+
pub env_overrides: BTreeMap<String, String>,
36+
pub cli_overrides: BTreeMap<String, String>,
37+
pub pod_overrides: PodTemplateSpec,
38+
pub product_specific_common_config: CommonConfig,
39+
}
40+
41+
/// Merges and validates the `RoleGroup` with the given `role` and `default_config`.
42+
pub fn with_validated_config<ValidatedConfig, CommonConfig, Config, RoleConfig, ConfigOverrides>(
43+
role_group: &RoleGroup<Config, CommonConfig, ConfigOverrides>,
44+
role: &Role<Config, ConfigOverrides, RoleConfig, CommonConfig>,
45+
default_config: &Config,
46+
) -> Result<
47+
RoleGroupConfig<ValidatedConfig, CommonConfig, ConfigOverrides>,
48+
fragment::ValidationError,
49+
>
50+
where
51+
ValidatedConfig: FromFragment<Fragment = Config>,
52+
CommonConfig: Clone + Default + JsonSchema + Serialize,
53+
Config: Clone + Merge,
54+
RoleConfig: Default + JsonSchema + Serialize,
55+
ConfigOverrides: Clone + Default + JsonSchema + Merge + Serialize,
56+
{
57+
let validated_config = validate_config(role_group, role, default_config)?;
58+
Ok(RoleGroupConfig {
59+
replicas: role_group.replicas.unwrap_or(1),
60+
config: validated_config,
61+
config_overrides: merged_config_overrides(
62+
&role.config.config_overrides,
63+
role_group.config.config_overrides.clone(),
64+
),
65+
env_overrides: merged_env_overrides(
66+
role.config
67+
.env_overrides
68+
.iter()
69+
.map(|(k, v)| (k.clone(), v.clone()))
70+
.collect(),
71+
role_group
72+
.config
73+
.env_overrides
74+
.iter()
75+
.map(|(k, v)| (k.clone(), v.clone()))
76+
.collect(),
77+
),
78+
cli_overrides: merged_cli_overrides(
79+
role.config.cli_overrides.clone(),
80+
role_group.config.cli_overrides.clone(),
81+
),
82+
pod_overrides: merged_pod_overrides(
83+
role.config.pod_overrides.clone(),
84+
role_group.config.pod_overrides.clone(),
85+
),
86+
product_specific_common_config: role_group.config.product_specific_common_config.clone(),
87+
})
88+
}
89+
90+
fn validate_config<ValidatedConfig, CommonConfig, Config, RoleConfig, ConfigOverrides>(
91+
role_group: &RoleGroup<Config, CommonConfig, ConfigOverrides>,
92+
role: &Role<Config, ConfigOverrides, RoleConfig, CommonConfig>,
93+
default_config: &Config,
94+
) -> Result<ValidatedConfig, fragment::ValidationError>
95+
where
96+
ValidatedConfig: FromFragment<Fragment = Config>,
97+
CommonConfig: Default + JsonSchema + Serialize,
98+
Config: Clone + Merge,
99+
RoleConfig: Default + JsonSchema + Serialize,
100+
ConfigOverrides: Default + JsonSchema + Serialize,
101+
{
102+
role_group.validate_config(role, default_config)
103+
}
104+
105+
fn merged_config_overrides<ConfigOverrides>(
106+
role_config_overrides: &ConfigOverrides,
107+
role_group_config_overrides: ConfigOverrides,
108+
) -> ConfigOverrides
109+
where
110+
ConfigOverrides: Merge,
111+
{
112+
merge(role_group_config_overrides, role_config_overrides)
113+
}
114+
115+
fn merged_env_overrides(
116+
role_env_overrides: BTreeMap<String, String>,
117+
role_group_env_overrides: BTreeMap<String, String>,
118+
) -> BTreeMap<String, String> {
119+
let mut merged = role_env_overrides;
120+
merged.extend(role_group_env_overrides);
121+
merged
122+
}
123+
124+
fn merged_cli_overrides(
125+
role_cli_overrides: BTreeMap<String, String>,
126+
role_group_cli_overrides: BTreeMap<String, String>,
127+
) -> BTreeMap<String, String> {
128+
let mut merged = role_cli_overrides;
129+
merged.extend(role_group_cli_overrides);
130+
merged
131+
}
132+
133+
fn merged_pod_overrides(
134+
role_pod_overrides: PodTemplateSpec,
135+
role_group_pod_overrides: PodTemplateSpec,
136+
) -> PodTemplateSpec {
137+
let mut merged = role_pod_overrides;
138+
merged.merge_from(role_group_pod_overrides);
139+
merged
140+
}

rust/operator-binary/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ mod config;
4242
mod controller;
4343
mod crd;
4444
mod discovery;
45+
#[allow(dead_code)] // wired up in the validate refactor (a later task)
46+
mod framework;
4547
mod kerberos;
4648
mod listener;
4749
mod operations;

0 commit comments

Comments
 (0)