Skip to content

Commit

Permalink
MetadataToProtoTests: RDS
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiitk committed Mar 23, 2021
1 parent cde0967 commit de1e4ac
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 14 deletions.
36 changes: 33 additions & 3 deletions xds/src/main/java/io/grpc/xds/CsdsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import io.envoyproxy.envoy.admin.v3.ListenersConfigDump;
import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListener;
import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListenerState;
import io.envoyproxy.envoy.admin.v3.RoutesConfigDump;
import io.envoyproxy.envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig;
import io.envoyproxy.envoy.service.status.v3.ClientConfig;
import io.envoyproxy.envoy.service.status.v3.ClientStatusDiscoveryServiceGrpc;
import io.envoyproxy.envoy.service.status.v3.ClientStatusRequest;
Expand Down Expand Up @@ -128,18 +130,22 @@ private ClientStatusResponse getConfigDumpForRequest(ClientStatusRequest request
}

private ClientConfig getClientConfigForXdsClient(XdsClient xdsClient) {
ListenersConfigDump ldsConfig = dumpLdsConfig(xdsClient.getCurrentVersion(ResourceType.LDS),
xdsClient.getSubscribedResourcesMetadata(ResourceType.LDS));
ListenersConfigDump ldsConfig = dumpLdsConfig(
xdsClient.getSubscribedResourcesMetadata(ResourceType.LDS),
xdsClient.getCurrentVersion(ResourceType.LDS));
RoutesConfigDump rdsConfig = dumpRdsConfig(
xdsClient.getSubscribedResourcesMetadata(ResourceType.RDS));

return ClientConfig.newBuilder()
.setNode(xdsClient.getNode().toEnvoyProtoNode())
.addXdsConfig(PerXdsConfig.newBuilder().setListenerConfig(ldsConfig))
.addXdsConfig(PerXdsConfig.newBuilder().setRouteConfig(rdsConfig))
.build();
}

