rls: migrate deprecated server/path to extraKeys (#8469)

The [`server` and `path` fields](https://github.com/grpc/grpc-java/blob/v1.40.1/rls/src/main/proto/grpc/lookup/v1/rls.proto#L25-L32) in `RouteLookupRequest` are deprecated. Instead, we will send the server/path information in side of [`key_map`](https://github.com/grpc/grpc-java/blob/v1.40.1/rls/src/main/proto/grpc/lookup/v1/rls.proto#L45).

The keys for the server, service and method in the `key_map` will be the _values_ of `host`, `service`, `method` fields respectively in [`extraKeys`](https://github.com/grpc/grpc-java/blob/v1.40.1/rls/src/main/proto/grpc/lookup/v1/rls_config.proto#L69) in RlsConfig.

We will also include all entries in the [`constantKey`](https://github.com/grpc/grpc-java/blob/v1.40.1/rls/src/main/proto/grpc/lookup/v1/rls_config.proto#L80) in RlsConfig into `RouteLookupRequest`.


Other changes:

- Add AutoValue library for ExtraKeys class, just like data classes used in grpc-xds. Will migrate other data classes to AutoValue as well.
- Not to keep `targetType` field in the route lookup request data class, because we always use "grpc" as targetType.
This commit is contained in:
ZHANG Dapeng 2021-09-07 21:32:33 -07:00 committed by GitHub
parent 5dc6e0ca54
commit cd346832ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 217 additions and 153 deletions

View File

@ -16,6 +16,8 @@ IO_GRPC_GRPC_JAVA_ARTIFACTS = [
"com.google.auth:google-auth-library-oauth2-http:0.22.0", "com.google.auth:google-auth-library-oauth2-http:0.22.0",
"com.google.code.findbugs:jsr305:3.0.2", "com.google.code.findbugs:jsr305:3.0.2",
"com.google.code.gson:gson:jar:2.8.6", "com.google.code.gson:gson:jar:2.8.6",
"com.google.auto.value:auto-value:1.7.4",
"com.google.auto.value:auto-value-annotations:1.7.4",
"com.google.errorprone:error_prone_annotations:2.9.0", "com.google.errorprone:error_prone_annotations:2.9.0",
"com.google.guava:failureaccess:1.0.1", "com.google.guava:failureaccess:1.0.1",
"com.google.guava:guava:30.1-android", "com.google.guava:guava:30.1-android",

View File

@ -7,12 +7,14 @@ java_library(
]), ]),
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":autovalue",
":rls_java_grpc", ":rls_java_grpc",
"//api", "//api",
"//core", "//core",
"//core:internal", "//core:internal",
"//core:util", "//core:util",
"//stub", "//stub",
"@com_google_auto_value_auto_value_annotations//jar",
"@com_google_code_findbugs_jsr305//jar", "@com_google_code_findbugs_jsr305//jar",
"@com_google_guava_guava//jar", "@com_google_guava_guava//jar",
"@io_grpc_grpc_proto//:rls_java_proto", "@io_grpc_grpc_proto//:rls_java_proto",
@ -20,6 +22,25 @@ java_library(
], ],
) )
java_plugin(
name = "autovalue_plugin",
processor_class = "com.google.auto.value.processor.AutoValueProcessor",
deps = [
"@com_google_auto_value_auto_value//jar",
],
)
java_library(
name = "autovalue",
exported_plugins = [
":autovalue_plugin",
],
neverlink = 1,
exports = [
"@com_google_auto_value_auto_value//jar",
],
)
java_grpc_library( java_grpc_library(
name = "rls_java_grpc", name = "rls_java_grpc",
srcs = ["@io_grpc_grpc_proto//:rls_proto"], srcs = ["@io_grpc_grpc_proto//:rls_proto"],

View File

@ -14,7 +14,9 @@ dependencies {
implementation project(':grpc-core'), implementation project(':grpc-core'),
project(':grpc-protobuf'), project(':grpc-protobuf'),
project(':grpc-stub'), project(':grpc-stub'),
libraries.autovalue_annotation,
libraries.guava libraries.guava
annotationProcessor libraries.autovalue
compileOnly libraries.javax_annotation compileOnly libraries.javax_annotation
testImplementation libraries.truth, testImplementation libraries.truth,
project(':grpc-grpclb'), project(':grpc-grpclb'),
@ -24,6 +26,17 @@ dependencies {
signature "org.codehaus.mojo.signature:java17:1.0@signature" signature "org.codehaus.mojo.signature:java17:1.0@signature"
} }
[compileJava].each() {
it.options.compilerArgs += [
// only has AutoValue annotation processor
"-Xlint:-processing",
]
appendToProperty(
it.options.errorprone.excludedPaths,
".*/build/generated/sources/annotationProcessor/java/.*",
"|")
}
javadoc { javadoc {
// Do not publish javadoc since currently there is no public API. // Do not publish javadoc since currently there is no public API.
failOnError false // no public or protected classes found to document failOnError false // no public or protected classes found to document

View File

@ -20,9 +20,11 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Converter; import com.google.common.base.Converter;
import com.google.common.collect.ImmutableMap;
import io.grpc.internal.JsonUtil; import io.grpc.internal.JsonUtil;
import io.grpc.lookup.v1.RouteLookupRequest; import io.grpc.lookup.v1.RouteLookupRequest;
import io.grpc.lookup.v1.RouteLookupResponse; import io.grpc.lookup.v1.RouteLookupResponse;
import io.grpc.rls.RlsProtoData.ExtraKeys;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name;
import io.grpc.rls.RlsProtoData.NameMatcher; import io.grpc.rls.RlsProtoData.NameMatcher;
@ -46,25 +48,16 @@ final class RlsProtoConverters {
static final class RouteLookupRequestConverter static final class RouteLookupRequestConverter
extends Converter<RouteLookupRequest, RlsProtoData.RouteLookupRequest> { extends Converter<RouteLookupRequest, RlsProtoData.RouteLookupRequest> {
@SuppressWarnings("deprecation")
@Override @Override
protected RlsProtoData.RouteLookupRequest doForward(RouteLookupRequest routeLookupRequest) { protected RlsProtoData.RouteLookupRequest doForward(RouteLookupRequest routeLookupRequest) {
return return new RlsProtoData.RouteLookupRequest(routeLookupRequest.getKeyMapMap());
new RlsProtoData.RouteLookupRequest(
/* server= */ routeLookupRequest.getServer(),
/* path= */ routeLookupRequest.getPath(),
/* targetType= */ routeLookupRequest.getTargetType(),
routeLookupRequest.getKeyMapMap());
} }
@SuppressWarnings("deprecation")
@Override @Override
protected RouteLookupRequest doBackward(RlsProtoData.RouteLookupRequest routeLookupRequest) { protected RouteLookupRequest doBackward(RlsProtoData.RouteLookupRequest routeLookupRequest) {
return return
RouteLookupRequest.newBuilder() RouteLookupRequest.newBuilder()
.setServer(routeLookupRequest.getServer()) .setTargetType("grpc")
.setPath(routeLookupRequest.getPath())
.setTargetType(routeLookupRequest.getTargetType())
.putAllKeyMap(routeLookupRequest.getKeyMap()) .putAllKeyMap(routeLookupRequest.getKeyMap())
.build(); .build();
} }
@ -183,7 +176,19 @@ final class RlsProtoConverters {
matcher.isOptional(), "NameMatcher for GrpcKeyBuilders shouldn't be required"); matcher.isOptional(), "NameMatcher for GrpcKeyBuilders shouldn't be required");
nameMatchers.add(matcher); nameMatchers.add(matcher);
} }
return new GrpcKeyBuilder(names, nameMatchers); ExtraKeys extraKeys = ExtraKeys.DEFAULT;
Map<String, String> rawExtraKeys =
(Map<String, String>) JsonUtil.getObject(keyBuilder, "extraKeys");
if (rawExtraKeys != null) {
extraKeys = ExtraKeys.create(
rawExtraKeys.get("host"), rawExtraKeys.get("service"), rawExtraKeys.get("method"));
}
Map<String, String> constantKeys =
(Map<String, String>) JsonUtil.getObject(keyBuilder, "constantKeys");
if (constantKeys == null) {
constantKeys = ImmutableMap.of();
}
return new GrpcKeyBuilder(names, nameMatchers, extraKeys, constantKeys);
} }
} }

