@@ -213,6 +213,16 @@ async fn select_exit_node_local(
213213 return Err ( ReconcileError :: NoAvailableExitNodes ) ;
214214 }
215215 } ;
216+
217+ let already_bound_exit_node =
218+ crate :: util:: get_svc_bound_exit_node ( ctx. clone ( ) , service) . await ?;
219+
220+ if let Some ( node) = already_bound_exit_node {
221+ info ! ( "Service already bound to an exit node, using that now" ) ;
222+ * lock = Some ( ( std:: time:: Instant :: now ( ) , node. get_host ( ) ) ) ;
223+ return Ok ( node) ;
224+ }
225+
216226 // if service has label with exit node name, use that and error if not found
217227 let exit_node_selection = {
218228 if let Some ( exit_node_name) = service
@@ -408,42 +418,14 @@ async fn reconcile_svcs(obj: Arc<Service>, ctx: Arc<Context>) -> Result<Action,
408418 let services: Api < Service > = Api :: namespaced ( ctx. client . clone ( ) , & obj. namespace ( ) . unwrap ( ) ) ;
409419 let nodes: Api < ExitNode > = Api :: all ( ctx. client . clone ( ) ) ;
410420
411- // --- Let's skip reconciling services whose exit node IP addresses still exit in the cluster
412- // only list IP addresses of exit nodes
413- let nodes_by_ip: BTreeMap < String , ExitNode > = nodes
414- . list ( & ListParams :: default ( ) . timeout ( 30 ) )
415- . await ?
416- . items
417- . into_iter ( )
418- . filter_map ( |node| {
419- let host = node. get_host ( ) ;
420- if let Some ( _status) = & node. status {
421- Some ( ( host, node) )
422- } else {
423- None
424- }
425- } )
426- . collect ( ) ;
427-
428421 let mut svc = services. get_status ( & obj. name_any ( ) ) . await ?;
429422
430- let svc_lb_ip = svc
431- . status
432- . as_ref ( )
433- . and_then ( |status| status. load_balancer . as_ref ( ) )
434- . and_then ( |lb| lb. ingress . as_ref ( ) )
435- . and_then ( |ingress| ingress. first ( ) )
436- . and_then ( |ingress| ingress. ip . clone ( ) )
437- . unwrap_or_default ( ) ;
438-
439- let existing_bound_node = nodes_by_ip. get ( & svc_lb_ip) ;
440-
441423 let obj = svc. clone ( ) ;
442424
443425 let node_list = nodes. list ( & ListParams :: default ( ) . timeout ( 30 ) ) . await ?;
444426
445427 // Find service binding of svc name/namespace?
446- let existing_node = node_list. iter ( ) . find ( |node| {
428+ let named_exit_node = node_list. iter ( ) . find ( |node| {
447429 node. metadata
448430 . annotations
449431 . as_ref ( )
@@ -453,9 +435,11 @@ async fn reconcile_svcs(obj: Arc<Service>, ctx: Arc<Context>) -> Result<Action,
453435
454436 // XXX: Exit node manifest generation starts here
455437 let node = {
456- if let Some ( node) = existing_node {
438+ if let Some ( node) = named_exit_node {
439+ info ! ( "Service explicitly set to use a named exit node, using that now" ) ;
457440 node. clone ( )
458441 } else if check_service_managed ( & obj) . await {
442+ info ! ( "Service is managed by a cloud provider, Resolving exit node..." ) ;
459443 // Remove attached exit node if the service was managed by a cloud provider and when it is removed
460444 let mut exit_node = exit_node_for_service ( ctx. clone ( ) , & obj) . await ?;
461445
@@ -466,15 +450,8 @@ async fn reconcile_svcs(obj: Arc<Service>, ctx: Arc<Context>) -> Result<Action,
466450 }
467451
468452 exit_node
469- }
470- // If a service *specifically* chooses a named exit node, use that one
471- // Allows support for multiple services to use the same exit node
472-
473- // Else, use the first available exit node
474- // Fails if there's no empty exit node available
475- else if let Some ( node) = existing_bound_node {
476- node. clone ( )
477453 } else {
454+ info ! ( "Selecting an exit node for the service" ) ;
478455 select_exit_node_local ( & ctx, & obj) . await ?
479456 }
480457 } ;
0 commit comments