xds: remove path matcher format requirements and default route requirement for routing enabled (v1.30.x backport) (#7063) (#7070)

Remove requirement for formats of path matchers. Only require the last route to be the default route for the case when routing is disabled.
This commit is contained in:
Chengyuan Zhang 2020-05-27 19:56:22 +00:00 committed by GitHub
parent bd1c256ef5
commit d71161432a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 11 additions and 79 deletions

View File

@ -444,6 +444,7 @@ final class EnvoyProtoData {
return routeAction;
}
// TODO(chengyuanzhang): delete and do not use after routing feature is always ON.
boolean isDefaultRoute() {
return routeMatch.isMatchAll();
}
@ -553,16 +554,10 @@ final class EnvoyProtoData {
return pathExactMatch;
}
boolean isMatchAll() {
if (pathSafeRegExMatch != null || fractionMatch != null) {
return false;
}
if (!headerMatchers.isEmpty()) {
return false;
}
if (pathExactMatch != null) {
return false;
}
// TODO(chengyuanzhang): delete and do not use after routing feature is always ON.
private boolean isMatchAll() {
// For backward compatibility, all the other matchers are ignored. When routing is enabled,
// we should never care if a matcher matches all requests.
if (pathPrefixMatch != null) {
return pathPrefixMatch.isEmpty() || pathPrefixMatch.equals("/");
}
@ -655,27 +650,9 @@ final class EnvoyProtoData {
switch (proto.getPathSpecifierCase()) {
case PREFIX:
prefixPathMatch = proto.getPrefix();
// Supported prefix match format:
// "", "/" (default)
// "/service/"
if (!prefixPathMatch.isEmpty() && !prefixPathMatch.equals("/")) {
if (!prefixPathMatch.startsWith("/") || !prefixPathMatch.endsWith("/")
|| prefixPathMatch.length() < 3) {
return StructOrError.fromError(
"Invalid format of prefix path match: " + prefixPathMatch);
}
}
break;
case PATH:
exactPathMatch = proto.getPath();
int lastSlash = exactPathMatch.lastIndexOf('/');
// Supported exact match format:
// "/service/method"
if (!exactPathMatch.startsWith("/") || lastSlash == 0
|| lastSlash == exactPathMatch.length() - 1) {
return StructOrError.fromError(
"Invalid format of exact path match: " + exactPathMatch);
}
break;
case REGEX:
return StructOrError.fromError("Unsupported path match type: regex");

View File

@ -858,14 +858,14 @@ final class XdsClientImpl extends XdsClient {
throw new InvalidProtoDataException(
"Virtual host [" + virtualHost.getName() + "] contains no usable route");
}
// The last route must be a default route.
if (!Iterables.getLast(routes).isDefaultRoute()) {
throw new InvalidProtoDataException(
"Virtual host [" + virtualHost.getName()
+ "] contains non-default route as the last route");
}
if (!enableExperimentalRouting) {
EnvoyProtoData.Route defaultRoute = Iterables.getLast(routes);
if (!defaultRoute.isDefaultRoute()) {
throw new InvalidProtoDataException(
"Virtual host [" + virtualHost.getName()
+ "] contains non-default route as the last route");
}
return Collections.singletonList(defaultRoute);
}
return Collections.unmodifiableList(routes);

View File

@ -246,51 +246,6 @@ public class EnvoyProtoDataTest {
assertThat(unsetStruct.getStruct()).isNull();
}
@Test
public void convertRouteMatch_pathMatchFormat() {
StructOrError<RouteMatch> struct1 =
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("", null));
StructOrError<RouteMatch> struct2 =
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("/", null));
StructOrError<RouteMatch> struct3 =
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("/service", null));
StructOrError<RouteMatch> struct4 =
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("/service/", null));
StructOrError<RouteMatch> struct5 =
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto(null, ""));
StructOrError<RouteMatch> struct6 =
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto(null, "/service/method"));
StructOrError<RouteMatch> struct7 =
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto(null, "/service/method/"));
StructOrError<RouteMatch> struct8 =
RouteMatch.fromEnvoyProtoRouteMatch(
io.envoyproxy.envoy.api.v2.route.RouteMatch.newBuilder()
.setSafeRegex(
io.envoyproxy.envoy.type.matcher.RegexMatcher.newBuilder().setRegex("["))
.build());
assertThat(struct1.getStruct()).isNotNull();
assertThat(struct2.getStruct()).isNotNull();
assertThat(struct3.getStruct()).isNull();
assertThat(struct4.getStruct()).isNotNull();
assertThat(struct5.getStruct()).isNull();
assertThat(struct6.getStruct()).isNotNull();
assertThat(struct7.getStruct()).isNull();
assertThat(struct8.getStruct()).isNull();
}
private static io.envoyproxy.envoy.api.v2.route.RouteMatch buildSimpleRouteMatchProto(
@Nullable String pathPrefix, @Nullable String path) {
io.envoyproxy.envoy.api.v2.route.RouteMatch.Builder builder =
io.envoyproxy.envoy.api.v2.route.RouteMatch.newBuilder();
if (pathPrefix != null) {
builder.setPrefix(pathPrefix);
} else if (path != null) {
builder.setPath(path);
}
return builder.build();
}
@Test
public void convertRouteMatch_withHeaderMatching() {
io.envoyproxy.envoy.api.v2.route.RouteMatch proto =