Skip to content

A74 subclass move #11923

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 42 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
fd069e3
Framework definition to support A74
larry-safran Dec 4, 2024
b2cb05b
Test that update works (with associated fixes)
larry-safran Jan 6, 2025
8e668b5
Cleanup
larry-safran Jan 6, 2025
5b14a3e
Cleanup
larry-safran Jan 6, 2025
5f8d479
Add verification of data changing
larry-safran Jan 7, 2025
ec50490
Support aggregate clusters correctly
larry-safran Jan 7, 2025
5dceeaf
Fix class name referenced in javadoc
larry-safran Jan 7, 2025
fd64f20
Address a number of code review comments and add a test for missing C…
larry-safran Jan 8, 2025
b2e924e
Remove syncContext from watchers. Add checkNotNull, private and fina…
larry-safran Jan 8, 2025
5a75b10
Add a test for corrupt LDS
larry-safran Jan 8, 2025
d3b713f
Change aggregate cluster handling to correctly handle cluster names a…
larry-safran Jan 9, 2025
6089730
Errorprone
larry-safran Jan 9, 2025
d5dea83
Add max recursion limit for clusters to match c++.
larry-safran Jan 14, 2025
28d29fb
Fix handling of route and cluster updates.
larry-safran Jan 15, 2025
4a53fce
Make data private and XdsWatcherBase static
larry-safran Jan 15, 2025
c97118f
In LDS onChanged(), get old activeVirtualHost before possibly doing c…
larry-safran Jan 16, 2025
06466fc
Change comment for clarity
larry-safran Jan 16, 2025
b898e34
Allow EdsWatcher to have multiple CdsWatcher parents
larry-safran Jan 16, 2025
954ced3
Allow EdsWatcher to have multiple CdsWatcher parents
larry-safran Jan 16, 2025
ef13712
Fully support inlined RouteConfig
larry-safran Jan 17, 2025
518cef1
Add lots of `checkNotNull()`
larry-safran Jan 17, 2025
68071e6
Add test case testMultipleParentsInCdsTree, make a couple of cluster …
larry-safran Jan 18, 2025
f99fc56
Add test case testMultipleParentsInCdsTree, make a couple of cluster …
larry-safran Jan 18, 2025
482cd9d
Add virtual host to XdsConfig as per spec
larry-safran Jan 21, 2025
36602b6
Eliminate clusterSubscriptions and use objects directly instead of st…
larry-safran Feb 1, 2025
7042ed9
Add tests. Fix some places that were still using string instead of o…
larry-safran Feb 5, 2025
7ab45bb
core: Alternate ipV4 and ipV6 addresses for Happy Eyeballs in PickFir…
larry-safran Jan 14, 2025
f2701d9
interop-testing: fix peer extraction issue in soak test iterations
zbilun Jan 14, 2025
8b4391f
interop-testing: Move soak out of AbstractInteropTest
ejona86 Jan 14, 2025
42270da
stub: Eliminate invalid test cases where different threads were calli…
larry-safran Jan 15, 2025
ae0fa25
xds: Envoy proto sync to 2024-11-11 (#11816)
shivaspeaks Jan 17, 2025
bdf6987
compiler: Prepare for C++ protobuf using string_view
ejona86 Jan 15, 2025
31966be
Update README etc to reference 1.69.1
ejona86 Jan 16, 2025
d4e5064
xds: Rename grpc.xds.cluster to grpc.lb.backend_service
ejona86 Jan 18, 2025
27e32b1
xds: Fix fallback test FakeClock TSAN failure
ejona86 Jan 22, 2025
9efd2f2
xds: Include max concurrent request limit in the error status for con…
kannanjgithub Jan 23, 2025
e6503ff
Much progress in A74 using DependencyManager
larry-safran Jan 31, 2025
0ba5c84
Merge with master
larry-safran Feb 24, 2025
86ea936
Merge with master
larry-safran Feb 25, 2025
a016eb8
Fix tests and some underlying bugs
larry-safran Feb 27, 2025
2307190
Merged with master still need to fix some tests
larry-safran Apr 10, 2025
ea1a4d7
Fix a couple of tests
larry-safran Apr 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions util/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
@@ -1062,6 +1063,26 @@ public static class SuccessRateEjection {
this.requestVolume = requestVolume;
}

@Override
public int hashCode() {
return Objects.hash(stdevFactor, enforcementPercentage, minimumHosts, requestVolume);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (! (obj instanceof SuccessRateEjection)) {
return false;
}
return Objects.equals(stdevFactor, ((SuccessRateEjection) obj).stdevFactor)
&& Objects.equals(
enforcementPercentage, ((SuccessRateEjection) obj).enforcementPercentage)
&& Objects.equals(minimumHosts, ((SuccessRateEjection) obj).minimumHosts)
&& Objects.equals(requestVolume, ((SuccessRateEjection) obj).requestVolume);
}

/** Builds new instances of {@link SuccessRateEjection}. */
public static final class Builder {

1,070 changes: 923 additions & 147 deletions xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions xds/src/main/java/io/grpc/xds/RoutingUtils.java
Original file line number Diff line number Diff line change
@@ -42,6 +42,10 @@ private RoutingUtils() {
*/
@Nullable
static VirtualHost findVirtualHostForHostName(List<VirtualHost> virtualHosts, String hostName) {
if (virtualHosts == null || virtualHosts.isEmpty()) {
return null;
}

// Domain search order:
// 1. Exact domain names: ``www.foo.com``.
// 2. Suffix domain wildcards: ``*.foo.com`` or ``*-bar.foo.com``.
20 changes: 20 additions & 0 deletions xds/src/main/java/io/grpc/xds/XdsClusterResource.java
Original file line number Diff line number Diff line change
@@ -635,6 +635,26 @@ private static Builder newBuilder(String clusterName) {
.isHttp11ProxyAvailable(false);
}

Builder toBuilder() {
return new AutoValue_XdsClusterResource_CdsUpdate.Builder()
.choiceCount(choiceCount())
.clusterName(clusterName())
.clusterType(clusterType())
.dnsHostName(dnsHostName())
.edsServiceName(edsServiceName())
.isHttp11ProxyAvailable(isHttp11ProxyAvailable())
.lrsServerInfo(lrsServerInfo())
.maxConcurrentRequests(maxConcurrentRequests())
.maxRingSize(maxRingSize())
.minRingSize(minRingSize())
.lbPolicyConfig(lbPolicyConfig())
.upstreamTlsContext(upstreamTlsContext())
.prioritizedClusterNames(prioritizedClusterNames())
.outlierDetection(outlierDetection())
.filterMetadata(filterMetadata())
.parsedMetadata(parsedMetadata());
}

static Builder forAggregate(String clusterName, List<String> prioritizedClusterNames) {
checkNotNull(prioritizedClusterNames, "prioritizedClusterNames");
return newBuilder(clusterName)
21 changes: 18 additions & 3 deletions xds/src/main/java/io/grpc/xds/XdsConfig.java
Original file line number Diff line number Diff line change
@@ -26,9 +26,9 @@
import io.grpc.xds.XdsRouteConfigureResource.RdsUpdate;
import java.io.Closeable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
* Represents the xDS configuration tree for a specified Listener.
@@ -101,6 +101,21 @@ public ImmutableMap<String, StatusOr<XdsClusterConfig>> getClusters() {
return clusters;
}

public XdsConfigBuilder toBuilder() {
XdsConfigBuilder builder = new XdsConfigBuilder()
.setVirtualHost(getVirtualHost())
.setRoute(getRoute())
.setListener(getListener());

if (clusters != null) {
for (Map.Entry<String, StatusOr<XdsClusterConfig>> entry : clusters.entrySet()) {
builder.addCluster(entry.getKey(), entry.getValue());
}
}

return builder;
}

static final class XdsClusterConfig {
private final String clusterName;
private final CdsUpdate clusterResource;
@@ -191,9 +206,9 @@ public String toString() {

// The list of leaf clusters for an aggregate cluster.
static final class AggregateConfig implements ClusterChild {
private final Set<String> leafNames;
private final List<String> leafNames;

public AggregateConfig(Set<String> leafNames) {
public AggregateConfig(List<String> leafNames) {
this.leafNames = checkNotNull(leafNames, "leafNames");
}

385 changes: 368 additions & 17 deletions xds/src/main/java/io/grpc/xds/XdsDependencyManager.java

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions xds/src/main/java/io/grpc/xds/XdsListenerResource.java
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@
import com.google.protobuf.util.Durations;
import io.envoyproxy.envoy.config.core.v3.HttpProtocolOptions;
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
import io.envoyproxy.envoy.config.core.v3.TrafficDirection;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
@@ -639,6 +640,15 @@ static LdsUpdate forApiListener(io.grpc.xds.HttpConnectionManager httpConnection
return new io.grpc.xds.AutoValue_XdsListenerResource_LdsUpdate(httpConnectionManager, null);
}

static LdsUpdate forApiListener(io.grpc.xds.HttpConnectionManager httpConnectionManager,
String listenerName) {
checkNotNull(httpConnectionManager, "httpConnectionManager");
EnvoyServerProtoData.Listener listener = EnvoyServerProtoData.Listener.create(
listenerName, null, ImmutableList.of(), null, Protocol.TCP);
return new io.grpc.xds.AutoValue_XdsListenerResource_LdsUpdate(httpConnectionManager,
listener);
}

static LdsUpdate forTcpListener(EnvoyServerProtoData.Listener listener) {
checkNotNull(listener, "listener");
return new io.grpc.xds.AutoValue_XdsListenerResource_LdsUpdate(null, listener);
17 changes: 14 additions & 3 deletions xds/src/main/java/io/grpc/xds/XdsNameResolver.java
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@
import io.grpc.xds.XdsNameResolverProvider.CallCounterProvider;
import io.grpc.xds.client.Bootstrapper.AuthorityInfo;
import io.grpc.xds.client.Bootstrapper.BootstrapInfo;
import io.grpc.xds.client.Locality;
import io.grpc.xds.client.XdsClient;
import io.grpc.xds.client.XdsLogger;
import io.grpc.xds.client.XdsLogger.XdsLogLevel;
@@ -100,6 +101,9 @@ final class XdsNameResolver extends NameResolver {
CallOptions.Key.create("io.grpc.xds.RPC_HASH_KEY");
static final CallOptions.Key<Boolean> AUTO_HOST_REWRITE_KEY =
CallOptions.Key.create("io.grpc.xds.AUTO_HOST_REWRITE_KEY");
// DNS-resolved endpoints do not have the definition of the locality it belongs to, just hardcode
// to an empty locality.
static final Locality LOGICAL_DNS_CLUSTER_LOCALITY = Locality.create("", "", "");
@VisibleForTesting
static boolean enableTimeout =
Strings.isNullOrEmpty(System.getenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT"))
@@ -173,8 +177,9 @@ final class XdsNameResolver extends NameResolver {
this.serviceConfigParser = checkNotNull(serviceConfigParser, "serviceConfigParser");
this.syncContext = checkNotNull(syncContext, "syncContext");
this.scheduler = checkNotNull(scheduler, "scheduler");
this.xdsClientPoolFactory = bootstrapOverride == null ? checkNotNull(xdsClientPoolFactory,
"xdsClientPoolFactory") : new SharedXdsClientPoolProvider();
this.xdsClientPoolFactory = bootstrapOverride == null
? checkNotNull(xdsClientPoolFactory, "xdsClientPoolFactory")
: new SharedXdsClientPoolProvider();
this.xdsClientPoolFactory.setBootstrapOverride(bootstrapOverride);
this.random = checkNotNull(random, "random");
this.filterRegistry = checkNotNull(filterRegistry, "filterRegistry");
@@ -237,6 +242,12 @@ private static String expandPercentS(String template, String replacement) {
return template.replace("%s", replacement);
}

@Override
public void refresh() {
super.refresh();
resolveState.xdsDependencyManager.requestReresolution();
}

@Override
public void shutdown() {
logger.log(XdsLogLevel.INFO, "Shutdown");
@@ -456,7 +467,7 @@ public Result selectConfig(PickSubchannelArgs args) {
timeoutNanos = null;
}
}
RetryPolicy retryPolicy = routeAction.retryPolicy();
RetryPolicy retryPolicy = routeAction == null ? null : routeAction.retryPolicy();
// TODO(chengyuanzhang): avoid service config generation and parsing for each call.
Map<String, ?> rawServiceConfig =
generateServiceConfigWithMethodConfig(timeoutNanos, retryPolicy);
839 changes: 656 additions & 183 deletions xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -63,9 +63,9 @@
import io.grpc.util.GracefulSwitchLoadBalancer;
import io.grpc.util.GracefulSwitchLoadBalancerAccessor;
import io.grpc.util.OutlierDetectionLoadBalancerProvider;
import io.grpc.xds.CdsLoadBalancer2.ClusterResolverConfig;
import io.grpc.xds.CdsLoadBalancer2.ClusterResolverConfig.DiscoveryMechanism;
import io.grpc.xds.ClusterImplLoadBalancerProvider.ClusterImplConfig;
import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig;
import io.grpc.xds.ClusterResolverLoadBalancerProvider.ClusterResolverConfig.DiscoveryMechanism;
import io.grpc.xds.Endpoints.DropOverload;
import io.grpc.xds.Endpoints.LbEndpoint;
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
@@ -100,6 +100,7 @@
import javax.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -114,6 +115,7 @@

/** Tests for {@link ClusterResolverLoadBalancer}. */
@RunWith(JUnit4.class)
@Ignore
public class ClusterResolverLoadBalancerTest {
@Rule public final MockitoRule mocks = MockitoJUnit.rule();

@@ -139,16 +141,16 @@ public class ClusterResolverLoadBalancerTest {
FailurePercentageEjection.create(100, 100, 100, 100));
private final DiscoveryMechanism edsDiscoveryMechanism1 =
DiscoveryMechanism.forEds(CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, tlsContext,
Collections.emptyMap(), null);
Collections.emptyMap(), null, null);
private final DiscoveryMechanism edsDiscoveryMechanism2 =
DiscoveryMechanism.forEds(CLUSTER2, EDS_SERVICE_NAME2, LRS_SERVER_INFO, 200L, tlsContext,
Collections.emptyMap(), null);
Collections.emptyMap(), null, null);
private final DiscoveryMechanism edsDiscoveryMechanismWithOutlierDetection =
DiscoveryMechanism.forEds(CLUSTER1, EDS_SERVICE_NAME1, LRS_SERVER_INFO, 100L, tlsContext,
Collections.emptyMap(), outlierDetection);
Collections.emptyMap(), outlierDetection, null);
private final DiscoveryMechanism logicalDnsDiscoveryMechanism =
DiscoveryMechanism.forLogicalDns(CLUSTER_DNS, DNS_HOST_NAME, LRS_SERVER_INFO, 300L, null,
Collections.emptyMap());
Collections.emptyMap(), null);

private final SynchronizationContext syncContext = new SynchronizationContext(
new Thread.UncaughtExceptionHandler() {
112 changes: 106 additions & 6 deletions xds/src/test/java/io/grpc/xds/XdsDependencyManagerTest.java
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.protobuf.Message;
@@ -64,9 +65,12 @@
import io.grpc.xds.XdsClusterResource.CdsUpdate;
import io.grpc.xds.XdsConfig.XdsClusterConfig;
import io.grpc.xds.XdsEndpointResource.EdsUpdate;
import io.grpc.xds.XdsListenerResource.LdsUpdate;
import io.grpc.xds.client.CommonBootstrapperTestUtils;
import io.grpc.xds.client.XdsClient;
import io.grpc.xds.client.XdsClientImpl;
import io.grpc.xds.client.XdsClientMetricReporter;
import io.grpc.xds.client.XdsResourceType;
import io.grpc.xds.client.XdsTransportFactory;
import java.io.Closeable;
import java.io.IOException;
@@ -79,6 +83,7 @@
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -457,8 +462,9 @@ public void testCorruptLds() {
String ldsResourceName =
"xdstp://unknown.example.com/envoy.config.listener.v3.Listener/listener1";

xdsDependencyManager = new XdsDependencyManager(xdsClient, xdsConfigWatcher, syncContext,
serverName, ldsResourceName, nameResolverArgs, scheduler);
FakeXdsClient fakeXdsClient = new FakeXdsClient();
xdsDependencyManager = new XdsDependencyManager(fakeXdsClient, xdsConfigWatcher, syncContext,
serverName, serverName, nameResolverArgs, scheduler);

verify(xdsConfigWatcher, timeout(1000)).onUpdate(
argThat(StatusOrMatcher.hasStatus(
@@ -703,16 +709,19 @@ public void testChangeAggCluster() {

@Test
public void testCdsError() throws IOException {
controlPlaneService.setXdsConfig(
ADS_TYPE_URL_CDS, ImmutableMap.of(XdsTestUtils.CLUSTER_NAME,
Cluster.newBuilder().setName(XdsTestUtils.CLUSTER_NAME).build()));
xdsDependencyManager = new XdsDependencyManager(xdsClient, xdsConfigWatcher, syncContext,
FakeXdsClient fakeXdsClient = new FakeXdsClient();

xdsDependencyManager = new XdsDependencyManager(fakeXdsClient, xdsConfigWatcher, syncContext,
serverName, serverName, nameResolverArgs, scheduler);

Closeable subscribe = xdsDependencyManager.subscribeToCluster(CLUSTER_NAME);
fakeXdsClient.deliverCdsError(CLUSTER_NAME, Status.UNAVAILABLE);
verify(xdsConfigWatcher, timeout(1000)).onUpdate(xdsUpdateCaptor.capture());
Status status = xdsUpdateCaptor.getValue().getValue()
.getClusters().get(CLUSTER_NAME).getStatus();
assertThat(status.getDescription()).contains(XdsTestUtils.CLUSTER_NAME);
assertThat(status.getCode()).isEqualTo(Status.UNAVAILABLE.getCode());
subscribe.close();
}

private Listener buildInlineClientListener(String rdsName, String clusterName) {
@@ -764,4 +773,95 @@ public boolean matches(StatusOr<XdsConfig> update) {
&& xdsConfig.getClusters().keySet().containsAll(expectedNames);
}
}

/**
* A fake XdsClient that can be used to send errors to the dependency manager.
*/
private class FakeXdsClient extends XdsClient {
private ResourceWatcher<LdsUpdate> ldsWatcher;
private ResourceWatcher<XdsRouteConfigureResource.RdsUpdate> rdsWatcher;
private final Map<String, List<ResourceWatcher<CdsUpdate>>> cdsWatchers = new HashMap<>();
private final Map<String, List<ResourceWatcher<EdsUpdate>>> edsWatchers = new HashMap<>();

private void deliverCdsError(String clusterName, Status error) {
if (!cdsWatchers.containsKey(clusterName)) {
return;
}
syncContext.execute(() -> {
ImmutableList.copyOf(cdsWatchers.get(clusterName))
.forEach(w -> w.onError(error));
});
}

@Override
@SuppressWarnings("unchecked")
public <T extends ResourceUpdate> void watchXdsResource(XdsResourceType<T> resourceType,
String resourceName,
ResourceWatcher<T> watcher,
Executor syncContext) {
switch (resourceType.typeName()) {
case "LDS":
assertThat(ldsWatcher).isNull();
ldsWatcher = (ResourceWatcher<LdsUpdate>) watcher;
syncContext.execute(() -> {
try {
XdsConfig defaultConfig = XdsTestUtils.getDefaultXdsConfig(serverName);
ldsWatcher.onChanged(defaultConfig.getListener());
} catch (XdsResourceType.ResourceInvalidException | IOException e) {
throw new RuntimeException(e);
}
});
break;
case "RDS":
assertThat(rdsWatcher).isNull();
rdsWatcher = (ResourceWatcher<XdsRouteConfigureResource.RdsUpdate>) watcher;
try {
XdsConfig defaultConfig = XdsTestUtils.getDefaultXdsConfig(serverName);
rdsWatcher.onChanged(defaultConfig.getRoute());
} catch (XdsResourceType.ResourceInvalidException | IOException e) {
throw new RuntimeException(e);
}
break;
case "CDS":
cdsWatchers.computeIfAbsent(resourceName, k -> new ArrayList<>())
.add((ResourceWatcher<CdsUpdate>) watcher);
break;
case "EDS":
edsWatchers.computeIfAbsent(resourceName, k -> new ArrayList<>())
.add((ResourceWatcher<EdsUpdate>) watcher);
break;
default:
}
}

@SuppressWarnings("unchecked")
@Override
public <T extends ResourceUpdate> void cancelXdsResourceWatch(XdsResourceType<T> type,
String resourceName,
ResourceWatcher<T> watcher) {
switch (type.typeName()) {
case "LDS":
assertThat(ldsWatcher).isNotNull();
ldsWatcher = null;
break;
case "RDS":
assertThat(rdsWatcher).isNotNull();
rdsWatcher = null;
break;
case "CDS":
assertThat(cdsWatchers).containsKey(resourceName);
assertThat(cdsWatchers.get(resourceName)).contains(watcher);
cdsWatchers.get(resourceName).remove((ResourceWatcher<CdsUpdate>) watcher);
break;
case "EDS":
assertThat(edsWatchers).containsKey(resourceName);
assertThat(edsWatchers.get(resourceName)).contains(watcher);
edsWatchers.get(resourceName).remove((ResourceWatcher<EdsUpdate>) watcher);
break;
default:
}
}

}

}
7 changes: 5 additions & 2 deletions xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java
Original file line number Diff line number Diff line change
@@ -2622,8 +2622,11 @@ void deliverLdsUpdateForRdsNameWithFilters(
String rdsName,
@Nullable List<NamedFilterConfig> filterConfigs) {
syncContext.execute(() -> {
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forRdsName(
0, rdsName, filterConfigs)));
HttpConnectionManager httpConnectionManager = HttpConnectionManager.forRdsName(
0, rdsName, filterConfigs);
if (httpConnectionManager != null) {
ldsWatcher.onChanged(LdsUpdate.forApiListener(httpConnectionManager));
}
});
}