View File

@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import com.google.auto.value.AutoValue;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -40,46 +41,12 @@ final class RlsProtoData {
@Immutable @Immutable
static final class RouteLookupRequest { static final class RouteLookupRequest {
private final String server;
private final String path;
private final String targetType;
private final ImmutableMap<String, String> keyMap; private final ImmutableMap<String, String> keyMap;
RouteLookupRequest( RouteLookupRequest(Map<String, String> keyMap) {
String server, String path, String targetType, Map<String, String> keyMap) {
this.server = checkNotNull(server, "server");
this.path = checkNotNull(path, "path");
this.targetType = checkNotNull(targetType, "targetName");
this.keyMap = ImmutableMap.copyOf(checkNotNull(keyMap, "keyMap")); this.keyMap = ImmutableMap.copyOf(checkNotNull(keyMap, "keyMap"));
} }
/**
* Returns a full host name of the target server, {@literal e.g.} firestore.googleapis.com. Only
* set for gRPC requests; HTTP requests must use key_map explicitly.
*/
String getServer() {
return server;
}
/**
* Returns a full path of the request, {@literal i.e.} "/service/method". Only set for gRPC
* requests; HTTP requests must use key_map explicitly.
*/
String getPath() {
return path;
}
/**
* Returns the target type allows the client to specify what kind of target format it would like
* from RLS to allow it to find the regional server, {@literal e.g.} "grpc".
*/
String getTargetType() {
return targetType;
}
/** Returns a map of key values extracted via key builders for the gRPC or HTTP request. */ /** Returns a map of key values extracted via key builders for the gRPC or HTTP request. */
ImmutableMap<String, String> getKeyMap() { ImmutableMap<String, String> getKeyMap() {
return keyMap; return keyMap;
@ -94,23 +61,17 @@ final class RlsProtoData {
return false; return false;
} }
RouteLookupRequest that = (RouteLookupRequest) o; RouteLookupRequest that = (RouteLookupRequest) o;
return Objects.equal(server, that.server) return Objects.equal(keyMap, that.keyMap);
&& Objects.equal(path, that.path)
&& Objects.equal(targetType, that.targetType)
&& Objects.equal(keyMap, that.keyMap);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(server, path, targetType, keyMap); return Objects.hashCode(keyMap);
} }
@Override @Override
public String toString() { public String toString() {
return MoreObjects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("server", server)
.add("path", path)
.add("targetName", targetType)
.add("keyMap", keyMap) .add("keyMap", keyMap)
.toString(); .toString();
} }
@ -300,6 +261,7 @@ final class RlsProtoData {
* error. Note that requests can be routed only to a subdomain of the original target, * error. Note that requests can be routed only to a subdomain of the original target,
* {@literal e.g.} "us_east_1.cloudbigtable.googleapis.com". * {@literal e.g.} "us_east_1.cloudbigtable.googleapis.com".
*/ */
@Nullable
String getDefaultTarget() { String getDefaultTarget() {
return defaultTarget; return defaultTarget;
} }
@ -431,12 +393,18 @@ final class RlsProtoData {
private final ImmutableList<Name> names; private final ImmutableList<Name> names;
private final ImmutableList<NameMatcher> headers; private final ImmutableList<NameMatcher> headers;
private final ExtraKeys extraKeys;
private final ImmutableMap<String, String> constantKeys;
public GrpcKeyBuilder(List<Name> names, List<NameMatcher> headers) { public GrpcKeyBuilder(
List<Name> names, List<NameMatcher> headers, ExtraKeys extraKeys,
Map<String, String> constantKeys) {
checkState(names != null && !names.isEmpty(), "names cannot be empty"); checkState(names != null && !names.isEmpty(), "names cannot be empty");
this.names = ImmutableList.copyOf(names); this.names = ImmutableList.copyOf(names);
checkUniqueKey(checkNotNull(headers, "headers")); checkUniqueKey(checkNotNull(headers, "headers"));
this.headers = ImmutableList.copyOf(headers); this.headers = ImmutableList.copyOf(headers);
this.extraKeys = checkNotNull(extraKeys, "extraKeys");
this.constantKeys = ImmutableMap.copyOf(checkNotNull(constantKeys, "constantKeys"));
} }
private static void checkUniqueKey(List<NameMatcher> headers) { private static void checkUniqueKey(List<NameMatcher> headers) {
@ -464,6 +432,14 @@ final class RlsProtoData {
return headers; return headers;
} }
ExtraKeys getExtraKeys() {
return extraKeys;
}
ImmutableMap<String, String> getConstantKeys() {
return constantKeys;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {
@ -473,12 +449,14 @@ final class RlsProtoData {
return false; return false;
} }
GrpcKeyBuilder that = (GrpcKeyBuilder) o; GrpcKeyBuilder that = (GrpcKeyBuilder) o;
return Objects.equal(names, that.names) && Objects.equal(headers, that.headers); return Objects.equal(names, that.names) && Objects.equal(headers, that.headers)
&& Objects.equal(extraKeys, that.extraKeys)
&& Objects.equal(constantKeys, that.constantKeys);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(names, headers); return Objects.hashCode(names, headers, extraKeys, constantKeys);
} }
@Override @Override
@ -486,6 +464,8 @@ final class RlsProtoData {
return MoreObjects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("names", names) .add("names", names)
.add("headers", headers) .add("headers", headers)
.add("extraKeys", extraKeys)
.add("constantKeys", constantKeys)
.toString(); .toString();
} }
@ -548,4 +528,20 @@ final class RlsProtoData {
} }
} }
} }
@AutoValue
abstract static class ExtraKeys {
static final ExtraKeys DEFAULT = create(null, null, null);
@Nullable abstract String host();
@Nullable abstract String service();
@Nullable abstract String method();
static ExtraKeys create(
@Nullable String host, @Nullable String service, @Nullable String method) {
return new AutoValue_RlsProtoData_ExtraKeys(host, service, method);
}
}
} }