@VisibleForTesting
static ListenersConfigDump dumpLdsConfig(
String version, Map<String, ResourceMetadata> resourcesMetadata) {
Map<String, ResourceMetadata> resourcesMetadata, String version) {
ListenersConfigDump.Builder ldsConfig = ListenersConfigDump.newBuilder();
for (Map.Entry<String, ResourceMetadata> entry : resourcesMetadata.entrySet()) {
ldsConfig.addDynamicListeners(buildDynamicListener(entry.getKey(), entry.getValue()));
Expand All @@ -164,6 +170,30 @@ static DynamicListener buildDynamicListener(String name, ResourceMetadata metada
return listener.setActiveState(listenerState).build();
}

@VisibleForTesting
static RoutesConfigDump dumpRdsConfig(Map<String, ResourceMetadata> resourcesMetadata) {
RoutesConfigDump.Builder rdsConfig = RoutesConfigDump.newBuilder();
for (ResourceMetadata metadata : resourcesMetadata.values()) {
rdsConfig.addDynamicRouteConfigs(buildDynamicRouteConfig(metadata));
}
return rdsConfig.build();
}

@VisibleForTesting
static DynamicRouteConfig buildDynamicRouteConfig(ResourceMetadata metadata) {
DynamicRouteConfig.Builder routeConfig = DynamicRouteConfig.newBuilder()
.setVersionInfo(metadata.getVersion())
.setClientStatus(metadataStatusToClientStatus(metadata.getStatus()))
.setLastUpdated(nanosToTimestamp(metadata.getUpdateTimeNanos()));
if (metadata.getErrorState() != null) {
routeConfig.setErrorState(metadataUpdateFailureStateToProto(metadata.getErrorState()));
}
if (metadata.getRawResource() != null) {
routeConfig.setRouteConfig(metadata.getRawResource());
}
return routeConfig.build();
}

private static Timestamp nanosToTimestamp(long updateTimeNanos) {
long exponent = 1_000_000_000L;
long seconds = updateTimeNanos / exponent;
Expand Down
125 changes: 114 additions & 11 deletions xds/src/test/java/io/grpc/xds/CsdsServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@
import io.envoyproxy.envoy.admin.v3.ListenersConfigDump;
import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListener;
import io.envoyproxy.envoy.admin.v3.ListenersConfigDump.DynamicListenerState;
import io.envoyproxy.envoy.admin.v3.RoutesConfigDump;
import io.envoyproxy.envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig;
import io.envoyproxy.envoy.admin.v3.UpdateFailureState;
import io.envoyproxy.envoy.config.core.v3.Node;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.service.status.v3.ClientConfig;
import io.envoyproxy.envoy.service.status.v3.ClientStatusDiscoveryServiceGrpc;
import io.envoyproxy.envoy.service.status.v3.ClientStatusRequest;
Expand All @@ -45,6 +48,7 @@
import io.grpc.xds.Bootstrapper.ServerInfo;
import io.grpc.xds.XdsClient.ResourceMetadata;
import java.util.EnumMap;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -172,6 +176,7 @@ public static class MetadataToProtoTests {
private static final String VERSION_2 = "43";
private static final String ERROR = "Parse error line 1\n Parse error line 2";
private static final Any RAW_LISTENER = Any.pack(Listener.getDefaultInstance());
private static final Any RAW_ROUTE_CONFIG = Any.pack(RouteConfiguration.getDefaultInstance());
// Test timestamps.
private static final Timestamp TIMESTAMP_ZERO = Timestamp.getDefaultInstance();
private static final long NANOS_LAST_UPDATE = 1577923199_606042047L;
Expand All @@ -189,17 +194,18 @@ public static class MetadataToProtoTests {

@Test
public void dumpLdsConfig() {
ListenersConfigDump configDump = CsdsService.dumpLdsConfig(VERSION_1, ImmutableMap.of(
Map<String, ResourceMetadata> resourcesMetadata = ImmutableMap.of(
"A", ResourceMetadata.newResourceMetadataUnknown(),
"B", ResourceMetadata.newResourceMetadataRequested()));
assertThat(configDump.getVersionInfo()).isEqualTo(VERSION_1);
assertThat(configDump.getStaticListenersCount()).isEqualTo(0);
assertThat(configDump.getDynamicListenersCount()).isEqualTo(2);
// Minimal check to verify listeners generated from corresponding metadata.
DynamicListener listenerA = configDump.getDynamicListeners(0);
"B", ResourceMetadata.newResourceMetadataRequested());
ListenersConfigDump ldsConfig = CsdsService.dumpLdsConfig(resourcesMetadata, VERSION_1);
assertThat(ldsConfig.getVersionInfo()).isEqualTo(VERSION_1);
assertThat(ldsConfig.getStaticListenersCount()).isEqualTo(0);
assertThat(ldsConfig.getDynamicListenersCount()).isEqualTo(2);
// Minimal check to confirm that resources generated from corresponding metadata.
DynamicListener listenerA = ldsConfig.getDynamicListeners(0);
assertThat(listenerA.getName()).isEqualTo("A");
assertThat(listenerA.getClientStatus()).isEqualTo(ClientResourceStatus.UNKNOWN);
DynamicListener listenerB = configDump.getDynamicListeners(1);
DynamicListener listenerB = ldsConfig.getDynamicListeners(1);
assertThat(listenerB.getName()).isEqualTo("B");
assertThat(listenerB.getClientStatus()).isEqualTo(ClientResourceStatus.REQUESTED);
}
Expand Down Expand Up @@ -261,15 +267,14 @@ public void buildDynamicListener_metadataNackedFromAcked() {
}

private void verifyDynamicListener(
DynamicListener dynamicListener, ClientResourceStatus clientStatus, boolean hasErrorState) {
DynamicListener dynamicListener, ClientResourceStatus status, boolean hasErrorState) {
assertWithMessage("name").that(dynamicListener.getName()).isEqualTo(LDS_RESOURCE);
assertWithMessage("active_state").that(dynamicListener.hasActiveState()).isTrue();
assertWithMessage("warming_state").that(dynamicListener.hasWarmingState()).isFalse();
assertWithMessage("draining_state").that(dynamicListener.hasDrainingState()).isFalse();
assertWithMessage("error_state").that(dynamicListener.hasErrorState())
.isEqualTo(hasErrorState);
assertWithMessage("client_status").that(dynamicListener.getClientStatus())
.isEqualTo(clientStatus);
assertWithMessage("client_status").that(dynamicListener.getClientStatus()).isEqualTo(status);
}

private void verifyDynamicListenerStateEmpty(DynamicListenerState dynamicListenerState) {
Expand All @@ -289,6 +294,104 @@ private void verifyDynamicListenerStateNotEmpty(DynamicListenerState dynamicList
.isEqualTo(TIMESTAMP_LAST_UPDATE);
}

/* RDS tests */

@Test
public void dumpRdsConfig() {
Map<String, ResourceMetadata> resourcesMetadata = ImmutableMap.of(
"A", ResourceMetadata.newResourceMetadataUnknown(),
"B", ResourceMetadata.newResourceMetadataRequested());
RoutesConfigDump rdsConfig = CsdsService.dumpRdsConfig(resourcesMetadata);
assertThat(rdsConfig.getStaticRouteConfigsCount()).isEqualTo(0);
assertThat(rdsConfig.getDynamicRouteConfigsCount()).isEqualTo(2);
// Minimal check to confirm that resources generated from corresponding metadata.
assertThat(rdsConfig.getDynamicRouteConfigs(0).getClientStatus())
.isEqualTo(ClientResourceStatus.UNKNOWN);
assertThat(rdsConfig.getDynamicRouteConfigs(1).getClientStatus())
.isEqualTo(ClientResourceStatus.REQUESTED);
}

@Test
public void buildDynamicRouteConfig_metadataUnknown() {
ResourceMetadata metadata = ResourceMetadata.newResourceMetadataUnknown();
DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata);
verifyDynamicRouteConfigNoData(dynamicRouteConfig, ClientResourceStatus.UNKNOWN, false);
}

@Test
public void buildDynamicRouteConfig_metadataDoesNotExist() {
ResourceMetadata metadata = ResourceMetadata.newResourceMetadataDoesNotExist();
DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata);
verifyDynamicRouteConfigNoData(dynamicRouteConfig, ClientResourceStatus.DOES_NOT_EXIST,
false);
}

@Test
public void buildDynamicRouteConfig_metadataRequested() {
ResourceMetadata metadata = ResourceMetadata.newResourceMetadataRequested();
DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata);
verifyDynamicRouteConfigNoData(dynamicRouteConfig, ClientResourceStatus.REQUESTED, false);
}

@Test
public void buildDynamicRouteConfig_metadataAcked() {
ResourceMetadata metadata =
ResourceMetadata.newResourceMetadataAcked(RAW_ROUTE_CONFIG, VERSION_1, NANOS_LAST_UPDATE);
DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata);
verifyDynamicRouteConfigAccepted(dynamicRouteConfig, ClientResourceStatus.ACKED,
RAW_ROUTE_CONFIG, false);
}

@Test
public void buildDynamicRouteConfig_metadataNackedFromRequested() {
ResourceMetadata metadataRequested = ResourceMetadata.newResourceMetadataRequested();
ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked(
metadataRequested, VERSION_2, NANOS_FAILED_UPDATE, ERROR);
DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata);
verifyDynamicRouteConfigNoData(dynamicRouteConfig, ClientResourceStatus.NACKED, true);
verifyErrorState(dynamicRouteConfig.getErrorState());
}

@Test
public void buildDynamicRouteConfig_metadataNackedFromAcked() {
ResourceMetadata metadataAcked =
ResourceMetadata.newResourceMetadataAcked(RAW_ROUTE_CONFIG, VERSION_1, NANOS_LAST_UPDATE);
ResourceMetadata metadata = ResourceMetadata.newResourceMetadataNacked(
metadataAcked, VERSION_2, NANOS_FAILED_UPDATE, ERROR);
DynamicRouteConfig dynamicRouteConfig = CsdsService.buildDynamicRouteConfig(metadata);
verifyDynamicRouteConfigAccepted(dynamicRouteConfig, ClientResourceStatus.NACKED,
RAW_ROUTE_CONFIG, true);
verifyErrorState(dynamicRouteConfig.getErrorState());
}

private void verifyDynamicRouteConfigNoData(
DynamicRouteConfig dynamicRouteConfig, ClientResourceStatus status, boolean hasErrorState) {
assertWithMessage("version_info").that(dynamicRouteConfig.getVersionInfo()).isEmpty();
assertWithMessage("route_config").that(dynamicRouteConfig.hasRouteConfig()).isFalse();
assertWithMessage("last_updated").that(dynamicRouteConfig.getLastUpdated())
.isEqualTo(TIMESTAMP_ZERO);
assertWithMessage("error_state").that(dynamicRouteConfig.hasErrorState())
.isEqualTo(hasErrorState);
assertWithMessage("client_status").that(dynamicRouteConfig.getClientStatus())
.isEqualTo(status);
}

private void verifyDynamicRouteConfigAccepted(
DynamicRouteConfig dynamicRouteConfig, ClientResourceStatus status, Any rawResource,
boolean hasErrorState) {
assertWithMessage("version_info").that(dynamicRouteConfig.getVersionInfo())
.isEqualTo(VERSION_1);
assertWithMessage("route_config").that(dynamicRouteConfig.hasRouteConfig()).isTrue();
assertWithMessage("route_config").that(dynamicRouteConfig.getRouteConfig())
.isEqualTo(rawResource);
assertWithMessage("last_updated").that(dynamicRouteConfig.getLastUpdated())
.isEqualTo(TIMESTAMP_LAST_UPDATE);
assertWithMessage("error_state").that(dynamicRouteConfig.hasErrorState())
.isEqualTo(hasErrorState);
assertWithMessage("client_status").that(dynamicRouteConfig.getClientStatus())
.isEqualTo(status);
}

/* Common helpers */

private void verifyErrorState(UpdateFailureState errorState) {
Expand Down

0 comments on commit de1e4ac

Please sign in to comment.