Skip to content

Commit 9922382

Browse files
authored
xds: parse RDS response to ConfigUpdate for path matching
1 parent 1acde46 commit 9922382

File tree

4 files changed

+546
-53
lines changed

4 files changed

+546
-53
lines changed

xds/src/main/java/io/grpc/xds/EnvoyProtoData.java

Lines changed: 249 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import com.google.common.annotations.VisibleForTesting;
2020
import com.google.common.base.MoreObjects;
21-
import com.google.common.base.Objects;
21+
import com.google.common.base.Optional;
2222
import com.google.common.collect.ImmutableList;
2323
import io.envoyproxy.envoy.type.FractionalPercent;
2424
import io.envoyproxy.envoy.type.FractionalPercent.DenominatorType;
@@ -27,6 +27,8 @@
2727
import java.util.ArrayList;
2828
import java.util.Collections;
2929
import java.util.List;
30+
import java.util.Objects;
31+
import javax.annotation.Nullable;
3032

3133
/**
3234
* Defines gRPC data types for Envoy protobuf messages used in xDS protocol. Each data type has
@@ -96,14 +98,14 @@ public boolean equals(Object o) {
9698
return false;
9799
}
98100
Locality locality = (Locality) o;
99-
return Objects.equal(region, locality.region)
100-
&& Objects.equal(zone, locality.zone)
101-
&& Objects.equal(subzone, locality.subzone);
101+
return Objects.equals(region, locality.region)
102+
&& Objects.equals(zone, locality.zone)
103+
&& Objects.equals(subzone, locality.subzone);
102104
}
103105

104106
@Override
105107
public int hashCode() {
106-
return Objects.hashCode(region, zone, subzone);
108+
return Objects.hash(region, zone, subzone);
107109
}
108110

109111
@Override
@@ -169,12 +171,12 @@ public boolean equals(Object o) {
169171
LocalityLbEndpoints that = (LocalityLbEndpoints) o;
170172
return localityWeight == that.localityWeight
171173
&& priority == that.priority
172-
&& Objects.equal(endpoints, that.endpoints);
174+
&& Objects.equals(endpoints, that.endpoints);
173175
}
174176

175177
@Override
176178
public int hashCode() {
177-
return Objects.hashCode(endpoints, localityWeight, priority);
179+
return Objects.hash(endpoints, localityWeight, priority);
178180
}
179181

180182
@Override
@@ -247,13 +249,13 @@ public boolean equals(Object o) {
247249
}
248250
LbEndpoint that = (LbEndpoint) o;
249251
return loadBalancingWeight == that.loadBalancingWeight
250-
&& Objects.equal(eag, that.eag)
252+
&& Objects.equals(eag, that.eag)
251253
&& isHealthy == that.isHealthy;
252254
}
253255

254256
@Override
255257
public int hashCode() {
256-
return Objects.hashCode(eag, loadBalancingWeight, isHealthy);
258+
return Objects.hash(eag, loadBalancingWeight, isHealthy);
257259
}
258260

259261
@Override
@@ -267,7 +269,7 @@ public String toString() {
267269
}
268270

269271
/**
270-
* See corresponding Enovy proto message {@link
272+
* See corresponding Envoy proto message {@link
271273
* io.envoyproxy.envoy.api.v2.ClusterLoadAssignment.Policy.DropOverload}.
272274
*/
273275
static final class DropOverload {
@@ -323,12 +325,12 @@ public boolean equals(Object o) {
323325
return false;
324326
}
325327
DropOverload that = (DropOverload) o;
326-
return dropsPerMillion == that.dropsPerMillion && Objects.equal(category, that.category);
328+
return dropsPerMillion == that.dropsPerMillion && Objects.equals(category, that.category);
327329
}
328330

329331
@Override
330332
public int hashCode() {
331-
return Objects.hashCode(category, dropsPerMillion);
333+
return Objects.hash(category, dropsPerMillion);
332334
}
333335

