Skip to content

Commit 574d383

Browse files
authored
feat(location): support RouteCalculator (#30682)
### Issue # (if applicable) Closes #30681 . ### Reason for this change In [aws-location-alpha](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-location-alpha-readme.html), [route calculator](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_location.CfnRouteCalculator.html) has not been supported yet. ### Description of changes Add `RouteCalculator` class. ### Description of how you validated changes Add unit tests and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 2a27711 commit 574d383

16 files changed

+710
-21
lines changed

packages/@aws-cdk/aws-location-alpha/README.md

+27
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,30 @@ const geofenceCollection = new location.GeofenceCollection(this, 'GeofenceCollec
7777

7878
geofenceCollection.grantRead(role);
7979
```
80+
81+
## Route Calculator
82+
83+
Route calculator resources allow you to find routes and estimate travel time based on up-to-date road network and live traffic information from your chosen data provider.
84+
85+
For more information, see [Routes](https://docs.aws.amazon.com/location/latest/developerguide/route-concepts.html).
86+
87+
To create a route calculator, define a `RouteCalculator`:
88+
89+
```ts
90+
new location.RouteCalculator(this, 'RouteCalculator', {
91+
routeCalculatorName: 'MyRouteCalculator', // optional, defaults to a generated name
92+
dataSource: location.DataSource.ESRI,
93+
});
94+
```
95+
96+
Use the `grant()` or `grantRead()` method to grant the given identity permissions to perform actions
97+
on the route calculator:
98+
99+
```ts
100+
declare const role: iam.Role;
101+
102+
const routeCalculator = new location.RouteCalculator(this, 'RouteCalculator', {
103+
dataSource: location.DataSource.ESRI,
104+
});
105+
routeCalculator.grantRead(role);
106+
```
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export * from './geofence-collection';
22
export * from './place-index';
3+
export * from './route-calculator';
4+
export * from './util';
35

46
// AWS::Location CloudFormation Resources:

packages/@aws-cdk/aws-location-alpha/lib/place-index.ts

+1-20
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as iam from 'aws-cdk-lib/aws-iam';
22
import { ArnFormat, IResource, Lazy, Resource, Stack, Token } from 'aws-cdk-lib/core';
33
import { Construct } from 'constructs';
44
import { CfnPlaceIndex } from 'aws-cdk-lib/aws-location';
5-
import { generateUniqueId } from './util';
5+
import { DataSource, generateUniqueId } from './util';
66

77
/**
88
* A Place Index
@@ -59,25 +59,6 @@ export interface PlaceIndexProps {
5959
readonly description?: string;
6060
}
6161

62-
/**
63-
* Data source for a place index
64-
*/
65-
export enum DataSource {
66-
/**
67-
* Esri
68-
*
69-
* @see https://docs.aws.amazon.com/location/latest/developerguide/esri.html
70-
*/
71-
ESRI = 'Esri',
72-
73-
/**
74-
* HERE
75-
*
76-
* @see https://docs.aws.amazon.com/location/latest/developerguide/HERE.html
77-
*/
78-
HERE = 'Here',
79-
}
80-
8162
/**
8263
* Intend use for the results of an operation
8364
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import * as iam from 'aws-cdk-lib/aws-iam';
2+
import { ArnFormat, IResource, Lazy, Resource, Stack, Token } from 'aws-cdk-lib/core';
3+
import { Construct } from 'constructs';
4+
import { CfnRouteCalculator } from 'aws-cdk-lib/aws-location';
5+
import { generateUniqueId, DataSource } from './util';
6+
7+
/**
8+
* A Route Calculator
9+
*/
10+
export interface IRouteCalculator extends IResource {
11+
/**
12+
* The name of the route calculator
13+
*
14+
* @attribute
15+
*/
16+
readonly routeCalculatorName: string;
17+
18+
/**
19+
* The Amazon Resource Name (ARN) of the route calculator resource
20+
*
21+
* @attribute Arn,CalculatorArn
22+
*/
23+
readonly routeCalculatorArn: string;
24+
}
25+
26+
/**
27+
* Properties for a route calculator
28+
*/
29+
export interface RouteCalculatorProps {
30+
/**
31+
* A name for the route calculator
32+
*
33+
* Must be between 1 and 100 characters and contain only alphanumeric characters,
34+
* hyphens, periods and underscores.
35+
*
36+
* @default - A name is automatically generated
37+
*/
38+
readonly routeCalculatorName?: string;
39+
40+
/**
41+
* Data source for the route calculator
42+
*/
43+
readonly dataSource: DataSource;
44+
45+
/**
46+
* A description for the route calculator
47+
*
48+
* @default - no description
49+
*/
50+
readonly description?: string;
51+
}
52+
53+
/**
54+
* A Route Calculator
55+
*
56+
* @see https://docs.aws.amazon.com/location/latest/developerguide/places-concepts.html
57+
*/
58+
export class RouteCalculator extends Resource implements IRouteCalculator {
59+
/**
60+
* Use an existing route calculator by name
61+
*/
62+
public static fromRouteCalculatorName(scope: Construct, id: string, routeCalculatorName: string): IRouteCalculator {
63+
const routeCalculatorArn = Stack.of(scope).formatArn({
64+
service: 'geo',
65+
resource: 'route-calculator',
66+
resourceName: routeCalculatorName,
67+
});
68+
69+
return RouteCalculator.fromRouteCalculatorArn(scope, id, routeCalculatorArn);
70+
}
71+
72+
/**
73+
* Use an existing route calculator by ARN
74+
*/
75+
public static fromRouteCalculatorArn(scope: Construct, id: string, routeCalculatorArn: string): IRouteCalculator {
76+
const parsedArn = Stack.of(scope).splitArn(routeCalculatorArn, ArnFormat.SLASH_RESOURCE_NAME);
77+
78+
if (!parsedArn.resourceName) {
79+
throw new Error(`Route Calculator Arn ${routeCalculatorArn} does not have a resource name.`);
80+
}
81+
82+
class Import extends Resource implements IRouteCalculator {
83+
public readonly routeCalculatorName = parsedArn.resourceName!;
84+
public readonly routeCalculatorArn = routeCalculatorArn;
85+
}
86+
87+
return new Import(scope, id, {
88+
account: parsedArn.account,
89+
region: parsedArn.region,
90+
});
91+
}
92+
93+
public readonly routeCalculatorName: string;
94+
95+
public readonly routeCalculatorArn: string;
96+
97+
/**
98+
* The timestamp for when the route calculator resource was created in ISO 8601 format
99+
*
100+
* @attribute
101+
*/
102+
public readonly routeCalculatorCreateTime: string;
103+
104+
/**
105+
* The timestamp for when the route calculator resource was last updated in ISO 8601 format
106+
*
107+
* @attribute
108+
*/
109+
public readonly routeCalculatorUpdateTime: string;
110+
111+
constructor(scope: Construct, id: string, props: RouteCalculatorProps) {
112+
113+
if (props.description && !Token.isUnresolved(props.description) && props.description.length > 1000) {
114+
throw new Error(`\`description\` must be between 0 and 1000 characters. Received: ${props.description.length} characters`);
115+
}
116+
117+
if (props.routeCalculatorName && !Token.isUnresolved(props.routeCalculatorName) && !/^[-.\w]{1,100}$/.test(props.routeCalculatorName)) {
118+
throw new Error(`Invalid route calculator name. The route calculator name must be between 1 and 100 characters and contain only alphanumeric characters, hyphens, periods and underscores. Received: ${props.routeCalculatorName}`);
119+
}
120+
121+
super(scope, id, {
122+
physicalName: props.routeCalculatorName ?? Lazy.string({ produce: () => generateUniqueId(this) }),
123+
});
124+
125+
const routeCalculator = new CfnRouteCalculator(this, 'Resource', {
126+
calculatorName: this.physicalName,
127+
dataSource: props.dataSource ?? DataSource.ESRI,
128+
description: props.description,
129+
});
130+
131+
this.routeCalculatorName = routeCalculator.ref;
132+
this.routeCalculatorArn = routeCalculator.attrArn;
133+
this.routeCalculatorCreateTime = routeCalculator.attrCreateTime;
134+
this.routeCalculatorUpdateTime = routeCalculator.attrUpdateTime;
135+
}
136+
137+
/**
138+
* Grant the given principal identity permissions to perform the actions on this route calculator.
139+
*/
140+
public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant {
141+
return iam.Grant.addToPrincipal({
142+
grantee: grantee,
143+
actions: actions,
144+
resourceArns: [this.routeCalculatorArn],
145+
});
146+
}
147+
148+
/**
149+
* Grant the given identity permissions to access to a route calculator resource to calculate a route.
150+
*
151+
* @see https://docs.aws.amazon.com/location/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-calculate-route
152+
*/
153+
public grantRead(grantee: iam.IGrantable): iam.Grant {
154+
return this.grant(grantee,
155+
'geo:CalculateRoute',
156+
);
157+
}
158+
}

