Skip to content

Commit e94df75

Browse files
wip
1 parent 66c9851 commit e94df75

17 files changed

Lines changed: 1067 additions & 231 deletions

rust/operator-binary/src/controller.rs

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ use std::{collections::BTreeMap, marker::PhantomData, str::FromStr, sync::Arc};
77

88
use apply::Applier;
99
use build::build;
10+
use dereference::dereference;
1011
use snafu::{ResultExt, Snafu};
1112
use stackable_operator::{
1213
cluster_resources::ClusterResourceApplyStrategy,
1314
commons::{affinity::StackableAffinity, product_image_selection::ResolvedProductImage},
14-
crd::listener::v1alpha1::Listener,
15+
crd::listener,
1516
k8s_openapi::api::{
1617
apps::v1::StatefulSet,
1718
core::v1::{ConfigMap, Service, ServiceAccount},
@@ -33,7 +34,8 @@ use crate::{
3334
product_logging::framework::{ValidatedContainerLogConfigChoice, VectorContainerLogConfig},
3435
role_utils::{GenericProductSpecificCommonConfig, RoleGroupConfig},
3536
types::{
36-
kubernetes::{ListenerClassName, NamespaceName, Uid},
37+
common::Port,
38+
kubernetes::{Hostname, ListenerClassName, NamespaceName, Uid},
3739
operator::{
3840
ClusterName, ControllerName, OperatorName, ProductName, ProductVersion,
3941
RoleGroupName, RoleName,
@@ -44,6 +46,7 @@ use crate::{
4446

4547
mod apply;
4648
mod build;
49+
mod dereference;
4750
mod update_status;
4851
mod validate;
4952

@@ -102,6 +105,9 @@ pub enum Error {
102105
source: Box<stackable_operator::kube::core::error_boundary::InvalidObject>,
103106
},
104107

108+
#[snafu(display("failed to dereference resources"))]
109+
Dereference { source: dereference::Error },
110+
105111
#[snafu(display("failed to validate cluster"))]
106112
ValidateCluster { source: validate::Error },
107113

@@ -126,10 +132,16 @@ type OpenSearchRoleGroupConfig =
126132
type OpenSearchNodeResources =
127133
stackable_operator::commons::resources::Resources<v1alpha1::StorageConfig>;
128134

135+
/// Additional objects required for building the cluster
136+
pub struct DereferencedObjects {
137+
pub maybe_discovery_service_listener: Option<listener::v1alpha1::Listener>,
138+
}
139+
129140
/// Validated [`v1alpha1::OpenSearchConfig`]
130141
#[derive(Clone, Debug, PartialEq)]
131142
pub struct ValidatedOpenSearchConfig {
132143
pub affinity: StackableAffinity,
144+
pub discovery_service_exposed: bool,
133145
pub listener_class: ListenerClassName,
134146
pub logging: ValidatedLogging,
135147
pub node_roles: NodeRoles,
@@ -151,6 +163,12 @@ impl ValidatedLogging {
151163
}
152164
}
153165

166+
#[derive(Clone, Debug, PartialEq)]
167+
pub struct ValidatedDiscoveryEndpoint {
168+
pub hostname: Hostname,
169+
pub port: Port,
170+
}
171+
154172
/// The validated [`v1alpha1::OpenSearchCluster`]
155173
///
156174
/// Validated means that there should be no reason for Kubernetes to reject resources generated
@@ -171,6 +189,7 @@ pub struct ValidatedCluster {
171189
pub role_group_configs: BTreeMap<RoleGroupName, OpenSearchRoleGroupConfig>,
172190
pub tls_config: v1alpha1::OpenSearchTls,
173191
pub keystores: Vec<v1alpha1::OpenSearchKeystore>,
192+
pub discovery_endpoint: Option<ValidatedDiscoveryEndpoint>,
174193
}
175194

176195
impl ValidatedCluster {
@@ -185,9 +204,10 @@ impl ValidatedCluster {
185204
role_group_configs: BTreeMap<RoleGroupName, OpenSearchRoleGroupConfig>,
186205
tls_config: v1alpha1::OpenSearchTls,
187206
keystores: Vec<v1alpha1::OpenSearchKeystore>,
207+
discovery_endpoint: Option<ValidatedDiscoveryEndpoint>,
188208
) -> Self {
189209
let uid = uid.into();
190-
ValidatedCluster {
210+
Self {
191211
metadata: ObjectMeta {
192212
name: Some(name.to_string()),
193213
namespace: Some(namespace.to_string()),
@@ -203,6 +223,7 @@ impl ValidatedCluster {
203223
role_group_configs,
204224
tls_config,
205225
keystores,
226+
discovery_endpoint,
206227
}
207228
}
208229

@@ -285,6 +306,27 @@ impl Resource for ValidatedCluster {
285306
}
286307
}
287308

309+
/// Marker for prepared Kubernetes resources which are not applied yet
310+
struct Prepared;
311+
/// Marker for applied Kubernetes resources
312+
struct Applied;
313+
314+
/// List of all Kubernetes resources produced by this controller
315+
///
316+
/// `T` is a marker that indicates if these resources are only [`Prepared`] or already [`Applied`].
317+
/// The marker is useful e.g. to ensure that the cluster status is updated based on the applied
318+
/// resources.
319+
struct KubernetesResources<T> {
320+
stateful_sets: Vec<StatefulSet>,
321+
services: Vec<Service>,
322+
listeners: Vec<listener::v1alpha1::Listener>,
323+
config_maps: Vec<ConfigMap>,
324+
service_accounts: Vec<ServiceAccount>,
325+
role_bindings: Vec<RoleBinding>,
326+
pod_disruption_budgets: Vec<PodDisruptionBudget>,
327+
status: PhantomData<T>,
328+
}
329+
288330
pub fn error_policy(
289331
_object: Arc<DeserializeGuard<v1alpha1::OpenSearchCluster>>,
290332
error: &Error,
@@ -316,10 +358,14 @@ pub async fn reconcile(
316358
.map_err(stackable_operator::kube::core::error_boundary::InvalidObject::clone)
317359
.context(DeserializeClusterDefinitionSnafu)?;
318360

319-
// not necessary in this controller: dereference (client required)
361+
// dereference (client required)
362+
let dereferenced_objects = dereference(&context.client, cluster)
363+
.await
364+
.context(DereferenceSnafu)?;
320365

321366
// validate (no client required)
322-
let validated_cluster = validate(&context.names, cluster).context(ValidateClusterSnafu)?;
367+
let validated_cluster =
368+
validate(&context.names, cluster, &dereferenced_objects).context(ValidateClusterSnafu)?;
323369

324370
// build (no client required; infallible)
325371
let prepared_resources = build(&context.names, validated_cluster.clone());
@@ -348,27 +394,6 @@ pub async fn reconcile(
348394
Ok(Action::await_change())
349395
}
350396

351-
/// Marker for prepared Kubernetes resources which are not applied yet
352-
struct Prepared;
353-
/// Marker for applied Kubernetes resources
354-
struct Applied;
355-
356-
/// List of all Kubernetes resources produced by this controller
357-
///
358-
/// `T` is a marker that indicates if these resources are only [`Prepared`] or already [`Applied`].
359-
/// The marker is useful e.g. to ensure that the cluster status is updated based on the applied
360-
/// resources.
361-
struct KubernetesResources<T> {
362-
stateful_sets: Vec<StatefulSet>,
363-
services: Vec<Service>,
364-
listeners: Vec<Listener>,
365-
config_maps: Vec<ConfigMap>,
366-
service_accounts: Vec<ServiceAccount>,
367-
role_bindings: Vec<RoleBinding>,
368-
pod_disruption_budgets: Vec<PodDisruptionBudget>,
369-
status: PhantomData<T>,
370-
}
371-
372397
#[cfg(test)]
373398
mod tests {
374399
use std::{
@@ -509,6 +534,7 @@ mod tests {
509534
.into(),
510535
v1alpha1::OpenSearchTls::default(),
511536
vec![],
537+
None,
512538
)
513539
}
514540

@@ -520,6 +546,7 @@ mod tests {
520546
replicas,
521547
config: ValidatedOpenSearchConfig {
522548
affinity: StackableAffinity::default(),
549+
discovery_service_exposed: true,
523550
listener_class: ListenerClassName::from_str_unsafe("external-stable"),
524551
logging: ValidatedLogging {
525552
opensearch_container: ValidatedContainerLogConfigChoice::Automatic(

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ pub fn build(names: &ContextNames, cluster: ValidatedCluster) -> KubernetesResou
3333
listeners.push(role_group_builder.build_listener());
3434
}
3535

36-
let cluster_manager_service = role_builder.build_seed_nodes_service();
37-
services.push(cluster_manager_service);
36+
if let Some(discovery_config_map) = role_builder.build_discovery_config_map() {
37+
config_maps.push(discovery_config_map);
38+
}
39+
services.push(role_builder.build_seed_nodes_service());
40+
listeners.push(role_builder.build_discovery_service_listener());
3841

3942
let service_accounts = vec![role_builder.build_service_account()];
4043

@@ -75,14 +78,16 @@ mod tests {
7578
use crate::{
7679
controller::{
7780
ContextNames, OpenSearchNodeResources, OpenSearchRoleGroupConfig, ValidatedCluster,
78-
ValidatedContainerLogConfigChoice, ValidatedLogging, ValidatedOpenSearchConfig,
81+
ValidatedContainerLogConfigChoice, ValidatedDiscoveryEndpoint, ValidatedLogging,
82+
ValidatedOpenSearchConfig,
7983
},
8084
crd::{NodeRoles, v1alpha1},
8185
framework::{
8286
builder::pod::container::EnvVarSet,
8387
role_utils::GenericProductSpecificCommonConfig,
8488
types::{
85-
kubernetes::{ListenerClassName, NamespaceName},
89+
common::Port,
90+
kubernetes::{Hostname, ListenerClassName, NamespaceName},
8691
operator::{
8792
ClusterName, ControllerName, OperatorName, ProductName, ProductVersion,
8893
RoleGroupName,
@@ -114,6 +119,7 @@ mod tests {
114119
);
115120
assert_eq!(
116121
vec![
122+
"my-opensearch",
117123
"my-opensearch-nodes-cluster-manager",
118124
"my-opensearch-nodes-coordinating",
119125
"my-opensearch-nodes-data"
@@ -122,6 +128,7 @@ mod tests {
122128
);
123129
assert_eq!(
124130
vec![
131+
"my-opensearch",
125132
"my-opensearch-nodes-cluster-manager",
126133
"my-opensearch-nodes-coordinating",
127134
"my-opensearch-nodes-data"
@@ -199,6 +206,10 @@ mod tests {
199206
.into(),
200207
v1alpha1::OpenSearchTls::default(),
201208
vec![],
209+
Some(ValidatedDiscoveryEndpoint {
210+
hostname: Hostname::from_str_unsafe("1.2.3.4"),
211+
port: Port(12345),
212+
}),
202213
)
203214
}
204215

@@ -210,6 +221,7 @@ mod tests {
210221
replicas,
211222
config: ValidatedOpenSearchConfig {
212223
affinity: StackableAffinity::default(),
224+
discovery_service_exposed: true,
213225
listener_class: ListenerClassName::from_str_unsafe("external-stable"),
214226
logging: ValidatedLogging {
215227
opensearch_container: ValidatedContainerLogConfigChoice::Automatic(

rust/operator-binary/src/controller/build/node_config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ mod tests {
480480
replicas: test_config.replicas,
481481
config: ValidatedOpenSearchConfig {
482482
affinity: StackableAffinity::default(),
483+
discovery_service_exposed: true,
483484
listener_class: ListenerClassName::from_str_unsafe("cluster-internal"),
484485
logging: ValidatedLogging {
485486
opensearch_container: ValidatedContainerLogConfigChoice::Automatic(
@@ -539,6 +540,7 @@ mod tests {
539540
.into(),
540541
v1alpha1::OpenSearchTls::default(),
541542
vec![],
543+
None,
542544
);
543545

544546
NodeConfig::new(

0 commit comments

Comments
 (0)