334336
@Override
@@ -339,4 +341,239 @@ public String toString() {
339341
.toString();
340342
}
341343
}
344+
345+
/** See corresponding Envoy proto message {@link io.envoyproxy.envoy.api.v2.route.Route}. */
346+
static final class Route {
347+
private final RouteMatch routeMatch;
348+
@Nullable
349+
private final RouteAction routeAction;
350+
351+
@VisibleForTesting
352+
Route(RouteMatch routeMatch, @Nullable RouteAction routeAction) {
353+
this.routeMatch = routeMatch;
354+
this.routeAction = routeAction;
355+
}
356+
357+
RouteMatch getRouteMatch() {
358+
return routeMatch;
359+
}
360+
361+
Optional<RouteAction> getRouteAction() {
362+
return Optional.fromNullable(routeAction);
363+
}
364+
365+
@Override
366+
public boolean equals(Object o) {
367+
if (this == o) {
368+
return true;
369+
}
370+
if (o == null || getClass() != o.getClass()) {
371+
return false;
372+
}
373+
Route route = (Route) o;
374+
return Objects.equals(routeMatch, route.routeMatch)
375+
&& Objects.equals(routeAction, route.routeAction);
376+
}
377+
378+
@Override
379+
public int hashCode() {
380+
return Objects.hash(routeMatch, routeAction);
381+
}
382+
383+
@Override
384+
public String toString() {
385+
return MoreObjects.toStringHelper(this)
386+
.add("routeMatch", routeMatch)
387+
.add("routeAction", routeAction)
388+
.toString();
389+
}
390+
391+
static Route fromEnvoyProtoRoute(io.envoyproxy.envoy.api.v2.route.Route proto) {
392+
RouteMatch routeMatch = RouteMatch.fromEnvoyProtoRouteMatch(proto.getMatch());
393+
RouteAction routeAction = null;
394+
if (proto.hasRoute()) {
395+
routeAction = RouteAction.fromEnvoyProtoRouteAction(proto.getRoute());
396+
}
397+
return new Route(routeMatch, routeAction);
398+
}
399+
}
400+
401+
/** See corresponding Envoy proto message {@link io.envoyproxy.envoy.api.v2.route.RouteMatch}. */
402+
static final class RouteMatch {
403+
private final String prefix;
404+
private final String path;
405+
private final boolean hasRegex;
406+
407+
@VisibleForTesting
408+
RouteMatch(String prefix, String path, boolean hasRegex) {
409+
this.prefix = prefix;
410+
this.path = path;
411+
this.hasRegex = hasRegex;
412+
}
413+
414+
String getPrefix() {
415+
return prefix;
416+
}
417+
418+
String getPath() {
419+
return path;
420+
}
421+
422+
boolean hasRegex() {
423+
return hasRegex;
424+
}
425+
426+
@Override
427+
public boolean equals(Object o) {
428+
if (this == o) {
429+
return true;
430+
}
431+
if (o == null || getClass() != o.getClass()) {
432+
return false;
433+
}
434+
RouteMatch that = (RouteMatch) o;
435+
return hasRegex == that.hasRegex
436+
&& Objects.equals(prefix, that.prefix)
437+
&& Objects.equals(path, that.path);
438+
}
439+
440+
@Override
441+
public int hashCode() {
442+
return Objects.hash(prefix, path, hasRegex);
443+
}
444+
445+
@Override
446+
public String toString() {
447+
return MoreObjects.toStringHelper(this)
448+
.add("prefix", prefix)
449+
.add("path", path)
450+
.add("hasRegex", hasRegex)
451+
.toString();
452+
}
453+
454+
private static RouteMatch fromEnvoyProtoRouteMatch(
455+
io.envoyproxy.envoy.api.v2.route.RouteMatch proto) {
456+
return new RouteMatch(
457+
proto.getPrefix(), proto.getPath(), !proto.getRegex().isEmpty() || proto.hasSafeRegex());
458+
}
459+
}
460+
461+
/** See corresponding Envoy proto message {@link io.envoyproxy.envoy.api.v2.route.RouteAction}. */
462+
static final class RouteAction {
463+
private final String cluster;
464+
private final String clusterHeader;
465+
private final List<ClusterWeight> weightedCluster;
466+
467+
@VisibleForTesting
468+
RouteAction(String cluster, String clusterHeader, List<ClusterWeight> weightedCluster) {
469+
this.cluster = cluster;
470+
this.clusterHeader = clusterHeader;
471+
this.weightedCluster = Collections.unmodifiableList(weightedCluster);
472+
}
473+
474+
String getCluster() {
475+
return cluster;
476+
}
477+
478+
String getClusterHeader() {
479+
return clusterHeader;
480+
}
481+
482+
List<ClusterWeight> getWeightedCluster() {
483+
return weightedCluster;
484+
}
485+
486+
@Override
487+
public boolean equals(Object o) {
488+
if (this == o) {
489+
return true;
490+
}
491+
if (o == null || getClass() != o.getClass()) {
492+
return false;
493+
}
494+
RouteAction that = (RouteAction) o;
495+
return Objects.equals(cluster, that.cluster)
496+
&& Objects.equals(clusterHeader, that.clusterHeader)
497+
&& Objects.equals(weightedCluster, that.weightedCluster);
498+
}
499+
500+
@Override
501+
public int hashCode() {
502+
return Objects.hash(cluster, clusterHeader, weightedCluster);
503+
}
504+
505+
@Override
506+
public String toString() {
507+
return MoreObjects.toStringHelper(this)
508+
.add("cluster", cluster)
509+
.add("clusterHeader", clusterHeader)
510+
.add("weightedCluster", weightedCluster)
511+
.toString();
512+
}
513+
514+
private static RouteAction fromEnvoyProtoRouteAction(
515+
io.envoyproxy.envoy.api.v2.route.RouteAction proto) {
516+
List<ClusterWeight> weightedCluster = new ArrayList<>();
517+
List<io.envoyproxy.envoy.api.v2.route.WeightedCluster.ClusterWeight> clusterWeights
518+
= proto.getWeightedClusters().getClustersList();
519+
for (io.envoyproxy.envoy.api.v2.route.WeightedCluster.ClusterWeight clusterWeight
520+
: clusterWeights) {
521+
weightedCluster.add(ClusterWeight.fromEnvoyProtoClusterWeight(clusterWeight));
522+
}
523+
return new RouteAction(proto.getCluster(), proto.getClusterHeader(), weightedCluster);
524+
}
525+
}
526+
527+
/**
528+
* See corresponding Envoy proto message {@link
529+
* io.envoyproxy.envoy.api.v2.route.WeightedCluster.ClusterWeight}.
530+
*/
531+
static final class ClusterWeight {
532+
private final String name;
533+
private final int weight;
534+
535+
@VisibleForTesting
536+
ClusterWeight(String name, int weight) {
537+
this.name = name;
538+
this.weight = weight;
539+
}
540+
541+
String getName() {
542+
return name;
543+
}
544+
545+
int getWeight() {
546+
return weight;
547+
}
548+
549+
@Override
550+
public boolean equals(Object o) {
551+
if (this == o) {
552+
return true;
553+
}
554+
if (o == null || getClass() != o.getClass()) {
555+
return false;
556+
}
557+
ClusterWeight that = (ClusterWeight) o;
558+
return weight == that.weight && Objects.equals(name, that.name);
559+
}
560+
561+
@Override
562+
public int hashCode() {
563+
return Objects.hash(name, weight);
564+
}
565+
566+
@Override
567+
public String toString() {
568+
return MoreObjects.toStringHelper(this)
569+
.add("name", name)
570+
.add("weight", weight)
571+
.toString();
572+
}
573+
574+
private static ClusterWeight fromEnvoyProtoClusterWeight(
575+
io.envoyproxy.envoy.api.v2.route.WeightedCluster.ClusterWeight proto) {
576+
return new ClusterWeight(proto.getName(), proto.getWeight().getValue());
577+
}
578+
}
342579
}

