Skip to content

Commit

Permalink
feat(appmesh): change Route's spec to a union-like class (#11343)
Browse files Browse the repository at this point in the history
Implements the same pattern `GatewayRoutes` use for defining protocol specific specs.

Adds GRPC and HTTP2 support to Routes which will resolve #9755

BREAKING CHANGE: changes Route's spec to a union-like class. RouteSpec is now defined using protocol variant static methods


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
Dominic Fezzie authored Nov 19, 2020
1 parent 9fe0dad commit f0de91f
Show file tree
Hide file tree
Showing 8 changed files with 637 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,22 +293,24 @@ export class AppMeshExtension extends ServiceExtension {
virtualRouterName: `${this.parentService.id}`,
});

// Form the service name that requests will be made to
const serviceName = `${this.parentService.id}.${cloudmapNamespace.namespaceName}`;
const weightedTargets: appmesh.WeightedTarget[] = [{
virtualNode: this.virtualNode,
weight: 1,
}];
// Now add the virtual node as a route in the virtual router
// Ensure that the route type matches the protocol type.
this.route = this.virtualRouter.addRoute(`${this.parentService.id}-route`, {
routeTargets: [{
virtualNode: this.virtualNode,
weight: 1,
}],
// Ensure that the route type matches the protocol type.
routeType: this.protocol == appmesh.Protocol.HTTP ? appmesh.RouteType.HTTP : appmesh.RouteType.TCP,
routeSpec: this.routeSpec(weightedTargets, serviceName),
});

// Now create a virtual service. Relationship goes like this:
// virtual service -> virtual router -> virtual node
this.virtualService = new appmesh.VirtualService(this.scope, `${this.parentService.id}-virtual-service`, {
mesh: this.mesh,
virtualRouter: this.virtualRouter,
virtualServiceName: `${this.parentService.id}.${cloudmapNamespace.namespaceName}`,
virtualServiceName: serviceName,
});
}

Expand Down Expand Up @@ -340,6 +342,26 @@ export class AppMeshExtension extends ServiceExtension {
this.virtualNode.addBackend(otherAppMesh.virtualService);
}

private routeSpec(weightedTargets: appmesh.WeightedTarget[], serviceName: string): appmesh.RouteSpec {
switch (this.protocol) {
case appmesh.Protocol.HTTP: return appmesh.RouteSpec.http({
weightedTargets: weightedTargets,
});
case appmesh.Protocol.HTTP2: return appmesh.RouteSpec.http2({
weightedTargets: weightedTargets,
});
case appmesh.Protocol.GRPC: return appmesh.RouteSpec.grpc({
weightedTargets: weightedTargets,
match: {
serviceName: serviceName,
},
});
case appmesh.Protocol.TCP: return appmesh.RouteSpec.tcp({
weightedTargets: weightedTargets,
});
}
}

private virtualRouterListener(port: number): appmesh.VirtualRouterListener {
switch (this.protocol) {
case appmesh.Protocol.HTTP: return appmesh.VirtualRouterListener.http(port);
Expand Down
66 changes: 45 additions & 21 deletions packages/@aws-cdk/aws-appmesh/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,39 +188,63 @@ The `listeners` property can be left blank and added later with the `node.addLis

A `route` is associated with a virtual router, and it's used to match requests for a virtual router and distribute traffic accordingly to its associated virtual nodes.

You can use the prefix parameter in your `route` specification for path-based routing of requests. For example, if your virtual service name is my-service.local and you want the `route` to match requests to my-service.local/metrics, your prefix should be /metrics.

If your `route` matches a request, you can distribute traffic to one or more target virtual nodes with relative weighting.

```typescript
router.addRoute('route', {
routeTargets: [
{
virtualNode,
weight: 1,
router.addRoute('route-http', {
routeSpec: appmesh.RouteSpec.http({
weightedTargets: [
{
virtualNode: node,
},
],
match: {
prefixPath: '/path-to-app',
},
],
prefix: `/path-to-app`,
routeType: RouteType.HTTP,
}),
});
```

Add a single route with multiple targets and split traffic 50/50

```typescript
router.addRoute('route', {
routeTargets: [
{
virtualNode,
weight: 50,
router.addRoute('route-http', {
routeSpec: appmesh.RouteSpec.http({
weightedTargets: [
{
virtualNode: node,
weight: 50,
},
{
virtualNode: node,
weight: 50,
},
],
match: {
prefixPath: '/path-to-app',
},
{
virtualNode2,
weight: 50,
}),
});
```

The _RouteSpec_ class provides an easy interface for defining new protocol specific route specs.
The `tcp()`, `http()` and `http2()` methods provide the spec necessary to define a protocol specific spec.

For HTTP based routes, the match field can be used to match on a route prefix.
By default, an HTTP based route will match on `/`. All matches must start with a leading `/`.

```typescript
router.addRoute('route-http', {
routeSpec: appmesh.RouteSpec.grpc({
weightedTargets: [
{
virtualNode: node,
},
],
match: {
serviceName: 'my-service.default.svc.cluster.local',
},
],
prefix: `/path-to-app`,
routeType: RouteType.HTTP,
}),
});
```

Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-appmesh/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export * from './appmesh.generated';
export * from './mesh';
export * from './route';
export * from './route-spec';
export * from './shared-interfaces';
export * from './virtual-node';
export * from './virtual-router';
Expand Down
Loading

0 comments on commit f0de91f

Please sign in to comment.