packages/@aws-cdk/aws-location-alpha/lib/util.ts

+26
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,29 @@ export function generateUniqueId(context: IConstruct): string {
88
}
99
return name;
1010
}
11+
12+
/**
13+
* Data source for a place index
14+
*/
15+
export enum DataSource {
16+
/**
17+
* Esri
18+
*
19+
* @see https://docs.aws.amazon.com/location/latest/developerguide/esri.html
20+
*/
21+
ESRI = 'Esri',
22+
23+
/**
24+
* Grab provides routing functionality for Southeast Asia.
25+
*
26+
* @see https://docs.aws.amazon.com/location/latest/developerguide/grab.html
27+
*/
28+
GRAB = 'Grab',
29+
30+
/**
31+
* HERE
32+
*
33+
* @see https://docs.aws.amazon.com/location/latest/developerguide/HERE.html
34+
*/
35+
HERE = 'Here',
36+
}

packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets.json

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.template.json

+36
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.assets.json

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"Resources": {
3+
"RouteCalculator0F2D109D": {
4+
"Type": "AWS::Location::RouteCalculator",
5+
"Properties": {
6+
"CalculatorName": "cdkinteglocationroutecalculatorRouteCalculator916939B5",
7+
"DataSource": "Esri"
8+
}
9+
}
10+
},
11+
"Parameters": {
12+
"BootstrapVersion": {
13+
"Type": "AWS::SSM::Parameter::Value<String>",
14+
"Default": "/cdk-bootstrap/hnb659fds/version",
15+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
16+
}
17+
},
18+
"Rules": {
19+
"CheckBootstrapVersion": {
20+
"Assertions": [
21+
{
22+
"Assert": {
23+
"Fn::Not": [
24+
{
25+
"Fn::Contains": [
26+
[
27+
"1",
28+
"2",
29+
"3",
30+
"4",
31+
"5"
32+
],
33+
{
34+
"Ref": "BootstrapVersion"
35+
}
36+
]
37+
}
38+
]
39+
},
40+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
41+
}
42+
]
43+
}
44+
}
45+
}

packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk.out

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)