@@ -2,28 +2,52 @@ pub mod build;
22pub mod dereference;
33pub mod validate;
44
5- use std:: collections:: BTreeMap ;
5+ use std:: { collections:: BTreeMap , str :: FromStr } ;
66
77use stackable_operator:: {
8+ builder:: meta:: ObjectMetaBuilder ,
89 commons:: product_image_selection:: ResolvedProductImage ,
910 k8s_openapi:: { api:: core:: v1:: PodTemplateSpec , apimachinery:: pkg:: apis:: meta:: v1:: ObjectMeta } ,
1011 kube:: Resource ,
12+ kvp:: Labels ,
1113 v2:: {
1214 HasName , HasUid , NameIsValidLabelValue ,
13- builder:: pod:: container:: EnvVarSet ,
15+ builder:: { meta:: ownerreference_from_resource, pod:: container:: EnvVarSet } ,
16+ kvp:: label:: { recommended_labels, role_group_selector} ,
17+ role_group_utils:: ResourceNames ,
1418 types:: {
1519 kubernetes:: { NamespaceName , Uid } ,
16- operator:: ClusterName ,
20+ operator:: {
21+ ClusterName , ControllerName , OperatorName , ProductName , ProductVersion ,
22+ RoleGroupName , RoleName ,
23+ } ,
1724 } ,
1825 } ,
1926} ;
2027
2128use crate :: {
22- crd:: { AnyServiceConfig , HbaseRole , v1alpha1} ,
29+ crd:: { APP_NAME , AnyServiceConfig , HbaseRole , OPERATOR_NAME , v1alpha1} ,
30+ hbase_controller:: HBASE_CONTROLLER_NAME ,
2331 security:: opa:: HbaseOpaConfig ,
2432 zookeeper:: ZookeeperConnectionInformation ,
2533} ;
2634
35+ /// The product name (`hbase`) as a type-safe label value.
36+ pub ( crate ) fn product_name ( ) -> ProductName {
37+ ProductName :: from_str ( APP_NAME ) . expect ( "'hbase' is a valid product name" )
38+ }
39+
40+ /// The operator name as a type-safe label value.
41+ pub ( crate ) fn operator_name ( ) -> OperatorName {
42+ OperatorName :: from_str ( OPERATOR_NAME ) . expect ( "the operator name is a valid label value" )
43+ }
44+
45+ /// The controller name as a type-safe label value.
46+ pub ( crate ) fn controller_name ( ) -> ControllerName {
47+ ControllerName :: from_str ( HBASE_CONTROLLER_NAME )
48+ . expect ( "the controller name is a valid label value" )
49+ }
50+
2751/// The validated cluster: proves that config merging and validation succeeded for
2852/// every role and role group before any resources are created.
2953#[ derive( Clone , Debug ) ]
@@ -37,8 +61,12 @@ pub struct ValidatedCluster {
3761 /// The UID of the `HbaseCluster` object, used to build owner references.
3862 pub uid : Uid ,
3963 pub image : ResolvedProductImage ,
64+ /// The product version as a valid label value, used for the recommended
65+ /// `app.kubernetes.io/version` label. Derived from the resolved image's app version label
66+ /// value.
67+ pub product_version : ProductVersion ,
4068 pub cluster_config : ValidatedClusterConfig ,
41- pub role_group_configs : BTreeMap < HbaseRole , BTreeMap < String , ValidatedRoleGroupConfig > > ,
69+ pub role_group_configs : BTreeMap < HbaseRole , BTreeMap < RoleGroupName , ValidatedRoleGroupConfig > > ,
4270 pub role_configs : BTreeMap < HbaseRole , ValidatedRoleConfig > ,
4371}
4472
@@ -50,9 +78,13 @@ impl ValidatedCluster {
5078 uid : Uid ,
5179 image : ResolvedProductImage ,
5280 cluster_config : ValidatedClusterConfig ,
53- role_group_configs : BTreeMap < HbaseRole , BTreeMap < String , ValidatedRoleGroupConfig > > ,
81+ role_group_configs : BTreeMap < HbaseRole , BTreeMap < RoleGroupName , ValidatedRoleGroupConfig > > ,
5482 role_configs : BTreeMap < HbaseRole , ValidatedRoleConfig > ,
5583 ) -> Self {
84+ // `app_version_label_value` is constructed to be a valid label value, so it is also a
85+ // valid `ProductVersion`.
86+ let product_version = ProductVersion :: from_str ( & image. app_version_label_value )
87+ . expect ( "the app version label value is a valid product version" ) ;
5688 Self {
5789 metadata : ObjectMeta {
5890 name : Some ( name. to_string ( ) ) ,
@@ -63,11 +95,90 @@ impl ValidatedCluster {
6395 name,
6496 uid,
6597 image,
98+ product_version,
6699 cluster_config,
67100 role_group_configs,
68101 role_configs,
69102 }
70103 }
104+
105+ /// The Kubernetes role name for an [`HbaseRole`] (e.g. `master`, `regionserver`,
106+ /// `restserver`).
107+ pub fn role_name ( hbase_role : & HbaseRole ) -> RoleName {
108+ RoleName :: from_str ( & hbase_role. to_string ( ) ) . expect ( "an HbaseRole name is a valid role name" )
109+ }
110+
111+ /// Type-safe names for the resources of a given role group.
112+ pub ( crate ) fn resource_names (
113+ & self ,
114+ hbase_role : & HbaseRole ,
115+ role_group_name : & RoleGroupName ,
116+ ) -> ResourceNames {
117+ ResourceNames {
118+ cluster_name : self . name . clone ( ) ,
119+ role_name : Self :: role_name ( hbase_role) ,
120+ role_group_name : role_group_name. clone ( ) ,
121+ }
122+ }
123+
124+ /// Recommended labels for a role-group resource.
125+ pub fn recommended_labels (
126+ & self ,
127+ hbase_role : & HbaseRole ,
128+ role_group_name : & RoleGroupName ,
129+ ) -> Labels {
130+ recommended_labels (
131+ self ,
132+ & product_name ( ) ,
133+ & self . product_version ,
134+ & operator_name ( ) ,
135+ & controller_name ( ) ,
136+ & Self :: role_name ( hbase_role) ,
137+ role_group_name,
138+ )
139+ }
140+
141+ /// Selector labels matching the pods of a role group.
142+ pub fn role_group_selector (
143+ & self ,
144+ hbase_role : & HbaseRole ,
145+ role_group_name : & RoleGroupName ,
146+ ) -> Labels {
147+ role_group_selector (
148+ self ,
149+ & product_name ( ) ,
150+ & Self :: role_name ( hbase_role) ,
151+ role_group_name,
152+ )
153+ }
154+
155+ /// Returns an [`ObjectMetaBuilder`] pre-filled with the namespace, an owner reference back to
156+ /// this cluster, and the recommended labels for a resource named `name` in `role_group_name`.
157+ ///
158+ /// Consolidates the metadata chain repeated by the child-resource builders. Call sites that
159+ /// need extra labels/annotations chain them onto the returned builder.
160+ pub ( crate ) fn object_meta (
161+ & self ,
162+ name : impl Into < String > ,
163+ hbase_role : & HbaseRole ,
164+ role_group_name : & RoleGroupName ,
165+ ) -> ObjectMetaBuilder {
166+ let mut builder = ObjectMetaBuilder :: new ( ) ;
167+ builder
168+ . name_and_namespace ( self )
169+ . name ( name)
170+ . ownerreference ( ownerreference_from_resource ( self , None , Some ( true ) ) )
171+ . with_labels ( self . recommended_labels ( hbase_role, role_group_name) ) ;
172+ builder
173+ }
174+
175+ /// Whether Kerberos is enabled for this cluster.
176+ ///
177+ /// Mirrors [`v1alpha1::HbaseCluster::has_kerberos_enabled`], derived here from the validated
178+ /// config so build steps don't have to re-read the raw cluster.
179+ pub fn has_kerberos_enabled ( & self ) -> bool {
180+ self . cluster_config . kerberos_enabled
181+ }
71182}
72183
73184impl Resource for ValidatedCluster {
0 commit comments