@@ -37,8 +37,8 @@ use stackable_operator::{
3737 apps:: v1:: { StatefulSet , StatefulSetSpec , StatefulSetUpdateStrategy } ,
3838 core:: v1:: {
3939 ConfigMap , ConfigMapKeySelector , ConfigMapVolumeSource , EmptyDirVolumeSource ,
40- EnvVar , EnvVarSource , ObjectFieldSelector , Probe , SecretVolumeSource , Service ,
41- ServicePort , ServiceSpec , TCPSocketAction , Volume ,
40+ EnvVar , EnvVarSource , ObjectFieldSelector , Probe , SecretVolumeSource ,
41+ TCPSocketAction , Volume ,
4242 } ,
4343 } ,
4444 apimachinery:: pkg:: { apis:: meta:: v1:: LabelSelector , util:: intstr:: IntOrString } ,
@@ -48,7 +48,7 @@ use stackable_operator::{
4848 core:: { DeserializeGuard , error_boundary} ,
4949 runtime:: controller:: Action ,
5050 } ,
51- kvp:: { Label , Labels , ObjectLabels } ,
51+ kvp:: { Labels , ObjectLabels } ,
5252 logging:: controller:: ReconcilerError ,
5353 memory:: { BinaryMultiple , MemoryQuantity } ,
5454 product_config_utils:: env_vars_from_rolegroup_config,
@@ -107,6 +107,10 @@ use crate::{
107107 build_tls_volume, check_or_generate_oidc_admin_password, check_or_generate_sensitive_key,
108108 tls:: { KEYSTORE_NIFI_CONTAINER_MOUNT , KEYSTORE_VOLUME_NAME , TRUSTSTORE_VOLUME_NAME } ,
109109 } ,
110+ service:: {
111+ build_rolegroup_headless_service, build_rolegroup_metrics_service,
112+ rolegroup_headless_service_name,
113+ } ,
110114} ;
111115
112116pub const NIFI_CONTROLLER_NAME : & str = "nificluster" ;
@@ -346,6 +350,9 @@ pub enum Error {
346350
347351 #[ snafu( display( "failed to configure listener" ) ) ]
348352 ListenerConfiguration { source : crate :: listener:: Error } ,
353+
354+ #[ snafu( display( "failed to configure service" ) ) ]
355+ ServiceConfiguration { source : crate :: service:: Error } ,
349356}
350357
351358type Result < T , E = Error > = std:: result:: Result < T , E > ;
@@ -488,8 +495,24 @@ pub async fn reconcile_nifi(
488495 )
489496 . context ( InvalidGitSyncSpecSnafu ) ?;
490497
491- let rg_service =
492- build_node_rolegroup_service ( nifi, & resolved_product_image, & rolegroup) ?;
498+ let role_group_service_recommended_labels = build_recommended_labels (
499+ nifi,
500+ & resolved_product_image. app_version_label ,
501+ & rolegroup. role ,
502+ & rolegroup. role_group ,
503+ ) ;
504+
505+ let role_group_service_selector =
506+ Labels :: role_group_selector ( nifi, APP_NAME , & rolegroup. role , & rolegroup. role_group )
507+ . context ( LabelBuildSnafu ) ?;
508+
509+ let rg_headless_service = build_rolegroup_headless_service (
510+ nifi,
511+ & rolegroup,
512+ role_group_service_recommended_labels. clone ( ) ,
513+ role_group_service_selector. clone ( ) . into ( ) ,
514+ )
515+ . context ( ServiceConfigurationSnafu ) ?;
493516
494517 let role = nifi. spec . nodes . as_ref ( ) . context ( NoNodesDefinedSnafu ) ?;
495518
@@ -539,12 +562,30 @@ pub async fn reconcile_nifi(
539562 )
540563 . await ?;
541564
565+ if resolved_product_image. product_version . starts_with ( "1." ) {
566+ let rg_metrics_service = build_rolegroup_metrics_service (
567+ nifi,
568+ & rolegroup,
569+ role_group_service_recommended_labels,
570+ role_group_service_selector. into ( ) ,
571+ )
572+ . context ( ServiceConfigurationSnafu ) ?;
573+
574+ cluster_resources
575+ . add ( client, rg_metrics_service)
576+ . await
577+ . with_context ( |_| ApplyRoleGroupServiceSnafu {
578+ rolegroup : rolegroup. clone ( ) ,
579+ } ) ?;
580+ }
581+
542582 cluster_resources
543- . add ( client, rg_service )
583+ . add ( client, rg_headless_service )
544584 . await
545585 . with_context ( |_| ApplyRoleGroupServiceSnafu {
546586 rolegroup : rolegroup. clone ( ) ,
547587 } ) ?;
588+
548589 cluster_resources
549590 . add ( client, rg_configmap)
550591 . await
@@ -778,76 +819,12 @@ async fn build_node_rolegroup_config_map(
778819 } )
779820}
780821
781- /// The rolegroup [`Service`] is a headless service that allows direct access to the instances of a certain rolegroup
782- ///
783- /// This is mostly useful for internal communication between peers, or for clients that perform client-side load balancing.
784- fn build_node_rolegroup_service (
785- nifi : & v1alpha1:: NifiCluster ,
786- resolved_product_image : & ResolvedProductImage ,
787- rolegroup : & RoleGroupRef < v1alpha1:: NifiCluster > ,
788- ) -> Result < Service > {
789- let metadata = ObjectMetaBuilder :: new ( )
790- . name_and_namespace ( nifi)
791- . name ( rolegroup_service_name ( rolegroup) )
792- . ownerreference_from_resource ( nifi, None , Some ( true ) )
793- . context ( ObjectMissingMetadataForOwnerRefSnafu ) ?
794- . with_recommended_labels ( build_recommended_labels (
795- nifi,
796- & resolved_product_image. app_version_label ,
797- & rolegroup. role ,
798- & rolegroup. role_group ,
799- ) )
800- . context ( MetadataBuildSnafu ) ?
801- . with_label ( Label :: try_from ( ( "prometheus.io/scrape" , "true" ) ) . context ( LabelBuildSnafu ) ?)
802- . build ( ) ;
803-
804- // In NiFi 2.x metrics are scraped from the HTTPS port
805- let mut service_ports = vec ! [ ] ;
806- if resolved_product_image. product_version . starts_with ( "1." ) {
807- service_ports. push ( ServicePort {
808- name : Some ( METRICS_PORT_NAME . to_owned ( ) ) ,
809- port : METRICS_PORT . into ( ) ,
810- protocol : Some ( "TCP" . to_owned ( ) ) ,
811- ..ServicePort :: default ( )
812- } ) ;
813- } else {
814- service_ports. push ( ServicePort {
815- name : Some ( HTTPS_PORT_NAME . to_owned ( ) ) ,
816- port : HTTPS_PORT . into ( ) ,
817- protocol : Some ( "TCP" . to_owned ( ) ) ,
818- ..ServicePort :: default ( )
819- } ) ;
820- }
821-
822- let spec = Some ( ServiceSpec {
823- // Internal communication does not need to be exposed
824- type_ : Some ( "ClusterIP" . to_owned ( ) ) ,
825- cluster_ip : Some ( "None" . to_owned ( ) ) ,
826- ports : Some ( service_ports) ,
827- selector : Some (
828- Labels :: role_group_selector ( nifi, APP_NAME , & rolegroup. role , & rolegroup. role_group )
829- . context ( LabelBuildSnafu ) ?
830- . into ( ) ,
831- ) ,
832- publish_not_ready_addresses : Some ( true ) ,
833- ..ServiceSpec :: default ( )
834- } ) ;
835-
836- let service = Service {
837- metadata,
838- spec,
839- status : None ,
840- } ;
841-
842- Ok ( service)
843- }
844-
845822const USERDATA_MOUNTPOINT : & str = "/stackable/userdata" ;
846823
847824/// The rolegroup [`StatefulSet`] runs the rolegroup, as configured by the administrator.
848825///
849826/// The [`Pod`](`stackable_operator::k8s_openapi::api::core::v1::Pod`)s are accessible through the
850- /// corresponding [`Service`] (from [`build_node_rolegroup_service `]).
827+ /// corresponding [`stackable_operator::k8s_openapi::api::core::v1:: Service`] (from [`build_rolegroup_headless_service `]).
851828#[ allow( clippy:: too_many_arguments) ]
852829async fn build_node_rolegroup_statefulset (
853830 nifi : & v1alpha1:: NifiCluster ,
@@ -939,7 +916,7 @@ async fn build_node_rolegroup_statefulset(
939916
940917 let node_address = format ! (
941918 "$POD_NAME.{service_name}.{namespace}.svc.{cluster_domain}" ,
942- service_name = rolegroup_service_name ( rolegroup_ref) ,
919+ service_name = rolegroup_headless_service_name ( & rolegroup_ref. object_name ( ) ) ,
943920 namespace = & nifi
944921 . metadata
945922 . namespace
@@ -1443,7 +1420,9 @@ async fn build_node_rolegroup_statefulset(
14431420 ) ,
14441421 ..LabelSelector :: default ( )
14451422 } ,
1446- service_name : Some ( rolegroup_service_name ( rolegroup_ref) ) ,
1423+ service_name : Some ( rolegroup_headless_service_name (
1424+ & rolegroup_ref. object_name ( ) ,
1425+ ) ) ,
14471426 template : pod_template,
14481427 update_strategy : Some ( StatefulSetUpdateStrategy {
14491428 type_ : if rolling_update_supported {
@@ -1482,10 +1461,6 @@ async fn build_node_rolegroup_statefulset(
14821461 } )
14831462}
14841463
1485- pub fn rolegroup_service_name ( rolegroup : & RoleGroupRef < v1alpha1:: NifiCluster > ) -> String {
1486- format ! ( "{name}-headless" , name = rolegroup. object_name( ) )
1487- }
1488-
14891464async fn get_proxy_hosts (
14901465 client : & Client ,
14911466 nifi : & v1alpha1:: NifiCluster ,
0 commit comments