@@ -7,11 +7,12 @@ use std::{collections::BTreeMap, marker::PhantomData, str::FromStr, sync::Arc};
77
88use apply:: Applier ;
99use build:: build;
10+ use dereference:: dereference;
1011use snafu:: { ResultExt , Snafu } ;
1112use 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
4547mod apply;
4648mod build;
49+ mod dereference;
4750mod update_status;
4851mod 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 =
126132type 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 ) ]
131142pub 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
176195impl 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+
288330pub 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) ]
373398mod 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 (
0 commit comments