1- use std :: collections :: BTreeMap ;
1+ use stackable_operator :: { kube :: Resource , role_utils :: RoleGroupRef } ;
22
3- use snafu:: { ResultExt , Snafu } ;
4- use stackable_operator:: {
5- builder:: meta:: ObjectMetaBuilder ,
6- k8s_openapi:: api:: core:: v1:: { Service , ServicePort , ServiceSpec } ,
7- kube:: Resource ,
8- kvp:: { Annotations , Labels , ObjectLabels } ,
9- role_utils:: RoleGroupRef ,
10- } ;
11-
12- use crate :: crd:: { HTTP_PORT , HTTP_PORT_NAME , METRICS_PORT , METRICS_PORT_NAME , v1alpha2} ;
13-
14- pub const METRICS_SERVICE_SUFFIX : & str = "metrics" ;
153pub const HEADLESS_SERVICE_SUFFIX : & str = "headless" ;
164
17- #[ derive( Snafu , Debug ) ]
18- pub enum Error {
19- #[ snafu( display( "object is missing metadata to build owner reference" ) ) ]
20- ObjectMissingMetadataForOwnerRef {
21- source : stackable_operator:: builder:: meta:: Error ,
22- } ,
23-
24- #[ snafu( display( "failed to build Metadata" ) ) ]
25- MetadataBuild {
26- source : stackable_operator:: builder:: meta:: Error ,
27- } ,
28-
29- #[ snafu( display( "failed to build Labels" ) ) ]
30- LabelBuild {
31- source : stackable_operator:: kvp:: LabelError ,
32- } ,
33- }
34-
35- /// The rolegroup headless [`Service`] is a service that allows direct access to the instances of a certain rolegroup
36- /// This is mostly useful for internal communication between peers, or for clients that perform client-side load balancing.
37- pub fn build_rolegroup_headless_service (
38- airflow : & v1alpha2:: AirflowCluster ,
39- rolegroup_ref : & RoleGroupRef < v1alpha2:: AirflowCluster > ,
40- object_labels : ObjectLabels < v1alpha2:: AirflowCluster > ,
41- selector : BTreeMap < String , String > ,
42- ) -> Result < Service , Error > {
43- let ports = headless_service_ports ( ) ;
44-
45- let metadata = ObjectMetaBuilder :: new ( )
46- . name_and_namespace ( airflow)
47- . name ( rolegroup_headless_service_name (
48- & rolegroup_ref. object_name ( ) ,
49- ) )
50- . ownerreference_from_resource ( airflow, None , Some ( true ) )
51- . context ( ObjectMissingMetadataForOwnerRefSnafu ) ?
52- . with_recommended_labels ( & object_labels)
53- . context ( MetadataBuildSnafu ) ?
54- . build ( ) ;
55-
56- let service_spec = ServiceSpec {
57- // Internal communication does not need to be exposed
58- type_ : Some ( "ClusterIP" . to_string ( ) ) ,
59- cluster_ip : Some ( "None" . to_string ( ) ) ,
60- ports : Some ( ports) ,
61- selector : Some ( selector) ,
62- publish_not_ready_addresses : Some ( true ) ,
63- ..ServiceSpec :: default ( )
64- } ;
65-
66- Ok ( Service {
67- metadata,
68- spec : Some ( service_spec) ,
69- status : None ,
70- } )
71- }
72-
73- /// The rolegroup metrics [`Service`] is a service that exposes metrics and a prometheus scraping label.
74- pub fn build_rolegroup_metrics_service (
75- airflow : & v1alpha2:: AirflowCluster ,
76- rolegroup_ref : & RoleGroupRef < v1alpha2:: AirflowCluster > ,
77- object_labels : ObjectLabels < v1alpha2:: AirflowCluster > ,
78- selector : BTreeMap < String , String > ,
79- ) -> Result < Service , Error > {
80- let ports = metrics_service_ports ( ) ;
81-
82- let metadata = ObjectMetaBuilder :: new ( )
83- . name_and_namespace ( airflow)
84- . name ( rolegroup_metrics_service_name ( & rolegroup_ref. object_name ( ) ) )
85- . ownerreference_from_resource ( airflow, None , Some ( true ) )
86- . context ( ObjectMissingMetadataForOwnerRefSnafu ) ?
87- . with_recommended_labels ( & object_labels)
88- . context ( MetadataBuildSnafu ) ?
89- . with_labels ( prometheus_labels ( ) )
90- . with_annotations ( prometheus_annotations ( ) )
91- . build ( ) ;
92-
93- let service_spec = ServiceSpec {
94- // Internal communication does not need to be exposed
95- type_ : Some ( "ClusterIP" . to_string ( ) ) ,
96- cluster_ip : Some ( "None" . to_string ( ) ) ,
97- ports : Some ( ports) ,
98- selector : Some ( selector) ,
99- publish_not_ready_addresses : Some ( true ) ,
100- ..ServiceSpec :: default ( )
101- } ;
102-
103- Ok ( Service {
104- metadata,
105- spec : Some ( service_spec) ,
106- status : None ,
107- } )
108- }
109-
1105// REVIEW: made generic so the new controller can call this with
1116// RoleGroupRef<ValidatedAirflowCluster> instead of RoleGroupRef<v1alpha2::AirflowCluster>
1127pub fn stateful_set_service_name < T : Resource > (
@@ -117,52 +12,6 @@ pub fn stateful_set_service_name<T: Resource>(
11712 ) )
11813}
11914
120- /// Returns the metrics rolegroup service name `<cluster>-<role>-<rolegroup>-<METRICS_SERVICE_SUFFIX>`.
121- // TODO: Replace by operator.rs functions
122- fn rolegroup_metrics_service_name ( role_group_ref_object_name : & str ) -> String {
123- format ! ( "{role_group_ref_object_name}-{METRICS_SERVICE_SUFFIX}" )
124- }
125-
126- /// Returns the headless rolegroup service name `<cluster>-<role>-<rolegroup>-<HEADLESS_SERVICE_SUFFIX>`.
127- // TODO: Replace by operator.rs functions
12815fn rolegroup_headless_service_name ( role_group_ref_object_name : & str ) -> String {
12916 format ! ( "{role_group_ref_object_name}-{HEADLESS_SERVICE_SUFFIX}" )
13017}
131-
132- fn headless_service_ports ( ) -> Vec < ServicePort > {
133- vec ! [ ServicePort {
134- name: Some ( HTTP_PORT_NAME . to_string( ) ) ,
135- port: HTTP_PORT . into( ) ,
136- protocol: Some ( "TCP" . to_string( ) ) ,
137- ..ServicePort :: default ( )
138- } ]
139- }
140-
141- fn metrics_service_ports ( ) -> Vec < ServicePort > {
142- vec ! [ ServicePort {
143- name: Some ( METRICS_PORT_NAME . to_string( ) ) ,
144- port: METRICS_PORT . into( ) ,
145- protocol: Some ( "TCP" . to_string( ) ) ,
146- ..ServicePort :: default ( )
147- } ]
148- }
149-
150- /// Common labels for Prometheus
151- fn prometheus_labels ( ) -> Labels {
152- Labels :: try_from ( [ ( "prometheus.io/scrape" , "true" ) ] ) . expect ( "should be a valid label" )
153- }
154-
155- /// Common annotations for Prometheus
156- ///
157- /// These annotations can be used in a ServiceMonitor.
158- ///
159- /// see also <https://github.com/prometheus-community/helm-charts/blob/prometheus-27.32.0/charts/prometheus/values.yaml#L983-L1036>
160- fn prometheus_annotations ( ) -> Annotations {
161- Annotations :: try_from ( [
162- ( "prometheus.io/path" . to_owned ( ) , "/metrics" . to_owned ( ) ) ,
163- ( "prometheus.io/port" . to_owned ( ) , METRICS_PORT . to_string ( ) ) ,
164- ( "prometheus.io/scheme" . to_owned ( ) , "http" . to_owned ( ) ) ,
165- ( "prometheus.io/scrape" . to_owned ( ) , "true" . to_owned ( ) ) ,
166- ] )
167- . expect ( "should be valid annotations" )
168- }
0 commit comments