xds: clean up MessagePrinter (#7658)

In v3, UpstreamTlsContext and DownstreamTlsContext messages are not transitively type-referenced by Cluster and Listener. So the message printer is not able to print them without adding them into the registry manually.
This commit is contained in:
Chengyuan Zhang 2020-11-24 01:03:14 -08:00 committed by GitHub
parent ca12e7a339
commit f2e71a69b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 431 additions and 532 deletions

View File

@ -24,16 +24,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier;
import com.google.protobuf.Any;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageOrBuilder;
import com.google.protobuf.TypeRegistry;
import com.google.protobuf.util.JsonFormat;
import com.google.rpc.Code;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.envoyproxy.envoy.service.discovery.v3.AggregatedDiscoveryServiceGrpc;
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryRequest;
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryResponse;
@ -717,44 +708,4 @@ abstract class AbstractXdsClient extends XdsClient {
requestWriter.onError(error);
}
}
/**
* Convert protobuf message to human readable String format. Useful for protobuf messages
* containing {@link com.google.protobuf.Any} fields.
*/
@VisibleForTesting
static final class MessagePrinter {
private final JsonFormat.Printer printer;
@VisibleForTesting
MessagePrinter() {
TypeRegistry registry =
TypeRegistry.newBuilder()
.add(Listener.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.Listener.getDescriptor())
.add(HttpConnectionManager.getDescriptor())
.add(
io.envoyproxy.envoy.config.filter.network.http_connection_manager.v2
.HttpConnectionManager.getDescriptor())
.add(RouteConfiguration.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.RouteConfiguration.getDescriptor())
.add(Cluster.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.Cluster.getDescriptor())
.add(ClusterLoadAssignment.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.ClusterLoadAssignment.getDescriptor())
.build();
printer = JsonFormat.printer().usingTypeRegistry(registry);
}
@VisibleForTesting
String print(MessageOrBuilder message) {
String res;
try {
res = printer.print(message);
} catch (InvalidProtocolBufferException e) {
res = message + " (failed to pretty-print: " + e + ")";
}
return res;
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 2020 The gRPC Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.xds;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageOrBuilder;
import com.google.protobuf.TypeRegistry;
import com.google.protobuf.util.JsonFormat;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext;
/**
* Converts protobuf message to human readable String format. Useful for protobuf messages
* containing {@link com.google.protobuf.Any} fields.
*/
final class MessagePrinter {
private final JsonFormat.Printer printer;
MessagePrinter() {
TypeRegistry registry =
TypeRegistry.newBuilder()
.add(Listener.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.Listener.getDescriptor())
.add(HttpConnectionManager.getDescriptor())
.add(io.envoyproxy.envoy.config.filter.network.http_connection_manager.v2
.HttpConnectionManager.getDescriptor())
// UpstreamTlsContext and DownstreamTlsContext in v3 are not transitively imported
// by top-level resource types.
.add(UpstreamTlsContext.getDescriptor())
.add(DownstreamTlsContext.getDescriptor())
.add(RouteConfiguration.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.RouteConfiguration.getDescriptor())
.add(Cluster.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.Cluster.getDescriptor())
.add(ClusterLoadAssignment.getDescriptor())
.add(io.envoyproxy.envoy.api.v2.ClusterLoadAssignment.getDescriptor())
.build();
printer = JsonFormat.printer().usingTypeRegistry(registry);
}
String print(MessageOrBuilder message) {
String res;
try {
res = printer.print(message);
} catch (InvalidProtocolBufferException e) {
res = message + " (failed to pretty-print: " + e + ")";
}
return res;
}
}

View File

@ -1,276 +0,0 @@
/*
* Copyright 2020 The gRPC Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.xds;
import static com.google.common.truth.Truth.assertThat;
import static io.grpc.xds.XdsClientTestHelper.buildCluster;
import static io.grpc.xds.XdsClientTestHelper.buildClusterLoadAssignment;
import static io.grpc.xds.XdsClientTestHelper.buildDiscoveryResponse;
import static io.grpc.xds.XdsClientTestHelper.buildDropOverload;
import static io.grpc.xds.XdsClientTestHelper.buildLbEndpoint;
import static io.grpc.xds.XdsClientTestHelper.buildListener;
import static io.grpc.xds.XdsClientTestHelper.buildLocalityLbEndpoints;
import static io.grpc.xds.XdsClientTestHelper.buildRouteConfiguration;
import static io.grpc.xds.XdsClientTestHelper.buildVirtualHost;
import com.google.common.collect.ImmutableList;
import com.google.protobuf.Any;
import io.envoyproxy.envoy.config.core.v3.HealthStatus;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryResponse;
import io.grpc.xds.AbstractXdsClient.MessagePrinter;
import io.grpc.xds.AbstractXdsClient.ResourceType;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Tests for {@link AbstractXdsClient}.
*/
@RunWith(JUnit4.class)
public class AbstractXdsClientTest {
@Test
public void messagePrinter_printLdsResponse() {
MessagePrinter printer = new MessagePrinter();
List<Any> listeners = ImmutableList.of(
Any.pack(buildListener("foo.googleapis.com:8080",
Any.pack(
HttpConnectionManager.newBuilder()
.setRouteConfig(
buildRouteConfiguration("route-foo.googleapis.com",
ImmutableList.of(
buildVirtualHost(
ImmutableList.of("foo.googleapis.com", "bar.googleapis.com"),
"cluster.googleapis.com"))))
.build()))));
DiscoveryResponse response =
buildDiscoveryResponse("0", listeners, ResourceType.LDS.typeUrl(), "0000");
String expectedString = "{\n"
+ " \"versionInfo\": \"0\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.listener.v3.Listener\",\n"
+ " \"name\": \"foo.googleapis.com:8080\",\n"
+ " \"address\": {\n"
+ " },\n"
+ " \"filterChains\": [{\n"
+ " }],\n"
+ " \"apiListener\": {\n"
+ " \"apiListener\": {\n"
+ " \"@type\": \"type.googleapis.com/envoy.extensions.filters.network"
+ ".http_connection_manager.v3.HttpConnectionManager\",\n"
+ " \"routeConfig\": {\n"
+ " \"name\": \"route-foo.googleapis.com\",\n"
+ " \"virtualHosts\": [{\n"
+ " \"name\": \"virtualhost00.googleapis.com\",\n"
+ " \"domains\": [\"foo.googleapis.com\", \"bar.googleapis.com\"],\n"
+ " \"routes\": [{\n"
+ " \"match\": {\n"
+ " \"prefix\": \"\"\n"
+ " },\n"
+ " \"route\": {\n"
+ " \"cluster\": \"cluster.googleapis.com\"\n"
+ " }\n"
+ " }]\n"
+ " }]\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.listener.v3.Listener\",\n"
+ " \"nonce\": \"0000\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
@Test
public void messagePrinter_printRdsResponse() {
MessagePrinter printer = new MessagePrinter();
List<Any> routeConfigs =
ImmutableList.of(
Any.pack(
buildRouteConfiguration(
"route-foo.googleapis.com",
ImmutableList.of(
buildVirtualHost(
ImmutableList.of("foo.googleapis.com", "bar.googleapis.com"),
"cluster.googleapis.com")))));
DiscoveryResponse response =
buildDiscoveryResponse("213", routeConfigs, ResourceType.RDS.typeUrl(), "0052");
String expectedString = "{\n"
+ " \"versionInfo\": \"213\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.route.v3.RouteConfiguration\",\n"
+ " \"name\": \"route-foo.googleapis.com\",\n"
+ " \"virtualHosts\": [{\n"
+ " \"name\": \"virtualhost00.googleapis.com\",\n"
+ " \"domains\": [\"foo.googleapis.com\", \"bar.googleapis.com\"],\n"
+ " \"routes\": [{\n"
+ " \"match\": {\n"
+ " \"prefix\": \"\"\n"
+ " },\n"
+ " \"route\": {\n"
+ " \"cluster\": \"cluster.googleapis.com\"\n"
+ " }\n"
+ " }]\n"
+ " }]\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.route.v3.RouteConfiguration\",\n"
+ " \"nonce\": \"0052\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
@Test
public void messagePrinter_printCdsResponse() {
MessagePrinter printer = new MessagePrinter();
List<Any> clusters = ImmutableList.of(
Any.pack(buildCluster("cluster-bar.googleapis.com", "service-blaze:cluster-bar", true)),
Any.pack(buildCluster("cluster-foo.googleapis.com", null, false)));
DiscoveryResponse response =
buildDiscoveryResponse("14", clusters, ResourceType.CDS.typeUrl(), "8");
String expectedString = "{\n"
+ " \"versionInfo\": \"14\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.cluster.v3.Cluster\",\n"
+ " \"name\": \"cluster-bar.googleapis.com\",\n"
+ " \"type\": \"EDS\",\n"
+ " \"edsClusterConfig\": {\n"
+ " \"edsConfig\": {\n"
+ " \"ads\": {\n"
+ " }\n"
+ " },\n"
+ " \"serviceName\": \"service-blaze:cluster-bar\"\n"
+ " },\n"
+ " \"lrsServer\": {\n"
+ " \"self\": {\n"
+ " }\n"
+ " }\n"
+ " }, {\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.cluster.v3.Cluster\",\n"
+ " \"name\": \"cluster-foo.googleapis.com\",\n"
+ " \"type\": \"EDS\",\n"
+ " \"edsClusterConfig\": {\n"
+ " \"edsConfig\": {\n"
+ " \"ads\": {\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.cluster.v3.Cluster\",\n"
+ " \"nonce\": \"8\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
@Test
public void messagePrinter_printEdsResponse() {
MessagePrinter printer = new MessagePrinter();
List<Any> clusterLoadAssignments = ImmutableList.of(
Any.pack(buildClusterLoadAssignment("cluster-foo.googleapis.com",
ImmutableList.of(
buildLocalityLbEndpoints("region1", "zone1", "subzone1",
ImmutableList.of(
buildLbEndpoint("192.168.0.1", 8080, HealthStatus.HEALTHY, 2)),
1, 0),
buildLocalityLbEndpoints("region3", "zone3", "subzone3",
ImmutableList.of(
buildLbEndpoint("192.168.142.5", 80, HealthStatus.UNHEALTHY, 5)),
2, 1)),
ImmutableList.of(
buildDropOverload("lb", 200),
buildDropOverload("throttle", 1000)))));
DiscoveryResponse response =
buildDiscoveryResponse("5", clusterLoadAssignments,
ResourceType.EDS.typeUrl(), "004");
String expectedString = "{\n"
+ " \"versionInfo\": \"5\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment\",\n"
+ " \"clusterName\": \"cluster-foo.googleapis.com\",\n"
+ " \"endpoints\": [{\n"
+ " \"locality\": {\n"
+ " \"region\": \"region1\",\n"
+ " \"zone\": \"zone1\",\n"
+ " \"subZone\": \"subzone1\"\n"
+ " },\n"
+ " \"lbEndpoints\": [{\n"
+ " \"endpoint\": {\n"
+ " \"address\": {\n"
+ " \"socketAddress\": {\n"
+ " \"address\": \"192.168.0.1\",\n"
+ " \"portValue\": 8080\n"
+ " }\n"
+ " }\n"
+ " },\n"
+ " \"healthStatus\": \"HEALTHY\",\n"
+ " \"loadBalancingWeight\": 2\n"
+ " }],\n"
+ " \"loadBalancingWeight\": 1\n"
+ " }, {\n"
+ " \"locality\": {\n"
+ " \"region\": \"region3\",\n"
+ " \"zone\": \"zone3\",\n"
+ " \"subZone\": \"subzone3\"\n"
+ " },\n"
+ " \"lbEndpoints\": [{\n"
+ " \"endpoint\": {\n"
+ " \"address\": {\n"
+ " \"socketAddress\": {\n"
+ " \"address\": \"192.168.142.5\",\n"
+ " \"portValue\": 80\n"
+ " }\n"
+ " }\n"
+ " },\n"
+ " \"healthStatus\": \"UNHEALTHY\",\n"
+ " \"loadBalancingWeight\": 5\n"
+ " }],\n"
+ " \"loadBalancingWeight\": 2,\n"
+ " \"priority\": 1\n"
+ " }],\n"
+ " \"policy\": {\n"
+ " \"dropOverloads\": [{\n"
+ " \"category\": \"lb\",\n"
+ " \"dropPercentage\": {\n"
+ " \"numerator\": 200,\n"
+ " \"denominator\": \"MILLION\"\n"
+ " }\n"
+ " }, {\n"
+ " \"category\": \"throttle\",\n"
+ " \"dropPercentage\": {\n"
+ " \"numerator\": 1000,\n"
+ " \"denominator\": \"MILLION\"\n"
+ " }\n"
+ " }]\n"
+ " }\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment\",\n"
+ " \"nonce\": \"004\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
}

View File

@ -0,0 +1,362 @@
/*
* Copyright 2020 The gRPC Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.xds;
import static com.google.common.truth.Truth.assertThat;
import com.google.protobuf.Any;
import com.google.protobuf.UInt32Value;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.cluster.v3.Cluster.EdsClusterConfig;
import io.envoyproxy.envoy.config.cluster.v3.Cluster.LbPolicy;
import io.envoyproxy.envoy.config.core.v3.Address;
import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource;
import io.envoyproxy.envoy.config.core.v3.ConfigSource;
import io.envoyproxy.envoy.config.core.v3.HealthStatus;
import io.envoyproxy.envoy.config.core.v3.Locality;
import io.envoyproxy.envoy.config.core.v3.SelfConfigSource;
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
import io.envoyproxy.envoy.config.core.v3.TransportSocket;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment.Policy;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment.Policy.DropOverload;
import io.envoyproxy.envoy.config.endpoint.v3.Endpoint;
import io.envoyproxy.envoy.config.endpoint.v3.LbEndpoint;
import io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints;
import io.envoyproxy.envoy.config.listener.v3.ApiListener;
import io.envoyproxy.envoy.config.listener.v3.Filter;
import io.envoyproxy.envoy.config.listener.v3.FilterChain;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.config.route.v3.Route;
import io.envoyproxy.envoy.config.route.v3.RouteAction;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.config.route.v3.RouteMatch;
import io.envoyproxy.envoy.config.route.v3.VirtualHost;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext;
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryResponse;
import io.envoyproxy.envoy.type.v3.FractionalPercent;
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Tests for {@link MessagePrinter}.
*/
@RunWith(JUnit4.class)
public class MessagePrinterTest {
private final MessagePrinter printer = new MessagePrinter();
@Test
public void printLdsResponse_v3() {
Listener listener =
Listener.newBuilder().setName("foo.googleapis.com:8080")
.setAddress(
Address.newBuilder()
.setSocketAddress(
SocketAddress.newBuilder().setAddress("10.0.0.1").setPortValue(8080)))
.addFilterChains(
FilterChain.newBuilder()
.addFilters(Filter.getDefaultInstance())
.setTransportSocket(
TransportSocket.newBuilder()
.setName("envoy.transport_sockets.tls")
.setTypedConfig(
Any.pack(
DownstreamTlsContext.newBuilder()
.setCommonTlsContext(
CommonTlsContext.newBuilder()
.addTlsCertificateSdsSecretConfigs(
SdsSecretConfig.getDefaultInstance()))
.build()))))
.setApiListener(
ApiListener.newBuilder()
.setApiListener(
Any.pack(HttpConnectionManager.newBuilder()
.setRds(
Rds.newBuilder()
.setRouteConfigName("route-foo.googleapis.com")
.setConfigSource(
ConfigSource.newBuilder().setAds(
AggregatedConfigSource.getDefaultInstance())))
.build())))
.build();
DiscoveryResponse response =
DiscoveryResponse.newBuilder()
.setTypeUrl("type.googleapis.com/envoy.config.listener.v3.Listener")
.setVersionInfo("0")
.addResources(Any.pack(listener))
.setNonce("0000")
.build();
String expectedString = "{\n"
+ " \"versionInfo\": \"0\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.listener.v3.Listener\",\n"
+ " \"name\": \"foo.googleapis.com:8080\",\n"
+ " \"address\": {\n"
+ " \"socketAddress\": {\n"
+ " \"address\": \"10.0.0.1\",\n"
+ " \"portValue\": 8080\n"
+ " }\n"
+ " },\n"
+ " \"filterChains\": [{\n"
+ " \"filters\": [{\n"
+ " }],\n"
+ " \"transportSocket\": {\n"
+ " \"name\": \"envoy.transport_sockets.tls\",\n"
+ " \"typedConfig\": {\n"
+ " \"@type\": \"type.googleapis.com/envoy.extensions.transport_sockets"
+ ".tls.v3.DownstreamTlsContext\",\n"
+ " \"commonTlsContext\": {\n"
+ " \"tlsCertificateSdsSecretConfigs\": [{\n"
+ " }]\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }],\n"
+ " \"apiListener\": {\n"
+ " \"apiListener\": {\n"
+ " \"@type\": \"type.googleapis.com/envoy.extensions.filters.network"
+ ".http_connection_manager.v3.HttpConnectionManager\",\n"
+ " \"rds\": {\n"
+ " \"configSource\": {\n"
+ " \"ads\": {\n"
+ " }\n"
+ " },\n"
+ " \"routeConfigName\": \"route-foo.googleapis.com\"\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.listener.v3.Listener\",\n"
+ " \"nonce\": \"0000\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
@Test
public void printRdsResponse_v3() {
RouteConfiguration routeConfiguration =
RouteConfiguration.newBuilder()
.setName("route-foo.googleapis.com")
.addVirtualHosts(
VirtualHost.newBuilder()
.setName("virtualhost.googleapis.com")
.addDomains("foo.googleapis.com")
.addDomains("bar.googleapis.com")
.addRoutes(
Route.newBuilder()
.setMatch(
RouteMatch.newBuilder().setPath("foo.googleapis.com"))
.setRoute(
RouteAction.newBuilder()
.setCluster("cluster.googleapis.com"))))
.build();
DiscoveryResponse response =
DiscoveryResponse.newBuilder()
.setTypeUrl("type.googleapis.com/envoy.config.route.v3.RouteConfiguration")
.setVersionInfo("0")
.addResources(Any.pack(routeConfiguration))
.setNonce("0000")
.build();
String expectedString = "{\n"
+ " \"versionInfo\": \"0\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.route.v3.RouteConfiguration\",\n"
+ " \"name\": \"route-foo.googleapis.com\",\n"
+ " \"virtualHosts\": [{\n"
+ " \"name\": \"virtualhost.googleapis.com\",\n"
+ " \"domains\": [\"foo.googleapis.com\", \"bar.googleapis.com\"],\n"
+ " \"routes\": [{\n"
+ " \"match\": {\n"
+ " \"path\": \"foo.googleapis.com\"\n"
+ " },\n"
+ " \"route\": {\n"
+ " \"cluster\": \"cluster.googleapis.com\"\n"
+ " }\n"
+ " }]\n"
+ " }]\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.route.v3.RouteConfiguration\",\n"
+ " \"nonce\": \"0000\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
@Test
public void printCdsResponse_v3() {
Cluster cluster =
Cluster.newBuilder()
.setName("cluster-foo.googleapis.com")
.setEdsClusterConfig(
EdsClusterConfig.newBuilder()
.setServiceName("backend-service-foo.googleapis.com")
.setEdsConfig(
ConfigSource.newBuilder()
.setAds(AggregatedConfigSource.getDefaultInstance())))
.setLrsServer(ConfigSource.newBuilder().setSelf(SelfConfigSource.getDefaultInstance()))
.setLbPolicy(LbPolicy.ROUND_ROBIN)
.setTransportSocket(
TransportSocket.newBuilder()
.setTypedConfig(
Any.pack(
UpstreamTlsContext.newBuilder()
.setCommonTlsContext(
CommonTlsContext.newBuilder()
.addTlsCertificateSdsSecretConfigs(
SdsSecretConfig.getDefaultInstance())).build())))
.build();
DiscoveryResponse response =
DiscoveryResponse.newBuilder()
.setTypeUrl("type.googleapis.com/envoy.config.cluster.v3.Cluster")
.setVersionInfo("0")
.addResources(Any.pack(cluster))
.setNonce("0000")
.build();
String expectedString = "{\n"
+ " \"versionInfo\": \"0\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.cluster.v3.Cluster\",\n"
+ " \"name\": \"cluster-foo.googleapis.com\",\n"
+ " \"edsClusterConfig\": {\n"
+ " \"edsConfig\": {\n"
+ " \"ads\": {\n"
+ " }\n"
+ " },\n"
+ " \"serviceName\": \"backend-service-foo.googleapis.com\"\n"
+ " },\n"
+ " \"transportSocket\": {\n"
+ " \"typedConfig\": {\n"
+ " \"@type\": \"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3"
+ ".UpstreamTlsContext\",\n"
+ " \"commonTlsContext\": {\n"
+ " \"tlsCertificateSdsSecretConfigs\": [{\n"
+ " }]\n"
+ " }\n"
+ " }\n"
+ " },\n"
+ " \"lrsServer\": {\n"
+ " \"self\": {\n"
+ " }\n"
+ " }\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.cluster.v3.Cluster\",\n"
+ " \"nonce\": \"0000\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
@Test
public void printEdsResponse_v3() {
ClusterLoadAssignment clusterLoadAssignment =
ClusterLoadAssignment.newBuilder()
.setClusterName("cluster-foo.googleapis.com")
.setPolicy(
Policy.newBuilder()
.addDropOverloads(
DropOverload.newBuilder()
.setCategory("throttle")
.setDropPercentage(
FractionalPercent.newBuilder()
.setNumerator(80)
.setDenominator(DenominatorType.HUNDRED))))
.addEndpoints(
LocalityLbEndpoints.newBuilder()
.setLocality(
Locality.newBuilder()
.setRegion("region")
.setZone("zone")
.setSubZone("subzone")).setPriority(1)
.setLoadBalancingWeight(UInt32Value.newBuilder().setValue(20))
.addLbEndpoints(
LbEndpoint.newBuilder()
.setLoadBalancingWeight(UInt32Value.newBuilder().setValue(100))
.setHealthStatus(HealthStatus.UNHEALTHY)
.setEndpoint(
Endpoint.newBuilder()
.setAddress(
Address.newBuilder()
.setSocketAddress(
SocketAddress.newBuilder()
.setAddress("10.0.0.1")
.setPortValue(8001))))))
.build();
DiscoveryResponse response =
DiscoveryResponse.newBuilder()
.setTypeUrl("type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment")
.setVersionInfo("0")
.addResources(Any.pack(clusterLoadAssignment))
.setNonce("0000")
.build();
String expectedString = "{\n"
+ " \"versionInfo\": \"0\",\n"
+ " \"resources\": [{\n"
+ " \"@type\": \"type.googleapis.com/envoy.config.endpoint.v3"
+ ".ClusterLoadAssignment\",\n"
+ " \"clusterName\": \"cluster-foo.googleapis.com\",\n"
+ " \"endpoints\": [{\n"
+ " \"locality\": {\n"
+ " \"region\": \"region\",\n"
+ " \"zone\": \"zone\",\n"
+ " \"subZone\": \"subzone\"\n"
+ " },\n"
+ " \"lbEndpoints\": [{\n"
+ " \"endpoint\": {\n"
+ " \"address\": {\n"
+ " \"socketAddress\": {\n"
+ " \"address\": \"10.0.0.1\",\n"
+ " \"portValue\": 8001\n"
+ " }\n"
+ " }\n"
+ " },\n"
+ " \"healthStatus\": \"UNHEALTHY\",\n"
+ " \"loadBalancingWeight\": 100\n"
+ " }],\n"
+ " \"loadBalancingWeight\": 20,\n"
+ " \"priority\": 1\n"
+ " }],\n"
+ " \"policy\": {\n"
+ " \"dropOverloads\": [{\n"
+ " \"category\": \"throttle\",\n"
+ " \"dropPercentage\": {\n"
+ " \"numerator\": 80\n"
+ " }\n"
+ " }]\n"
+ " }\n"
+ " }],\n"
+ " \"typeUrl\": \"type.googleapis.com/envoy.config.endpoint.v3"
+ ".ClusterLoadAssignment\",\n"
+ " \"nonce\": \"0000\"\n"
+ "}";
String res = printer.print(response);
assertThat(res).isEqualTo(expectedString);
}
}

View File

@ -16,27 +16,8 @@
package io.grpc.xds;
import com.google.common.collect.ImmutableList;
import com.google.protobuf.Any;
import com.google.protobuf.UInt32Value;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.cluster.v3.Cluster.DiscoveryType;
import io.envoyproxy.envoy.config.cluster.v3.Cluster.EdsClusterConfig;
import io.envoyproxy.envoy.config.cluster.v3.Cluster.LbPolicy;
import io.envoyproxy.envoy.config.core.v3.Address;
import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource;
import io.envoyproxy.envoy.config.core.v3.ConfigSource;
import io.envoyproxy.envoy.config.core.v3.HealthStatus;
import io.envoyproxy.envoy.config.core.v3.Locality;
import io.envoyproxy.envoy.config.core.v3.SelfConfigSource;
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
import io.envoyproxy.envoy.config.core.v3.TransportSocket;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment.Policy;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment.Policy.DropOverload;
import io.envoyproxy.envoy.config.endpoint.v3.Endpoint;
import io.envoyproxy.envoy.config.endpoint.v3.LbEndpoint;
import io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints;
import io.envoyproxy.envoy.config.listener.v3.ApiListener;
import io.envoyproxy.envoy.config.listener.v3.FilterChain;
import io.envoyproxy.envoy.config.listener.v3.Listener;
@ -45,14 +26,10 @@ import io.envoyproxy.envoy.config.route.v3.RouteAction;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.config.route.v3.RouteMatch;
import io.envoyproxy.envoy.config.route.v3.VirtualHost;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext;
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryRequest;
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryResponse;
import io.envoyproxy.envoy.type.v3.FractionalPercent;
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
import io.grpc.xds.EnvoyProtoData.Node;
import java.util.List;
import javax.annotation.Nullable;
/**
* Helper methods for building protobuf messages with custom data for xDS protocols.
@ -93,24 +70,6 @@ class XdsClientTestHelper {
.build();
}
static io.envoyproxy.envoy.api.v2.DiscoveryRequest buildDiscoveryRequestV2(
Node node, String versionInfo, String resourceName, String typeUrl, String nonce) {
return buildDiscoveryRequestV2(
node, versionInfo, ImmutableList.of(resourceName), typeUrl, nonce);
}
static io.envoyproxy.envoy.api.v2.DiscoveryRequest buildDiscoveryRequestV2(
Node node, String versionInfo, List<String> resourceNames, String typeUrl, String nonce) {
return
io.envoyproxy.envoy.api.v2.DiscoveryRequest.newBuilder()
.setVersionInfo(versionInfo)
.setNode(node.toEnvoyProtoNodeV2())
.setTypeUrl(typeUrl)
.addAllResourceNames(resourceNames)
.setResponseNonce(nonce)
.build();
}
static Listener buildListener(String name, com.google.protobuf.Any apiListener) {
return
Listener.newBuilder()
@ -175,170 +134,4 @@ class XdsClientTestHelper {
.setMatch(io.envoyproxy.envoy.api.v2.route.RouteMatch.newBuilder().setPrefix("")))
.build();
}
static Cluster buildCluster(String clusterName, @Nullable String edsServiceName,
boolean enableLrs) {
return buildSecureCluster(clusterName, edsServiceName, enableLrs, null);
}
static io.envoyproxy.envoy.api.v2.Cluster buildClusterV2(
String clusterName, @Nullable String edsServiceName, boolean enableLrs) {
return buildSecureClusterV2(clusterName, edsServiceName, enableLrs, null);
}
static Cluster buildSecureCluster(
String clusterName, @Nullable String edsServiceName, boolean enableLrs,
@Nullable UpstreamTlsContext upstreamTlsContext) {
Cluster.Builder clusterBuilder = Cluster.newBuilder();
clusterBuilder.setName(clusterName);
clusterBuilder.setType(DiscoveryType.EDS);
EdsClusterConfig.Builder edsClusterConfigBuilder = EdsClusterConfig.newBuilder();
edsClusterConfigBuilder.setEdsConfig(
ConfigSource.newBuilder()
.setAds(AggregatedConfigSource.getDefaultInstance()));
if (edsServiceName != null) {
edsClusterConfigBuilder.setServiceName(edsServiceName);
}
clusterBuilder.setEdsClusterConfig(edsClusterConfigBuilder);
clusterBuilder.setLbPolicy(LbPolicy.ROUND_ROBIN);
if (enableLrs) {
clusterBuilder.setLrsServer(
ConfigSource.newBuilder()
.setSelf(SelfConfigSource.getDefaultInstance()));
}
if (upstreamTlsContext != null) {
clusterBuilder.setTransportSocket(
TransportSocket.newBuilder()
.setName("envoy.transport_sockets.tls")
.setTypedConfig(Any.pack(upstreamTlsContext)));
}
return clusterBuilder.build();
}
static io.envoyproxy.envoy.api.v2.Cluster buildSecureClusterV2(
String clusterName, @Nullable String edsServiceName, boolean enableLrs,
@Nullable io.envoyproxy.envoy.api.v2.auth.UpstreamTlsContext upstreamTlsContext) {
io.envoyproxy.envoy.api.v2.Cluster.Builder clusterBuilder =
io.envoyproxy.envoy.api.v2.Cluster.newBuilder()
.setName(clusterName)
.setType(io.envoyproxy.envoy.api.v2.Cluster.DiscoveryType.EDS);
io.envoyproxy.envoy.api.v2.Cluster.EdsClusterConfig.Builder edsClusterConfigBuilder =
io.envoyproxy.envoy.api.v2.Cluster.EdsClusterConfig.newBuilder()
.setEdsConfig(
io.envoyproxy.envoy.api.v2.core.ConfigSource.newBuilder().setAds(
io.envoyproxy.envoy.api.v2.core.AggregatedConfigSource.getDefaultInstance()));
if (edsServiceName != null) {
edsClusterConfigBuilder.setServiceName(edsServiceName);
}
clusterBuilder
.setEdsClusterConfig(edsClusterConfigBuilder)
.setLbPolicy(io.envoyproxy.envoy.api.v2.Cluster.LbPolicy.ROUND_ROBIN);
if (enableLrs) {
clusterBuilder.setLrsServer(
io.envoyproxy.envoy.api.v2.core.ConfigSource.newBuilder()
.setSelf(io.envoyproxy.envoy.api.v2.core.SelfConfigSource.getDefaultInstance()));
}
if (upstreamTlsContext != null) {
clusterBuilder.setTransportSocket(
io.envoyproxy.envoy.api.v2.core.TransportSocket.newBuilder()
.setName("envoy.transport_sockets.tls").setTypedConfig(Any.pack(upstreamTlsContext)));
}
return clusterBuilder.build();
}
static ClusterLoadAssignment buildClusterLoadAssignment(String clusterName,
List<LocalityLbEndpoints> localityLbEndpoints, List<DropOverload> dropOverloads) {
return
ClusterLoadAssignment.newBuilder()
.setClusterName(clusterName)
.addAllEndpoints(localityLbEndpoints)
.setPolicy(Policy.newBuilder().addAllDropOverloads(dropOverloads))
.build();
}
static DropOverload buildDropOverload(String category, int dropPerMillion) {
return
DropOverload.newBuilder()
.setCategory(category)
.setDropPercentage(
FractionalPercent.newBuilder()
.setNumerator(dropPerMillion)
.setDenominator(DenominatorType.MILLION))
.build();
}
static io.envoyproxy.envoy.api.v2.ClusterLoadAssignment.Policy.DropOverload buildDropOverloadV2(
String category, int dropPerMillion) {
return
io.envoyproxy.envoy.api.v2.ClusterLoadAssignment.Policy.DropOverload.newBuilder()
.setCategory(category)
.setDropPercentage(
io.envoyproxy.envoy.type.FractionalPercent.newBuilder()
.setNumerator(dropPerMillion)
.setDenominator(
io.envoyproxy.envoy.type.FractionalPercent.DenominatorType.MILLION))
.build();
}
static LocalityLbEndpoints buildLocalityLbEndpoints(
String region, String zone, String subZone, List<LbEndpoint> lbEndpoints,
int loadBalancingWeight, int priority) {
return
LocalityLbEndpoints.newBuilder()
.setLocality(
Locality.newBuilder()
.setRegion(region)
.setZone(zone)
.setSubZone(subZone))
.addAllLbEndpoints(lbEndpoints)
.setLoadBalancingWeight(UInt32Value.of(loadBalancingWeight))
.setPriority(priority)
.build();
}
static io.envoyproxy.envoy.api.v2.endpoint.LocalityLbEndpoints buildLocalityLbEndpointsV2(
String region, String zone, String subZone,
List<io.envoyproxy.envoy.api.v2.endpoint.LbEndpoint> lbEndpoints,
int loadBalancingWeight, int priority) {
return
io.envoyproxy.envoy.api.v2.endpoint.LocalityLbEndpoints.newBuilder()
.setLocality(
io.envoyproxy.envoy.api.v2.core.Locality.newBuilder()
.setRegion(region)
.setZone(zone)
.setSubZone(subZone))
.addAllLbEndpoints(lbEndpoints)
.setLoadBalancingWeight(UInt32Value.of(loadBalancingWeight))
.setPriority(priority)
.build();
}
static LbEndpoint buildLbEndpoint(
String address, int port, HealthStatus healthStatus, int loadbalancingWeight) {
return
LbEndpoint.newBuilder()
.setEndpoint(
Endpoint.newBuilder().setAddress(
Address.newBuilder().setSocketAddress(
SocketAddress.newBuilder().setAddress(address).setPortValue(port))))
.setHealthStatus(healthStatus)
.setLoadBalancingWeight(UInt32Value.of(loadbalancingWeight))
.build();
}
static io.envoyproxy.envoy.api.v2.endpoint.LbEndpoint buildLbEndpointV2(
String address, int port, io.envoyproxy.envoy.api.v2.core.HealthStatus healthStatus,
int loadbalancingWeight) {
return
io.envoyproxy.envoy.api.v2.endpoint.LbEndpoint.newBuilder()
.setEndpoint(
io.envoyproxy.envoy.api.v2.endpoint.Endpoint.newBuilder().setAddress(
io.envoyproxy.envoy.api.v2.core.Address.newBuilder().setSocketAddress(
io.envoyproxy.envoy.api.v2.core.SocketAddress.newBuilder()
.setAddress(address)
.setPortValue(port))))
.setHealthStatus(healthStatus)
.setLoadBalancingWeight(UInt32Value.of(loadbalancingWeight))
.build();
}
}