@@ -87,7 +87,7 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
8787 syncContext .execute (() -> addWatcher (new LdsWatcher (listenerName )));
8888 }
8989
90- public static String toContextStr (String typeName , String resourceName ) {
90+ public static String toContextStr (String typeName , String resourceName ) {
9191 return typeName + " resource: " + resourceName ;
9292 }
9393
@@ -280,8 +280,7 @@ XdsConfig buildConfig() {
280280 // Iterate watchers and build the XdsConfig
281281
282282 // Will only be 1 listener and 1 route resource
283- RdsUpdate rdsUpdate = null ;
284- XdsWatcherBase <?> routeSource = null ;
283+ RdsUpdateSupplier routeSource = null ;
285284 for (XdsWatcherBase <XdsListenerResource .LdsUpdate > ldsWatcher :
286285 getWatchers (XdsListenerResource .getInstance ()).values ()) {
287286 if (!ldsWatcher .getData ().hasValue ()) {
@@ -290,23 +289,15 @@ XdsConfig buildConfig() {
290289 }
291290 XdsListenerResource .LdsUpdate ldsUpdate = ldsWatcher .getData ().getValue ();
292291 builder .setListener (ldsUpdate );
293- if (ldsUpdate .httpConnectionManager () != null
294- && ldsUpdate .httpConnectionManager ().virtualHosts () != null ) {
295- rdsUpdate = new RdsUpdate (ldsUpdate .httpConnectionManager ().virtualHosts ());
296- routeSource = ldsWatcher ;
297- }
292+ routeSource = ((LdsWatcher ) ldsWatcher ).getRouteSource ();
298293 }
299294
300- XdsWatcherBase <RdsUpdate > rdsWatcher = getWatchers (XdsRouteConfigureResource .getInstance ())
301- .values ().stream ().findFirst ().orElse (null );
302- if (rdsWatcher != null ) {
303- if (!rdsWatcher .getData ().hasValue ()) {
304- xdsConfigWatcher .onError (rdsWatcher .toContextString (), rdsWatcher .getData ().getStatus ());
305- return null ;
306- }
307- rdsUpdate = rdsWatcher .getData ().getValue ();
308- routeSource = rdsWatcher ;
295+ StatusOr <RdsUpdate > statusOrRdsUpdate = routeSource .getRdsUpdate ();
296+ if (!statusOrRdsUpdate .hasValue ()) {
297+ xdsConfigWatcher .onError (routeSource .toContextString (), statusOrRdsUpdate .getStatus ());
298+ return null ;
309299 }
300+ RdsUpdate rdsUpdate = statusOrRdsUpdate .getValue ();
310301 builder .setRoute (rdsUpdate );
311302
312303 VirtualHost activeVirtualHost =
@@ -492,13 +483,14 @@ private void addClusterWatcher(String clusterName, Object parentContext, int dep
492483 }
493484
494485 private void updateRoutes (List <VirtualHost > virtualHosts , Object newParentContext ,
495- VirtualHost oldVirtualHost , boolean sameParentContext ) {
496- Set < String > oldClusters = getClusterNamesFromVirtualHost ( oldVirtualHost );
497-
486+ List < VirtualHost > oldVirtualHosts , boolean sameParentContext ) {
487+ VirtualHost oldVirtualHost =
488+ RoutingUtils . findVirtualHostForHostName ( oldVirtualHosts , dataPlaneAuthority );
498489 VirtualHost virtualHost =
499490 RoutingUtils .findVirtualHostForHostName (virtualHosts , dataPlaneAuthority );
500- Set <String > newClusters =
501- virtualHost != null ? getClusterNamesFromVirtualHost (virtualHost ) : Collections .emptySet ();
491+
492+ Set <String > newClusters = getClusterNamesFromVirtualHost (virtualHost );
493+ Set <String > oldClusters = getClusterNamesFromVirtualHost (oldVirtualHost );
502494
503495 if (sameParentContext ) {
504496 // Calculate diffs.
@@ -537,24 +529,6 @@ private static Set<String> getClusterNamesFromVirtualHost(VirtualHost virtualHos
537529 return clusters ;
538530 }
539531
540- @ Nullable
541- private VirtualHost getActiveVirtualHost () {
542- TypeWatchers <?> rdsWatchers = resourceWatchers .get (XdsRouteConfigureResource .getInstance ());
543- if (rdsWatchers == null ) {
544- return null ;
545- }
546-
547- RdsWatcher activeRdsWatcher =
548- (RdsWatcher ) rdsWatchers .watchers .values ().stream ().findFirst ().orElse (null );
549- if (activeRdsWatcher == null || activeRdsWatcher .missingResult ()
550- || !activeRdsWatcher .getData ().hasValue ()) {
551- return null ;
552- }
553-
554- return RoutingUtils .findVirtualHostForHostName (
555- activeRdsWatcher .getData ().getValue ().virtualHosts , dataPlaneAuthority );
556- }
557-
558532 private CdsWatcher getCluster (String clusterName ) {
559533 return (CdsWatcher ) resourceWatchers .get (CLUSTER_RESOURCE ).watchers .get (clusterName );
560534 }
@@ -660,12 +634,19 @@ protected void setDataAsStatus(Status status) {
660634 this .data = StatusOr .fromStatus (status );
661635 }
662636
663- String toContextString () {
637+ public String toContextString () {
664638 return toContextStr (type .typeName (), resourceName );
665639 }
666640 }
667641
668- private class LdsWatcher extends XdsWatcherBase <XdsListenerResource .LdsUpdate > {
642+ private interface RdsUpdateSupplier {
643+ StatusOr <RdsUpdate > getRdsUpdate ();
644+
645+ String toContextString ();
646+ }
647+
648+ private class LdsWatcher extends XdsWatcherBase <XdsListenerResource .LdsUpdate >
649+ implements RdsUpdateSupplier {
669650 String rdsName ;
670651
671652 private LdsWatcher (String resourceName ) {
@@ -677,9 +658,20 @@ public void onChanged(XdsListenerResource.LdsUpdate update) {
677658 checkNotNull (update , "update" );
678659
679660 HttpConnectionManager httpConnectionManager = update .httpConnectionManager ();
680- List <VirtualHost > virtualHosts = httpConnectionManager .virtualHosts ();
681- String rdsName = httpConnectionManager .rdsName ();
682- VirtualHost activeVirtualHost = getActiveVirtualHost ();
661+ List <VirtualHost > virtualHosts ;
662+ String rdsName ;
663+ if (httpConnectionManager == null ) {
664+ // TCP listener. Unsupported config
665+ virtualHosts = Collections .emptyList (); // Not null, to not delegate to RDS
666+ rdsName = null ;
667+ } else {
668+ virtualHosts = httpConnectionManager .virtualHosts ();
669+ rdsName = httpConnectionManager .rdsName ();
670+ }
671+ StatusOr <RdsUpdate > activeRdsUpdate = getRouteSource ().getRdsUpdate ();
672+ List <VirtualHost > activeVirtualHosts = activeRdsUpdate .hasValue ()
673+ ? activeRdsUpdate .getValue ().virtualHosts
674+ : Collections .emptyList ();
683675
684676 boolean changedRdsName = !Objects .equals (rdsName , this .rdsName );
685677 if (changedRdsName ) {
@@ -688,7 +680,7 @@ public void onChanged(XdsListenerResource.LdsUpdate update) {
688680
689681 if (virtualHosts != null ) {
690682 // No RDS watcher since we are getting RDS updates via LDS
691- updateRoutes (virtualHosts , this , activeVirtualHost , this .rdsName == null );
683+ updateRoutes (virtualHosts , this , activeVirtualHosts , this .rdsName == null );
692684 this .rdsName = null ;
693685 } else if (changedRdsName ) {
694686 this .rdsName = rdsName ;
@@ -720,8 +712,7 @@ private void cleanUpRdsWatcher() {
720712 logger .log (XdsLogger .XdsLogLevel .DEBUG , "Stop watching RDS resource {0}" , rdsName );
721713
722714 // Cleanup clusters (as appropriate) that had the old rds watcher as a parent
723- if (!oldRdsWatcher .hasDataValue () || !oldRdsWatcher .getData ().hasValue ()
724- || resourceWatchers .get (CLUSTER_RESOURCE ) == null ) {
715+ if (!oldRdsWatcher .hasDataValue () || resourceWatchers .get (CLUSTER_RESOURCE ) == null ) {
725716 return ;
726717 }
727718 for (XdsWatcherBase <?> watcher :
@@ -732,16 +723,58 @@ private void cleanUpRdsWatcher() {
732723 }
733724
734725 private RdsWatcher getRdsWatcher () {
726+ if (rdsName == null ) {
727+ return null ;
728+ }
735729 TypeWatchers <?> watchers = resourceWatchers .get (XdsRouteConfigureResource .getInstance ());
736- if (watchers == null || rdsName == null || watchers . watchers . isEmpty () ) {
730+ if (watchers == null ) {
737731 return null ;
738732 }
739-
740733 return (RdsWatcher ) watchers .watchers .get (rdsName );
741734 }
735+
736+ public RdsUpdateSupplier getRouteSource () {
737+ if (!hasDataValue ()) {
738+ return this ;
739+ }
740+ HttpConnectionManager hcm = getData ().getValue ().httpConnectionManager ();
741+ if (hcm == null ) {
742+ return this ;
743+ }
744+ List <VirtualHost > virtualHosts = hcm .virtualHosts ();
745+ if (virtualHosts != null ) {
746+ return this ;
747+ }
748+ RdsWatcher rdsWatcher = getRdsWatcher ();
749+ assert rdsWatcher != null ;
750+ return rdsWatcher ;
751+ }
752+
753+ @ Override
754+ public StatusOr <RdsUpdate > getRdsUpdate () {
755+ if (missingResult ()) {
756+ return StatusOr .fromStatus (Status .UNAVAILABLE .withDescription ("Not yet loaded" ));
757+ }
758+ if (!getData ().hasValue ()) {
759+ return StatusOr .fromStatus (getData ().getStatus ());
760+ }
761+ HttpConnectionManager hcm = getData ().getValue ().httpConnectionManager ();
762+ if (hcm == null ) {
763+ return StatusOr .fromStatus (
764+ Status .UNAVAILABLE .withDescription ("Not an API listener" ));
765+ }
766+ List <VirtualHost > virtualHosts = hcm .virtualHosts ();
767+ if (virtualHosts == null ) {
768+ // Code shouldn't trigger this case, as it should be calling RdsWatcher instead. This would
769+ // be easily implemented with getRdsWatcher().getRdsUpdate(), but getting here is likely a
770+ // bug
771+ return StatusOr .fromStatus (Status .INTERNAL .withDescription ("Routes are in RDS, not LDS" ));
772+ }
773+ return StatusOr .fromValue (new RdsUpdate (virtualHosts ));
774+ }
742775 }
743776
744- private class RdsWatcher extends XdsWatcherBase <RdsUpdate > {
777+ private class RdsWatcher extends XdsWatcherBase <RdsUpdate > implements RdsUpdateSupplier {
745778
746779 public RdsWatcher (String resourceName ) {
747780 super (XdsRouteConfigureResource .getInstance (), checkNotNull (resourceName , "resourceName" ));
@@ -750,13 +783,11 @@ public RdsWatcher(String resourceName) {
750783 @ Override
751784 public void onChanged (RdsUpdate update ) {
752785 checkNotNull (update , "update" );
753- RdsUpdate oldData = hasDataValue () ? getData ().getValue () : null ;
754- VirtualHost oldVirtualHost =
755- (oldData != null )
756- ? RoutingUtils .findVirtualHostForHostName (oldData .virtualHosts , dataPlaneAuthority )
757- : null ;
786+ List <VirtualHost > oldVirtualHosts = hasDataValue ()
787+ ? getData ().getValue ().virtualHosts
788+ : Collections .emptyList ();
758789 setData (update );
759- updateRoutes (update .virtualHosts , this , oldVirtualHost , true );
790+ updateRoutes (update .virtualHosts , this , oldVirtualHosts , true );
760791 maybePublishConfig ();
761792 }
762793
@@ -770,6 +801,14 @@ public void onResourceDoesNotExist(String resourceName) {
770801 xdsConfigWatcher .onResourceDoesNotExist (toContextString ());
771802 lastXdsConfig = null ; // Published an empty result
772803 }
804+
805+ @ Override
806+ public StatusOr <RdsUpdate > getRdsUpdate () {
807+ if (missingResult ()) {
808+ return StatusOr .fromStatus (Status .UNAVAILABLE .withDescription ("Not yet loaded" ));
809+ }
810+ return getData ();
811+ }
773812 }
774813
775814 private class CdsWatcher extends XdsWatcherBase <XdsClusterResource .CdsUpdate > {
0 commit comments