|
1 | 1 | pub mod build; |
2 | 2 | pub mod dereference; |
3 | 3 | pub mod validate; |
| 4 | + |
| 5 | +use std::collections::BTreeMap; |
| 6 | + |
| 7 | +use stackable_operator::{ |
| 8 | + commons::product_image_selection::ResolvedProductImage, |
| 9 | + k8s_openapi::{api::core::v1::PodTemplateSpec, apimachinery::pkg::apis::meta::v1::ObjectMeta}, |
| 10 | + kube::Resource, |
| 11 | + v2::{ |
| 12 | + HasName, HasUid, NameIsValidLabelValue, |
| 13 | + builder::pod::container::EnvVarSet, |
| 14 | + types::{ |
| 15 | + kubernetes::{NamespaceName, Uid}, |
| 16 | + operator::ClusterName, |
| 17 | + }, |
| 18 | + }, |
| 19 | +}; |
| 20 | + |
| 21 | +use crate::{ |
| 22 | + crd::{AnyServiceConfig, HbaseRole, v1alpha1}, |
| 23 | + security::opa::HbaseOpaConfig, |
| 24 | + zookeeper::ZookeeperConnectionInformation, |
| 25 | +}; |
| 26 | + |
| 27 | +/// The validated cluster: proves that config merging and validation succeeded for |
| 28 | +/// every role and role group before any resources are created. |
| 29 | +#[derive(Clone, Debug)] |
| 30 | +pub struct ValidatedCluster { |
| 31 | + /// Backs the [`Resource`] implementation (provides `meta()`/`name_any()`) so the build |
| 32 | + /// functions can derive `ObjectMeta`, owner references and labels without the full |
| 33 | + /// `HbaseCluster` object. Holds only name, namespace and uid. |
| 34 | + metadata: ObjectMeta, |
| 35 | + /// The logical (and Kubernetes object) name of the cluster. |
| 36 | + pub name: ClusterName, |
| 37 | + /// The namespace the cluster lives in. Part of the cluster identity; currently consumed via |
| 38 | + /// the [`Resource`] metadata (`name_and_namespace`) rather than read directly. |
| 39 | + #[allow(dead_code)] |
| 40 | + pub namespace: NamespaceName, |
| 41 | + /// The UID of the `HbaseCluster` object, used to build owner references. |
| 42 | + pub uid: Uid, |
| 43 | + pub image: ResolvedProductImage, |
| 44 | + pub cluster_config: ValidatedClusterConfig, |
| 45 | + pub role_group_configs: BTreeMap<HbaseRole, BTreeMap<String, ValidatedRoleGroupConfig>>, |
| 46 | + pub role_configs: BTreeMap<HbaseRole, ValidatedRoleConfig>, |
| 47 | +} |
| 48 | + |
| 49 | +impl ValidatedCluster { |
| 50 | + #[allow(clippy::too_many_arguments)] |
| 51 | + pub fn new( |
| 52 | + name: ClusterName, |
| 53 | + namespace: NamespaceName, |
| 54 | + uid: Uid, |
| 55 | + image: ResolvedProductImage, |
| 56 | + cluster_config: ValidatedClusterConfig, |
| 57 | + role_group_configs: BTreeMap<HbaseRole, BTreeMap<String, ValidatedRoleGroupConfig>>, |
| 58 | + role_configs: BTreeMap<HbaseRole, ValidatedRoleConfig>, |
| 59 | + ) -> Self { |
| 60 | + Self { |
| 61 | + metadata: ObjectMeta { |
| 62 | + name: Some(name.to_string()), |
| 63 | + namespace: Some(namespace.to_string()), |
| 64 | + uid: Some(uid.to_string()), |
| 65 | + ..ObjectMeta::default() |
| 66 | + }, |
| 67 | + name, |
| 68 | + namespace, |
| 69 | + uid, |
| 70 | + image, |
| 71 | + cluster_config, |
| 72 | + role_group_configs, |
| 73 | + role_configs, |
| 74 | + } |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +impl Resource for ValidatedCluster { |
| 79 | + type DynamicType = <v1alpha1::HbaseCluster as Resource>::DynamicType; |
| 80 | + type Scope = <v1alpha1::HbaseCluster as Resource>::Scope; |
| 81 | + |
| 82 | + fn group(dt: &Self::DynamicType) -> std::borrow::Cow<'_, str> { |
| 83 | + v1alpha1::HbaseCluster::group(dt) |
| 84 | + } |
| 85 | + |
| 86 | + fn version(dt: &Self::DynamicType) -> std::borrow::Cow<'_, str> { |
| 87 | + v1alpha1::HbaseCluster::version(dt) |
| 88 | + } |
| 89 | + |
| 90 | + fn kind(dt: &Self::DynamicType) -> std::borrow::Cow<'_, str> { |
| 91 | + v1alpha1::HbaseCluster::kind(dt) |
| 92 | + } |
| 93 | + |
| 94 | + fn plural(dt: &Self::DynamicType) -> std::borrow::Cow<'_, str> { |
| 95 | + v1alpha1::HbaseCluster::plural(dt) |
| 96 | + } |
| 97 | + |
| 98 | + fn meta(&self) -> &ObjectMeta { |
| 99 | + &self.metadata |
| 100 | + } |
| 101 | + |
| 102 | + fn meta_mut(&mut self) -> &mut ObjectMeta { |
| 103 | + &mut self.metadata |
| 104 | + } |
| 105 | +} |
| 106 | + |
| 107 | +impl HasName for ValidatedCluster { |
| 108 | + fn to_name(&self) -> String { |
| 109 | + self.name.to_string() |
| 110 | + } |
| 111 | +} |
| 112 | + |
| 113 | +impl HasUid for ValidatedCluster { |
| 114 | + fn to_uid(&self) -> Uid { |
| 115 | + self.uid.clone() |
| 116 | + } |
| 117 | +} |
| 118 | + |
| 119 | +impl NameIsValidLabelValue for ValidatedCluster { |
| 120 | + fn to_label_value(&self) -> String { |
| 121 | + self.name.to_label_value() |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +/// Cluster-wide settings resolved once during validation. |
| 126 | +#[derive(Clone, Debug)] |
| 127 | +pub struct ValidatedClusterConfig { |
| 128 | + // Pre-resolved OPA connection configuration. |
| 129 | + pub hbase_opa_config: Option<HbaseOpaConfig>, |
| 130 | + pub kerberos_enabled: bool, |
| 131 | + // Pre-resolved kerberos properties for hbase-site.xml (empty when kerberos is disabled). |
| 132 | + pub hbase_site_kerberos_config: BTreeMap<String, String>, |
| 133 | + // Pre-resolved kerberos properties for the discovery `hbase-site.xml` exposed to clients |
| 134 | + // (empty when kerberos is disabled). |
| 135 | + pub discovery_kerberos_config: BTreeMap<String, String>, |
| 136 | + // Pre-resolved ssl-server.xml settings (empty when HTTPS is disabled). |
| 137 | + pub ssl_server_settings: BTreeMap<String, String>, |
| 138 | + // Pre-resolved ssl-client.xml settings (empty when HTTPS is disabled). |
| 139 | + pub ssl_client_settings: BTreeMap<String, String>, |
| 140 | + // Pre-resolved zookeeper connection settings. |
| 141 | + pub zookeeper_connection_information: ZookeeperConnectionInformation, |
| 142 | +} |
| 143 | + |
| 144 | +/// Per-role configuration extracted during validation. |
| 145 | +#[derive(Clone, Debug)] |
| 146 | +pub struct ValidatedRoleConfig { |
| 147 | + pub pdb: stackable_operator::commons::pdb::PdbConfig, |
| 148 | +} |
| 149 | + |
| 150 | +/// Per-rolegroup configuration: the merged CRD config plus the merged |
| 151 | +/// (role <- role group) `configOverrides`, `envOverrides` and `podOverrides`. |
| 152 | +/// |
| 153 | +/// This carries every override channel so that the build step is a pure function of |
| 154 | +/// [`ValidatedCluster`] and never has to reach back into the raw `HbaseCluster`. |
| 155 | +#[derive(Clone, Debug)] |
| 156 | +pub struct ValidatedRoleGroupConfig { |
| 157 | + /// The desired number of replicas (`None` lets Kubernetes default to 1). |
| 158 | + pub replicas: Option<u16>, |
| 159 | + pub merged_config: AnyServiceConfig, |
| 160 | + pub config_overrides: v1alpha1::HbaseConfigOverrides, |
| 161 | + pub env_overrides: EnvVarSet, |
| 162 | + /// Merged (role <- role group) pod template overrides. |
| 163 | + pub pod_overrides: PodTemplateSpec, |
| 164 | + /// Pre-resolved role-specific non-heap JVM args (operator-generated + role/role-group overrides). |
| 165 | + pub non_heap_jvm_args: String, |
| 166 | +} |
0 commit comments