xds/src/main/java/io/grpc/xds/XdsClient.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@
3535
import io.grpc.xds.EnvoyProtoData.DropOverload;
3636
import io.grpc.xds.EnvoyProtoData.Locality;
3737
import io.grpc.xds.EnvoyProtoData.LocalityLbEndpoints;
38+
import io.grpc.xds.EnvoyProtoData.Route;
3839
import io.grpc.xds.EnvoyServerProtoData.Listener;
3940
import io.grpc.xds.XdsLogger.XdsLogLevel;
4041
import java.util.ArrayList;
42+
import java.util.Collection;
4143
import java.util.Collections;
4244
import java.util.LinkedHashMap;
4345
import java.util.List;
@@ -62,21 +64,28 @@ abstract class XdsClient {
6264
*/
6365
static final class ConfigUpdate {
6466
private final String clusterName;
67+
private final List<Route> routes;
6568

66-
private ConfigUpdate(String clusterName) {
69+
private ConfigUpdate(String clusterName, List<Route> routes) {
6770
this.clusterName = clusterName;
71+
this.routes = routes;
6872
}
6973

7074
String getClusterName() {
7175
return clusterName;
7276
}
7377

78+
public List<Route> getRoutes() {
79+
return routes;
80+
}
81+
7482
@Override
7583
public String toString() {
7684
return
7785
MoreObjects
7886
.toStringHelper(this)
7987
.add("clusterName", clusterName)
88+
.add("routes", routes)
8089
.toString();
8190
}
8291

@@ -85,6 +94,7 @@ static Builder newBuilder() {
8594
}
8695

8796
static final class Builder {
97+
private final List<Route> routes = new ArrayList<>();
8898
private String clusterName;
8999

90100
// Use ConfigUpdate.newBuilder().
@@ -96,9 +106,14 @@ Builder setClusterName(String clusterName) {
96106
return this;
97107
}
98108

109+
Builder addRoutes(Collection<Route> route) {
110+
routes.addAll(route);
111+
return this;
112+
}
113+
99114
ConfigUpdate build() {
100115
Preconditions.checkState(clusterName != null, "clusterName is not set");
101-
return new ConfigUpdate(clusterName);
116+
return new ConfigUpdate(clusterName, Collections.unmodifiableList(routes));
102117
}
103118
}
104119
}

0 commit comments

Comments
 (0)