View File

@ -19,17 +19,18 @@ package io.grpc.rls;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Table;
import io.grpc.Metadata; import io.grpc.Metadata;
import io.grpc.Status; import io.grpc.Status;
import io.grpc.StatusRuntimeException; import io.grpc.StatusRuntimeException;
import io.grpc.rls.RlsProtoData.ExtraKeys;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name;
import io.grpc.rls.RlsProtoData.NameMatcher; import io.grpc.rls.RlsProtoData.NameMatcher;
import io.grpc.rls.RlsProtoData.RouteLookupConfig; import io.grpc.rls.RlsProtoData.RouteLookupConfig;
import io.grpc.rls.RlsProtoData.RouteLookupRequest; import io.grpc.rls.RlsProtoData.RouteLookupRequest;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.CheckReturnValue; import javax.annotation.CheckReturnValue;
@ -40,10 +41,7 @@ import javax.annotation.CheckReturnValue;
final class RlsRequestFactory { final class RlsRequestFactory {
private final String target; private final String target;
/** private final Map<String, GrpcKeyBuilder> keyBuilderTable;
* schema: Path(/serviceName/methodName or /serviceName/*), rls request headerName, header fields.
*/
private final Table<String, String, NameMatcher> keyBuilderTable;
RlsRequestFactory(RouteLookupConfig rlsConfig, String target) { RlsRequestFactory(RouteLookupConfig rlsConfig, String target) {
checkNotNull(rlsConfig, "rlsConfig"); checkNotNull(rlsConfig, "rlsConfig");
@ -51,18 +49,15 @@ final class RlsRequestFactory {
this.keyBuilderTable = createKeyBuilderTable(rlsConfig); this.keyBuilderTable = createKeyBuilderTable(rlsConfig);
} }
private static Table<String, String, NameMatcher> createKeyBuilderTable( private static Map<String, GrpcKeyBuilder> createKeyBuilderTable(
RouteLookupConfig config) { RouteLookupConfig config) {
Table<String, String, NameMatcher> table = HashBasedTable.create(); Map<String, GrpcKeyBuilder> table = new HashMap<>();
for (GrpcKeyBuilder grpcKeyBuilder : config.getGrpcKeyBuilders()) { for (GrpcKeyBuilder grpcKeyBuilder : config.getGrpcKeyBuilders()) {
for (NameMatcher nameMatcher : grpcKeyBuilder.getHeaders()) { for (Name name : grpcKeyBuilder.getNames()) {
for (Name name : grpcKeyBuilder.getNames()) { boolean hasMethod = name.getMethod() == null || name.getMethod().isEmpty();
String method = String method = hasMethod ? "*" : name.getMethod();
name.getMethod() == null || name.getMethod().isEmpty() String path = "/" + name.getService() + "/" + method;
? "*" : name.getMethod(); table.put(path, grpcKeyBuilder);
String path = "/" + name.getService() + "/" + method;
table.put(path, nameMatcher.getKey(), nameMatcher);
}
} }
} }
return table; return table;
@ -74,20 +69,35 @@ final class RlsRequestFactory {
checkNotNull(service, "service"); checkNotNull(service, "service");
checkNotNull(method, "method"); checkNotNull(method, "method");
String path = "/" + service + "/" + method; String path = "/" + service + "/" + method;
Map<String, NameMatcher> keyBuilder = keyBuilderTable.row(path); GrpcKeyBuilder grpcKeyBuilder = keyBuilderTable.get(path);
// if no matching keyBuilder found, fall back to wildcard match (ServiceName/*) if (grpcKeyBuilder == null) {
if (keyBuilder.isEmpty()) { // if no matching keyBuilder found, fall back to wildcard match (ServiceName/*)
keyBuilder = keyBuilderTable.row("/" + service + "/*"); grpcKeyBuilder = keyBuilderTable.get("/" + service + "/*");
} }
Map<String, String> rlsRequestHeaders = createRequestHeaders(metadata, keyBuilder); if (grpcKeyBuilder == null) {
return new RouteLookupRequest(target, path, "grpc", rlsRequestHeaders); return new RouteLookupRequest(ImmutableMap.<String, String>of());
}
Map<String, String> rlsRequestHeaders =
createRequestHeaders(metadata, grpcKeyBuilder.getHeaders());
ExtraKeys extraKeys = grpcKeyBuilder.getExtraKeys();
Map<String, String> constantKeys = grpcKeyBuilder.getConstantKeys();
if (extraKeys.host() != null) {
rlsRequestHeaders.put(extraKeys.host(), target);
}
if (extraKeys.service() != null) {
rlsRequestHeaders.put(extraKeys.service(), service);
}
if (extraKeys.method() != null) {
rlsRequestHeaders.put(extraKeys.method(), method);
}
rlsRequestHeaders.putAll(constantKeys);
return new RouteLookupRequest(rlsRequestHeaders);
} }
private Map<String, String> createRequestHeaders( private Map<String, String> createRequestHeaders(
Metadata metadata, Map<String, NameMatcher> keyBuilder) { Metadata metadata, List<NameMatcher> keyBuilder) {
Map<String, String> rlsRequestHeaders = new HashMap<>(); Map<String, String> rlsRequestHeaders = new HashMap<>();
for (Map.Entry<String, NameMatcher> entry : keyBuilder.entrySet()) { for (NameMatcher nameMatcher : keyBuilder) {
NameMatcher nameMatcher = entry.getValue();
String value = null; String value = null;
for (String requestHeaderName : nameMatcher.names()) { for (String requestHeaderName : nameMatcher.names()) {
value = metadata.get(Metadata.Key.of(requestHeaderName, Metadata.ASCII_STRING_MARSHALLER)); value = metadata.get(Metadata.Key.of(requestHeaderName, Metadata.ASCII_STRING_MARSHALLER));
@ -96,11 +106,11 @@ final class RlsRequestFactory {
} }
} }
if (value != null) { if (value != null) {
rlsRequestHeaders.put(entry.getKey(), value); rlsRequestHeaders.put(nameMatcher.getKey(), value);
} else if (!nameMatcher.isOptional()) { } else if (!nameMatcher.isOptional()) {
throw new StatusRuntimeException( throw new StatusRuntimeException(
Status.INVALID_ARGUMENT.withDescription( Status.INVALID_ARGUMENT.withDescription(
String.format("Missing mandatory metadata(%s) not found", entry.getKey()))); String.format("Missing mandatory metadata(%s) not found", nameMatcher.getKey())));
} }
} }
return rlsRequestHeaders; return rlsRequestHeaders;

View File

@ -65,6 +65,7 @@ import io.grpc.rls.LbPolicyConfiguration.ChildPolicyWrapper;
import io.grpc.rls.LruCache.EvictionListener; import io.grpc.rls.LruCache.EvictionListener;
import io.grpc.rls.LruCache.EvictionType; import io.grpc.rls.LruCache.EvictionType;
import io.grpc.rls.RlsProtoConverters.RouteLookupResponseConverter; import io.grpc.rls.RlsProtoConverters.RouteLookupResponseConverter;
import io.grpc.rls.RlsProtoData.ExtraKeys;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name;
import io.grpc.rls.RlsProtoData.NameMatcher; import io.grpc.rls.RlsProtoData.NameMatcher;
@ -191,9 +192,8 @@ public class CachingRlsLbClientTest {
public void get_noError_lifeCycle() throws Exception { public void get_noError_lifeCycle() throws Exception {
setUpRlsLbClient(); setUpRlsLbClient();
InOrder inOrder = inOrder(evictionListener); InOrder inOrder = inOrder(evictionListener);
RouteLookupRequest routeLookupRequest = RouteLookupRequest routeLookupRequest = new RouteLookupRequest(ImmutableMap.of(
new RouteLookupRequest( "server", "bigtable.googleapis.com", "service-key", "foo", "method-key", "bar"));
"bigtable.googleapis.com", "/foo/bar", "grpc", ImmutableMap.<String, String>of());
rlsServerImpl.setLookupTable( rlsServerImpl.setLookupTable(
ImmutableMap.of( ImmutableMap.of(
routeLookupRequest, routeLookupRequest,
@ -242,9 +242,8 @@ public class CachingRlsLbClientTest {
public void rls_overDirectPath() throws Exception { public void rls_overDirectPath() throws Exception {
CachingRlsLbClient.enableOobChannelDirectPath = true; CachingRlsLbClient.enableOobChannelDirectPath = true;
setUpRlsLbClient(); setUpRlsLbClient();
RouteLookupRequest routeLookupRequest = RouteLookupRequest routeLookupRequest = new RouteLookupRequest(ImmutableMap.of(
new RouteLookupRequest( "server", "bigtable.googleapis.com", "service-key", "foo", "method-key", "bar"));
"bigtable.googleapis.com", "/foo/bar", "grpc", ImmutableMap.<String, String>of());
rlsServerImpl.setLookupTable( rlsServerImpl.setLookupTable(
ImmutableMap.of( ImmutableMap.of(
routeLookupRequest, routeLookupRequest,
@ -276,8 +275,8 @@ public class CachingRlsLbClientTest {
@Test @Test
public void get_throttledAndRecover() throws Exception { public void get_throttledAndRecover() throws Exception {
setUpRlsLbClient(); setUpRlsLbClient();
RouteLookupRequest routeLookupRequest = RouteLookupRequest routeLookupRequest = new RouteLookupRequest(ImmutableMap.of(
new RouteLookupRequest("server", "/foo/bar", "grpc", ImmutableMap.<String, String>of()); "server", "bigtable.googleapis.com", "service-key", "foo", "method-key", "bar"));
rlsServerImpl.setLookupTable( rlsServerImpl.setLookupTable(
ImmutableMap.of( ImmutableMap.of(
routeLookupRequest, routeLookupRequest,
@ -319,9 +318,8 @@ public class CachingRlsLbClientTest {
public void get_updatesLbState() throws Exception { public void get_updatesLbState() throws Exception {
setUpRlsLbClient(); setUpRlsLbClient();
InOrder inOrder = inOrder(helper); InOrder inOrder = inOrder(helper);
RouteLookupRequest routeLookupRequest = RouteLookupRequest routeLookupRequest = new RouteLookupRequest(ImmutableMap.of(
new RouteLookupRequest( "server", "bigtable.googleapis.com", "service-key", "service1", "method-key", "create"));
"bigtable.googleapis.com", "/foo/bar", "grpc", ImmutableMap.<String, String>of());
rlsServerImpl.setLookupTable( rlsServerImpl.setLookupTable(
ImmutableMap.of( ImmutableMap.of(
routeLookupRequest, routeLookupRequest,
@ -349,7 +347,8 @@ public class CachingRlsLbClientTest {
Metadata headers = new Metadata(); Metadata headers = new Metadata();
PickResult pickResult = pickerCaptor.getValue().pickSubchannel( PickResult pickResult = pickerCaptor.getValue().pickSubchannel(
new PickSubchannelArgsImpl( new PickSubchannelArgsImpl(
TestMethodDescriptors.voidMethod().toBuilder().setFullMethodName("foo/bar").build(), TestMethodDescriptors.voidMethod().toBuilder().setFullMethodName("service1/create")
.build(),
headers, headers,
CallOptions.DEFAULT)); CallOptions.DEFAULT));
assertThat(pickResult.getStatus().isOk()).isTrue(); assertThat(pickResult.getStatus().isOk()).isTrue();
@ -360,8 +359,7 @@ public class CachingRlsLbClientTest {
fakeBackoffProvider.nextPolicy = createBackoffPolicy(100, TimeUnit.MILLISECONDS); fakeBackoffProvider.nextPolicy = createBackoffPolicy(100, TimeUnit.MILLISECONDS);
// try to get invalid // try to get invalid
RouteLookupRequest invalidRouteLookupRequest = RouteLookupRequest invalidRouteLookupRequest =
new RouteLookupRequest( new RouteLookupRequest(ImmutableMap.<String, String>of());
"bigtable.googleapis.com", "/doesn/exists", "grpc", ImmutableMap.<String, String>of());
CachedRouteLookupResponse errorResp = getInSyncContext(invalidRouteLookupRequest); CachedRouteLookupResponse errorResp = getInSyncContext(invalidRouteLookupRequest);
assertThat(errorResp.isPending()).isTrue(); assertThat(errorResp.isPending()).isTrue();
fakeTimeProvider.forwardTime(SERVER_LATENCY_MILLIS, TimeUnit.MILLISECONDS); fakeTimeProvider.forwardTime(SERVER_LATENCY_MILLIS, TimeUnit.MILLISECONDS);
@ -369,7 +367,7 @@ public class CachingRlsLbClientTest {
errorResp = getInSyncContext(invalidRouteLookupRequest); errorResp = getInSyncContext(invalidRouteLookupRequest);
assertThat(errorResp.hasError()).isTrue(); assertThat(errorResp.hasError()).isTrue();
// Channel is still READY because the subchannel for method /foo/bar is still READY. // Channel is still READY because the subchannel for method /service1/create is still READY.
// Method /doesn/exists will use fallback child balancer and fail immediately. // Method /doesn/exists will use fallback child balancer and fail immediately.
inOrder.verify(helper) inOrder.verify(helper)
.updateBalancingState(eq(ConnectivityState.READY), pickerCaptor.capture()); .updateBalancingState(eq(ConnectivityState.READY), pickerCaptor.capture());
@ -387,10 +385,10 @@ public class CachingRlsLbClientTest {
@Test @Test
public void get_childPolicyWrapper_reusedForSameTarget() throws Exception { public void get_childPolicyWrapper_reusedForSameTarget() throws Exception {
setUpRlsLbClient(); setUpRlsLbClient();
RouteLookupRequest routeLookupRequest = RouteLookupRequest routeLookupRequest = new RouteLookupRequest(ImmutableMap.of(
new RouteLookupRequest("server", "/foo/bar", "grpc", ImmutableMap.<String, String>of()); "server", "bigtable.googleapis.com", "service-key", "foo", "method-key", "bar"));
RouteLookupRequest routeLookupRequest2 = RouteLookupRequest routeLookupRequest2 = new RouteLookupRequest(ImmutableMap.of(
new RouteLookupRequest("server", "/foo/baz", "grpc", ImmutableMap.<String, String>of()); "server", "bigtable.googleapis.com", "service-key", "foo", "method-key", "baz"));
rlsServerImpl.setLookupTable( rlsServerImpl.setLookupTable(
ImmutableMap.of( ImmutableMap.of(
routeLookupRequest, new RouteLookupResponse(ImmutableList.of("target"), "header"), routeLookupRequest, new RouteLookupResponse(ImmutableList.of("target"), "header"),
@ -426,7 +424,9 @@ public class CachingRlsLbClientTest {
ImmutableList.of(new Name("service1", "create")), ImmutableList.of(new Name("service1", "create")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), true), new NameMatcher("user", ImmutableList.of("User", "Parent"), true),
new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)))), new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)),
ExtraKeys.create("server", "service-key", "method-key"),
ImmutableMap.<String, String>of())),
/* lookupService= */ "service1", /* lookupService= */ "service1",
/* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2), /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2),
/* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300),

View File

@ -144,13 +144,15 @@ public class RlsLoadBalancerTest {
.build(); .build();
fakeRlsServerImpl.setLookupTable( fakeRlsServerImpl.setLookupTable(
ImmutableMap.of( ImmutableMap.of(
new RouteLookupRequest( new RouteLookupRequest(ImmutableMap.of(
"fake-bigtable.googleapis.com", "/com.google/Search", "grpc", "server", "fake-bigtable.googleapis.com",
ImmutableMap.<String, String>of()), "service-key", "com.google",
"method-key", "Search")),
new RouteLookupResponse(ImmutableList.of("wilderness"), "where are you?"), new RouteLookupResponse(ImmutableList.of("wilderness"), "where are you?"),
new RouteLookupRequest( new RouteLookupRequest(ImmutableMap.of(
"fake-bigtable.googleapis.com", "/com.google/Rescue", "grpc", "server", "fake-bigtable.googleapis.com",
ImmutableMap.<String, String>of()), "service-key", "com.google",
"method-key", "Rescue")),
new RouteLookupResponse(ImmutableList.of("civilization"), "you are safe"))); new RouteLookupResponse(ImmutableList.of("civilization"), "you are safe")));
rlsLb = (RlsLoadBalancer) provider.newLoadBalancer(helper); rlsLb = (RlsLoadBalancer) provider.newLoadBalancer(helper);
@ -409,7 +411,12 @@ public class RlsLoadBalancerTest {
+ " \"names\": [\"PermitId\"],\n" + " \"names\": [\"PermitId\"],\n"
+ " \"optional\": true\n" + " \"optional\": true\n"
+ " }\n" + " }\n"
+ " ]\n" + " ],\n"
+ " \"extraKeys\": {\n"
+ " \"host\": \"server\",\n"
+ " \"service\": \"service-key\",\n"
+ " \"method\": \"method-key\"\n"
+ " }\n"
+ " }\n" + " }\n"
+ " ],\n" + " ],\n"
+ " \"lookupService\": \"localhost:8972\",\n" + " \"lookupService\": \"localhost:8972\",\n"

View File

@ -27,6 +27,7 @@ import io.grpc.lookup.v1.RouteLookupResponse;
import io.grpc.rls.RlsProtoConverters.RouteLookupConfigConverter; import io.grpc.rls.RlsProtoConverters.RouteLookupConfigConverter;
import io.grpc.rls.RlsProtoConverters.RouteLookupRequestConverter; import io.grpc.rls.RlsProtoConverters.RouteLookupRequestConverter;
import io.grpc.rls.RlsProtoConverters.RouteLookupResponseConverter; import io.grpc.rls.RlsProtoConverters.RouteLookupResponseConverter;
import io.grpc.rls.RlsProtoData.ExtraKeys;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name;
import io.grpc.rls.RlsProtoData.NameMatcher; import io.grpc.rls.RlsProtoData.NameMatcher;
@ -41,40 +42,29 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class RlsProtoConvertersTest { public class RlsProtoConvertersTest {
@SuppressWarnings("deprecation")
@Test @Test
public void convert_toRequestProto() { public void convert_toRequestProto() {
Converter<RouteLookupRequest, RlsProtoData.RouteLookupRequest> converter = Converter<RouteLookupRequest, RlsProtoData.RouteLookupRequest> converter =
new RouteLookupRequestConverter(); new RouteLookupRequestConverter();
RouteLookupRequest proto = RouteLookupRequest.newBuilder() RouteLookupRequest proto = RouteLookupRequest.newBuilder()
.setServer("server")
.setPath("path")
.setTargetType("target")
.putKeyMap("key1", "val1") .putKeyMap("key1", "val1")
.build(); .build();
RlsProtoData.RouteLookupRequest object = converter.convert(proto); RlsProtoData.RouteLookupRequest object = converter.convert(proto);
assertThat(object.getServer()).isEqualTo("server");
assertThat(object.getPath()).isEqualTo("path");
assertThat(object.getTargetType()).isEqualTo("target");
assertThat(object.getKeyMap()).containsExactly("key1", "val1"); assertThat(object.getKeyMap()).containsExactly("key1", "val1");
} }
@SuppressWarnings("deprecation")
@Test @Test
public void convert_toRequestObject() { public void convert_toRequestObject() {
Converter<RlsProtoData.RouteLookupRequest, RouteLookupRequest> converter = Converter<RlsProtoData.RouteLookupRequest, RouteLookupRequest> converter =
new RouteLookupRequestConverter().reverse(); new RouteLookupRequestConverter().reverse();
RlsProtoData.RouteLookupRequest requestObject = RlsProtoData.RouteLookupRequest requestObject =
new RlsProtoData.RouteLookupRequest( new RlsProtoData.RouteLookupRequest(ImmutableMap.of("key1", "val1"));
"server", "path", "target", ImmutableMap.of("key1", "val1"));
RouteLookupRequest proto = converter.convert(requestObject); RouteLookupRequest proto = converter.convert(requestObject);
assertThat(proto.getServer()).isEqualTo("server"); assertThat(proto.getTargetType()).isEqualTo("grpc");
assertThat(proto.getPath()).isEqualTo("path");
assertThat(proto.getTargetType()).isEqualTo("target");
assertThat(proto.getKeyMapMap()).containsExactly("key1", "val1"); assertThat(proto.getKeyMapMap()).containsExactly("key1", "val1");
} }
@ -164,7 +154,15 @@ public class RlsProtoConvertersTest {
+ " \"names\": [\"User\", \"Parent\"],\n" + " \"names\": [\"User\", \"Parent\"],\n"
+ " \"optional\": true\n" + " \"optional\": true\n"
+ " }\n" + " }\n"
+ " ]\n" + " ],\n"
+ " \"extraKeys\": {\n"
+ " \"host\": \"host-key\",\n"
+ " \"service\": \"service-key\",\n"
+ " \"method\": \"method-key\"\n"
+ " }, \n"
+ " \"constantKeys\": {\n"
+ " \"constKey1\": \"value1\"\n"
+ " }\n"
+ " }\n" + " }\n"
+ " ],\n" + " ],\n"
+ " \"lookupService\": \"service1\",\n" + " \"lookupService\": \"service1\",\n"
@ -183,16 +181,22 @@ public class RlsProtoConvertersTest {
ImmutableList.of(new Name("service1", "create")), ImmutableList.of(new Name("service1", "create")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), true), new NameMatcher("user", ImmutableList.of("User", "Parent"), true),
new NameMatcher("id", ImmutableList.of("X-Google-Id"), true))), new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)),
ExtraKeys.DEFAULT,
ImmutableMap.<String, String>of()),
new GrpcKeyBuilder( new GrpcKeyBuilder(
ImmutableList.of(new Name("service1")), ImmutableList.of(new Name("service1")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), true), new NameMatcher("user", ImmutableList.of("User", "Parent"), true),
new NameMatcher("password", ImmutableList.of("Password"), true))), new NameMatcher("password", ImmutableList.of("Password"), true)),
ExtraKeys.DEFAULT,
ImmutableMap.<String, String>of()),
new GrpcKeyBuilder( new GrpcKeyBuilder(
ImmutableList.of(new Name("service3")), ImmutableList.of(new Name("service3")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), true)))), new NameMatcher("user", ImmutableList.of("User", "Parent"), true)),
ExtraKeys.create("host-key", "service-key", "method-key"),
ImmutableMap.of("constKey1", "value1"))),
/* lookupService= */ "service1", /* lookupService= */ "service1",
/* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2), /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2),
/* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300),

View File

@ -20,9 +20,11 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.grpc.Metadata; import io.grpc.Metadata;
import io.grpc.Status.Code; import io.grpc.Status.Code;
import io.grpc.StatusRuntimeException; import io.grpc.StatusRuntimeException;
import io.grpc.rls.RlsProtoData.ExtraKeys;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder;
import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder.Name;
import io.grpc.rls.RlsProtoData.NameMatcher; import io.grpc.rls.RlsProtoData.NameMatcher;
@ -43,21 +45,29 @@ public class RlsRequestFactoryTest {
ImmutableList.of(new Name("com.google.service1", "Create")), ImmutableList.of(new Name("com.google.service1", "Create")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), true), new NameMatcher("user", ImmutableList.of("User", "Parent"), true),
new NameMatcher("id", ImmutableList.of("X-Google-Id"), true))), new NameMatcher("id", ImmutableList.of("X-Google-Id"), true)),
ExtraKeys.create("server-1", null, null),
ImmutableMap.of("const-key-1", "const-value-1")),
new GrpcKeyBuilder( new GrpcKeyBuilder(
ImmutableList.of(new Name("com.google.service1")), ImmutableList.of(new Name("com.google.service1")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), true), new NameMatcher("user", ImmutableList.of("User", "Parent"), true),
new NameMatcher("password", ImmutableList.of("Password"), true))), new NameMatcher("password", ImmutableList.of("Password"), true)),
ExtraKeys.create(null, "service-2", null),
ImmutableMap.of("const-key-2", "const-value-2")),
new GrpcKeyBuilder( new GrpcKeyBuilder(
ImmutableList.of(new Name("com.google.service2")), ImmutableList.of(new Name("com.google.service2")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), false), new NameMatcher("user", ImmutableList.of("User", "Parent"), false),
new NameMatcher("password", ImmutableList.of("Password"), true))), new NameMatcher("password", ImmutableList.of("Password"), true)),
ExtraKeys.create(null, "service-3", "method-3"),
ImmutableMap.<String, String>of()),
new GrpcKeyBuilder( new GrpcKeyBuilder(
ImmutableList.of(new Name("com.google.service3")), ImmutableList.of(new Name("com.google.service3")),
ImmutableList.of( ImmutableList.of(
new NameMatcher("user", ImmutableList.of("User", "Parent"), true)))), new NameMatcher("user", ImmutableList.of("User", "Parent"), true)),
ExtraKeys.create(null, null, null),
ImmutableMap.of("const-key-4", "const-value-4"))),
/* lookupService= */ "bigtable-rls.googleapis.com", /* lookupService= */ "bigtable-rls.googleapis.com",
/* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2), /* lookupServiceTimeoutInMillis= */ TimeUnit.SECONDS.toMillis(2),
/* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300), /* maxAgeInMillis= */ TimeUnit.SECONDS.toMillis(300),
@ -77,10 +87,11 @@ public class RlsRequestFactoryTest {
metadata.put(Metadata.Key.of("foo", Metadata.ASCII_STRING_MARSHALLER), "bar"); metadata.put(Metadata.Key.of("foo", Metadata.ASCII_STRING_MARSHALLER), "bar");
RouteLookupRequest request = factory.create("com.google.service1", "Create", metadata); RouteLookupRequest request = factory.create("com.google.service1", "Create", metadata);
assertThat(request.getTargetType()).isEqualTo("grpc"); assertThat(request.getKeyMap()).containsExactly(
assertThat(request.getPath()).isEqualTo("/com.google.service1/Create"); "user", "test",
assertThat(request.getServer()).isEqualTo("bigtable.googleapis.com"); "id", "123",
assertThat(request.getKeyMap()).containsExactly("user", "test", "id", "123"); "server-1", "bigtable.googleapis.com",
"const-key-1", "const-value-1");
} }
@Test @Test
@ -106,10 +117,11 @@ public class RlsRequestFactoryTest {
RouteLookupRequest request = factory.create("com.google.service1" , "Update", metadata); RouteLookupRequest request = factory.create("com.google.service1" , "Update", metadata);
assertThat(request.getTargetType()).isEqualTo("grpc"); assertThat(request.getKeyMap()).containsExactly(
assertThat(request.getPath()).isEqualTo("/com.google.service1/Update"); "user", "test",
assertThat(request.getServer()).isEqualTo("bigtable.googleapis.com"); "password", "hunter2",
assertThat(request.getKeyMap()).containsExactly("user", "test", "password", "hunter2"); "service-2", "com.google.service1",
"const-key-2", "const-value-2");
} }
@Test @Test
@ -121,10 +133,10 @@ public class RlsRequestFactoryTest {
RouteLookupRequest request = factory.create("com.google.service1", "Update", metadata); RouteLookupRequest request = factory.create("com.google.service1", "Update", metadata);
assertThat(request.getTargetType()).isEqualTo("grpc"); assertThat(request.getKeyMap()).containsExactly(
assertThat(request.getPath()).isEqualTo("/com.google.service1/Update"); "user", "test",
assertThat(request.getServer()).isEqualTo("bigtable.googleapis.com"); "service-2", "com.google.service1",
assertThat(request.getKeyMap()).containsExactly("user", "test"); "const-key-2", "const-value-2");
} }
@Test @Test
@ -135,10 +147,6 @@ public class RlsRequestFactoryTest {
metadata.put(Metadata.Key.of("foo", Metadata.ASCII_STRING_MARSHALLER), "bar"); metadata.put(Metadata.Key.of("foo", Metadata.ASCII_STRING_MARSHALLER), "bar");
RouteLookupRequest request = factory.create("abc.def.service999", "Update", metadata); RouteLookupRequest request = factory.create("abc.def.service999", "Update", metadata);
assertThat(request.getTargetType()).isEqualTo("grpc");
assertThat(request.getPath()).isEqualTo("/abc.def.service999/Update");
assertThat(request.getServer()).isEqualTo("bigtable.googleapis.com");
assertThat(request.getKeyMap()).isEmpty(); assertThat(request.getKeyMap()).isEmpty();
} }
@ -151,9 +159,7 @@ public class RlsRequestFactoryTest {
RouteLookupRequest request = factory.create("com.google.service3", "Update", metadata); RouteLookupRequest request = factory.create("com.google.service3", "Update", metadata);
assertThat(request.getTargetType()).isEqualTo("grpc"); assertThat(request.getKeyMap()).containsExactly(
assertThat(request.getPath()).isEqualTo("/com.google.service3/Update"); "user", "test", "const-key-4", "const-value-4");
assertThat(request.getServer()).isEqualTo("bigtable.googleapis.com");
assertThat(request.getKeyMap()).containsExactly("user", "test");
} }
} }