@@ -45,15 +45,46 @@ pub async fn get_endpoints(
4545 object_name : & str ,
4646 object_namespace : & str ,
4747) -> Result < IndexMap < String , String > , Error > {
48- let service_list_params =
48+ let list_params =
4949 ListParams :: from_product ( product_name, Some ( object_name) , k8s:: ProductLabel :: Name ) ;
5050
51- let services = kube_client
52- . list_services ( Some ( object_namespace) , & service_list_params )
51+ let listeners = kube_client
52+ . list_listeners ( Some ( object_namespace) , & list_params )
5353 . await
5454 . context ( KubeClientFetchSnafu ) ?;
5555
5656 let mut endpoints = IndexMap :: new ( ) ;
57+ for listener in & listeners {
58+ let Some ( display_name) = display_name_for_listener_name ( & listener. name_any ( ) , object_name)
59+ else {
60+ continue ;
61+ } ;
62+ let Some ( listener_status) = & listener. status else {
63+ continue ;
64+ } ;
65+
66+ for address in listener_status. ingress_addresses . iter ( ) . flatten ( ) {
67+ for port in & address. ports {
68+ let text = format ! ( "{display_name}-{port_name}" , port_name = port. 0 ) ;
69+ let endpoint_url = endpoint_url ( & address. address , * port. 1 , port. 0 ) ;
70+ endpoints. insert ( text, endpoint_url) ;
71+ }
72+ }
73+ }
74+
75+ // Ideally we use listener-operator everywhere, afterwards we can remove the whole k8s Services handling below.
76+ // Currently the Services created by listener-op are missing the recommended labels, so this early exit in case we
77+ // find Listeners is currently not required. However, once we add the recommended labels to the k8s Services, we
78+ // would have duplicated entries (one from the Listener and one from the Service). Because of this we don't look at
79+ // the Services in case we found Listeners!
80+ if !listeners. items . is_empty ( ) {
81+ return Ok ( endpoints) ;
82+ }
83+
84+ let services = kube_client
85+ . list_services ( Some ( object_namespace) , & list_params)
86+ . await
87+ . context ( KubeClientFetchSnafu ) ?;
5788
5889 for service in services {
5990 match get_endpoint_urls ( kube_client, & service, object_name) . await {
@@ -268,7 +299,7 @@ async fn get_node_name_ip_mapping(
268299}
269300
270301fn endpoint_url ( endpoint_host : & str , endpoint_port : i32 , port_name : & str ) -> String {
271- // TODO: Consolidate web-ui port names in operators based on decision in arch meeting from 2022/08/ 10
302+ // TODO: Consolidate web-ui port names in operators based on decision in arch meeting from 2022-08- 10
272303 // For Superset: https://github.com/stackabletech/superset-operator/issues/248
273304 // For Airflow: https://github.com/stackabletech/airflow-operator/issues/146
274305 // As we still support older operator versions we need to also include the "old" way of naming
@@ -285,3 +316,38 @@ fn endpoint_url(endpoint_host: &str, endpoint_port: i32, port_name: &str) -> Str
285316 format ! ( "{endpoint_host}:{endpoint_port}" )
286317 }
287318}
319+
320+ /// Listener names usually have the pattern `listener-simple-hdfs-namenode-default-0` or
321+ /// `simple-hdfs-datanode-default-0-listener`, so we can strip everything before the first occurrence of
322+ /// the stacklet name (`simple-hdfs` in this case). After that it actually get's pretty hard.
323+ /// This truncation is *not* ideal, however we only have implemented listener-operator for HDFS so far,
324+ /// so better to have support for that than nothing :)
325+ fn display_name_for_listener_name ( listener_name : & str , object_name : & str ) -> Option < String > {
326+ let Some ( ( _, display_name) ) = listener_name. split_once ( object_name) else {
327+ return None ;
328+ } ;
329+ Some ( display_name. trim_start_matches ( '-' ) . to_owned ( ) )
330+ }
331+
332+ #[ cfg( test) ]
333+ mod tests {
334+ use super :: * ;
335+ use rstest:: rstest;
336+
337+ #[ rstest]
338+ // These are all the listener names implemented so far (only HDFS is using listener-operator). In the future more
339+ // test-case should be added.
340+ #[ case( "listener-simple-hdfs-namenode-default-0" , "simple-hdfs" , Some ( "namenode-default-0" . to_string( ) ) ) ]
341+ #[ case( "listener-simple-hdfs-namenode-default-1" , "simple-hdfs" , Some ( "namenode-default-1" . to_string( ) ) ) ]
342+ // FIXME: Come up with a more clever strategy to remove the `-listener` suffix. I would prefer to wait until we
343+ // actually have more products using listener-op to not accidentally strip to much.
344+ #[ case( "simple-hdfs-datanode-default-0-listener" , "simple-hdfs" , Some ( "datanode-default-0-listener" . to_string( ) ) ) ]
345+ fn test_display_name_for_listener_name (
346+ #[ case] listener_name : & str ,
347+ #[ case] object_name : & str ,
348+ #[ case] expected : Option < String > ,
349+ ) {
350+ let output = display_name_for_listener_name ( listener_name, object_name) ;
351+ assert_eq ! ( output, expected) ;
352+ }
353+ }
0 commit comments