From 574d383ef0a5b78564bbba76e5a14a049129c042 Mon Sep 17 00:00:00 2001 From: mazyu36 Date: Fri, 30 Aug 2024 09:39:40 +0900 Subject: [PATCH] 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* --- .../@aws-cdk/aws-location-alpha/README.md | 27 +++ .../@aws-cdk/aws-location-alpha/lib/index.ts | 2 + .../aws-location-alpha/lib/place-index.ts | 21 +-- .../lib/route-calculator.ts | 158 ++++++++++++++++++ .../@aws-cdk/aws-location-alpha/lib/util.ts | 26 +++ ...efaultTestDeployAssert5893D6F4.assets.json | 19 +++ ...aultTestDeployAssert5893D6F4.template.json | 36 ++++ ...nteg-location-route-calculator.assets.json | 19 +++ ...eg-location-route-calculator.template.json | 45 +++++ .../cdk.out | 1 + .../integ.json | 12 ++ .../manifest.json | 113 +++++++++++++ .../tree.json | 126 ++++++++++++++ .../test/integ.route-calculator.ts | 21 +++ .../test/place-index.test.ts | 3 +- .../test/route-calculator.test.ts | 102 +++++++++++ 16 files changed, 710 insertions(+), 21 deletions(-) create mode 100644 packages/@aws-cdk/aws-location-alpha/lib/route-calculator.ts create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets.json create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.template.json create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.assets.json create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.template.json create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.ts create mode 100644 packages/@aws-cdk/aws-location-alpha/test/route-calculator.test.ts diff --git a/packages/@aws-cdk/aws-location-alpha/README.md b/packages/@aws-cdk/aws-location-alpha/README.md index 33398554e31fd..810c29532a163 100644 --- a/packages/@aws-cdk/aws-location-alpha/README.md +++ b/packages/@aws-cdk/aws-location-alpha/README.md @@ -77,3 +77,30 @@ const geofenceCollection = new location.GeofenceCollection(this, 'GeofenceCollec geofenceCollection.grantRead(role); ``` + +## Route Calculator + +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. + +For more information, see [Routes](https://docs.aws.amazon.com/location/latest/developerguide/route-concepts.html). + +To create a route calculator, define a `RouteCalculator`: + +```ts +new location.RouteCalculator(this, 'RouteCalculator', { + routeCalculatorName: 'MyRouteCalculator', // optional, defaults to a generated name + dataSource: location.DataSource.ESRI, +}); +``` + +Use the `grant()` or `grantRead()` method to grant the given identity permissions to perform actions +on the route calculator: + +```ts +declare const role: iam.Role; + +const routeCalculator = new location.RouteCalculator(this, 'RouteCalculator', { + dataSource: location.DataSource.ESRI, +}); +routeCalculator.grantRead(role); +``` diff --git a/packages/@aws-cdk/aws-location-alpha/lib/index.ts b/packages/@aws-cdk/aws-location-alpha/lib/index.ts index 2dbba33a53f09..7a5cee74e9bdd 100644 --- a/packages/@aws-cdk/aws-location-alpha/lib/index.ts +++ b/packages/@aws-cdk/aws-location-alpha/lib/index.ts @@ -1,4 +1,6 @@ export * from './geofence-collection'; export * from './place-index'; +export * from './route-calculator'; +export * from './util'; // AWS::Location CloudFormation Resources: diff --git a/packages/@aws-cdk/aws-location-alpha/lib/place-index.ts b/packages/@aws-cdk/aws-location-alpha/lib/place-index.ts index 34f35264b7ad4..026d8c5268a68 100644 --- a/packages/@aws-cdk/aws-location-alpha/lib/place-index.ts +++ b/packages/@aws-cdk/aws-location-alpha/lib/place-index.ts @@ -2,7 +2,7 @@ import * as iam from 'aws-cdk-lib/aws-iam'; import { ArnFormat, IResource, Lazy, Resource, Stack, Token } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; import { CfnPlaceIndex } from 'aws-cdk-lib/aws-location'; -import { generateUniqueId } from './util'; +import { DataSource, generateUniqueId } from './util'; /** * A Place Index @@ -59,25 +59,6 @@ export interface PlaceIndexProps { readonly description?: string; } -/** - * Data source for a place index - */ -export enum DataSource { - /** - * Esri - * - * @see https://docs.aws.amazon.com/location/latest/developerguide/esri.html - */ - ESRI = 'Esri', - - /** - * HERE - * - * @see https://docs.aws.amazon.com/location/latest/developerguide/HERE.html - */ - HERE = 'Here', -} - /** * Intend use for the results of an operation */ diff --git a/packages/@aws-cdk/aws-location-alpha/lib/route-calculator.ts b/packages/@aws-cdk/aws-location-alpha/lib/route-calculator.ts new file mode 100644 index 0000000000000..68544c461651c --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/lib/route-calculator.ts @@ -0,0 +1,158 @@ +import * as iam from 'aws-cdk-lib/aws-iam'; +import { ArnFormat, IResource, Lazy, Resource, Stack, Token } from 'aws-cdk-lib/core'; +import { Construct } from 'constructs'; +import { CfnRouteCalculator } from 'aws-cdk-lib/aws-location'; +import { generateUniqueId, DataSource } from './util'; + +/** + * A Route Calculator + */ +export interface IRouteCalculator extends IResource { + /** + * The name of the route calculator + * + * @attribute + */ + readonly routeCalculatorName: string; + + /** + * The Amazon Resource Name (ARN) of the route calculator resource + * + * @attribute Arn,CalculatorArn + */ + readonly routeCalculatorArn: string; +} + +/** + * Properties for a route calculator + */ +export interface RouteCalculatorProps { + /** + * A name for the route calculator + * + * Must be between 1 and 100 characters and contain only alphanumeric characters, + * hyphens, periods and underscores. + * + * @default - A name is automatically generated + */ + readonly routeCalculatorName?: string; + + /** + * Data source for the route calculator + */ + readonly dataSource: DataSource; + + /** + * A description for the route calculator + * + * @default - no description + */ + readonly description?: string; +} + +/** + * A Route Calculator + * + * @see https://docs.aws.amazon.com/location/latest/developerguide/places-concepts.html + */ +export class RouteCalculator extends Resource implements IRouteCalculator { + /** + * Use an existing route calculator by name + */ + public static fromRouteCalculatorName(scope: Construct, id: string, routeCalculatorName: string): IRouteCalculator { + const routeCalculatorArn = Stack.of(scope).formatArn({ + service: 'geo', + resource: 'route-calculator', + resourceName: routeCalculatorName, + }); + + return RouteCalculator.fromRouteCalculatorArn(scope, id, routeCalculatorArn); + } + + /** + * Use an existing route calculator by ARN + */ + public static fromRouteCalculatorArn(scope: Construct, id: string, routeCalculatorArn: string): IRouteCalculator { + const parsedArn = Stack.of(scope).splitArn(routeCalculatorArn, ArnFormat.SLASH_RESOURCE_NAME); + + if (!parsedArn.resourceName) { + throw new Error(`Route Calculator Arn ${routeCalculatorArn} does not have a resource name.`); + } + + class Import extends Resource implements IRouteCalculator { + public readonly routeCalculatorName = parsedArn.resourceName!; + public readonly routeCalculatorArn = routeCalculatorArn; + } + + return new Import(scope, id, { + account: parsedArn.account, + region: parsedArn.region, + }); + } + + public readonly routeCalculatorName: string; + + public readonly routeCalculatorArn: string; + + /** + * The timestamp for when the route calculator resource was created in ISO 8601 format + * + * @attribute + */ + public readonly routeCalculatorCreateTime: string; + + /** + * The timestamp for when the route calculator resource was last updated in ISO 8601 format + * + * @attribute + */ + public readonly routeCalculatorUpdateTime: string; + + constructor(scope: Construct, id: string, props: RouteCalculatorProps) { + + if (props.description && !Token.isUnresolved(props.description) && props.description.length > 1000) { + throw new Error(`\`description\` must be between 0 and 1000 characters. Received: ${props.description.length} characters`); + } + + if (props.routeCalculatorName && !Token.isUnresolved(props.routeCalculatorName) && !/^[-.\w]{1,100}$/.test(props.routeCalculatorName)) { + 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}`); + } + + super(scope, id, { + physicalName: props.routeCalculatorName ?? Lazy.string({ produce: () => generateUniqueId(this) }), + }); + + const routeCalculator = new CfnRouteCalculator(this, 'Resource', { + calculatorName: this.physicalName, + dataSource: props.dataSource ?? DataSource.ESRI, + description: props.description, + }); + + this.routeCalculatorName = routeCalculator.ref; + this.routeCalculatorArn = routeCalculator.attrArn; + this.routeCalculatorCreateTime = routeCalculator.attrCreateTime; + this.routeCalculatorUpdateTime = routeCalculator.attrUpdateTime; + } + + /** + * Grant the given principal identity permissions to perform the actions on this route calculator. + */ + public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { + return iam.Grant.addToPrincipal({ + grantee: grantee, + actions: actions, + resourceArns: [this.routeCalculatorArn], + }); + } + + /** + * Grant the given identity permissions to access to a route calculator resource to calculate a route. + * + * @see https://docs.aws.amazon.com/location/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-calculate-route + */ + public grantRead(grantee: iam.IGrantable): iam.Grant { + return this.grant(grantee, + 'geo:CalculateRoute', + ); + } +} diff --git a/packages/@aws-cdk/aws-location-alpha/lib/util.ts b/packages/@aws-cdk/aws-location-alpha/lib/util.ts index ff0871f6836ff..01b2ea55246ce 100644 --- a/packages/@aws-cdk/aws-location-alpha/lib/util.ts +++ b/packages/@aws-cdk/aws-location-alpha/lib/util.ts @@ -8,3 +8,29 @@ export function generateUniqueId(context: IConstruct): string { } return name; } + +/** + * Data source for a place index + */ +export enum DataSource { + /** + * Esri + * + * @see https://docs.aws.amazon.com/location/latest/developerguide/esri.html + */ + ESRI = 'Esri', + + /** + * Grab provides routing functionality for Southeast Asia. + * + * @see https://docs.aws.amazon.com/location/latest/developerguide/grab.html + */ + GRAB = 'Grab', + + /** + * HERE + * + * @see https://docs.aws.amazon.com/location/latest/developerguide/HERE.html + */ + HERE = 'Here', +} diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets.json b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets.json new file mode 100644 index 0000000000000..97878c576a8a3 --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "RouteCalculatorTestDefaultTestDeployAssert5893D6F4.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.template.json b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/RouteCalculatorTestDefaultTestDeployAssert5893D6F4.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.assets.json b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.assets.json new file mode 100644 index 0000000000000..35d71aad006c3 --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "9c3ad46df5bdc598d0888e79b52076902e574e459c6c7be174d971890d175b88": { + "source": { + "path": "cdk-integ-location-route-calculator.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "9c3ad46df5bdc598d0888e79b52076902e574e459c6c7be174d971890d175b88.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.template.json b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.template.json new file mode 100644 index 0000000000000..14dcd7dac3bb1 --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk-integ-location-route-calculator.template.json @@ -0,0 +1,45 @@ +{ + "Resources": { + "RouteCalculator0F2D109D": { + "Type": "AWS::Location::RouteCalculator", + "Properties": { + "CalculatorName": "cdkinteglocationroutecalculatorRouteCalculator916939B5", + "DataSource": "Esri" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk.out b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/integ.json b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/integ.json new file mode 100644 index 0000000000000..2ae63358d507b --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "RouteCalculatorTest/DefaultTest": { + "stacks": [ + "cdk-integ-location-route-calculator" + ], + "assertionStack": "RouteCalculatorTest/DefaultTest/DeployAssert", + "assertionStackName": "RouteCalculatorTestDefaultTestDeployAssert5893D6F4" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/manifest.json b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/manifest.json new file mode 100644 index 0000000000000..70a6b73e03376 --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/manifest.json @@ -0,0 +1,113 @@ +{ + "version": "36.0.0", + "artifacts": { + "cdk-integ-location-route-calculator.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdk-integ-location-route-calculator.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdk-integ-location-route-calculator": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdk-integ-location-route-calculator.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9c3ad46df5bdc598d0888e79b52076902e574e459c6c7be174d971890d175b88.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "cdk-integ-location-route-calculator.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "cdk-integ-location-route-calculator.assets" + ], + "metadata": { + "/cdk-integ-location-route-calculator/RouteCalculator/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RouteCalculator0F2D109D" + } + ], + "/cdk-integ-location-route-calculator/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-location-route-calculator/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-location-route-calculator" + }, + "RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "RouteCalculatorTestDefaultTestDeployAssert5893D6F4": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "RouteCalculatorTestDefaultTestDeployAssert5893D6F4.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "RouteCalculatorTestDefaultTestDeployAssert5893D6F4.assets" + ], + "metadata": { + "/RouteCalculatorTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/RouteCalculatorTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "RouteCalculatorTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/tree.json b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/tree.json new file mode 100644 index 0000000000000..6deeb865fe4e6 --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.js.snapshot/tree.json @@ -0,0 +1,126 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "cdk-integ-location-route-calculator": { + "id": "cdk-integ-location-route-calculator", + "path": "cdk-integ-location-route-calculator", + "children": { + "RouteCalculator": { + "id": "RouteCalculator", + "path": "cdk-integ-location-route-calculator/RouteCalculator", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-integ-location-route-calculator/RouteCalculator/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Location::RouteCalculator", + "aws:cdk:cloudformation:props": { + "calculatorName": "cdkinteglocationroutecalculatorRouteCalculator916939B5", + "dataSource": "Esri" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_location.CfnRouteCalculator", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-location-route-calculator/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-location-route-calculator/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "RouteCalculatorTest": { + "id": "RouteCalculatorTest", + "path": "RouteCalculatorTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "RouteCalculatorTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "RouteCalculatorTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "RouteCalculatorTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "RouteCalculatorTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "RouteCalculatorTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.ts b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.ts new file mode 100644 index 0000000000000..4044e333bb40f --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/integ.route-calculator.ts @@ -0,0 +1,21 @@ +import { App, Stack } from 'aws-cdk-lib'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import { Construct } from 'constructs'; +import { DataSource } from '../lib'; +import { RouteCalculator } from '../lib/route-calculator'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new RouteCalculator(this, 'RouteCalculator', { + dataSource: DataSource.ESRI, + }); + } +} + +const app = new App(); + +new integ.IntegTest(app, 'RouteCalculatorTest', { + testCases: [new TestStack(app, 'cdk-integ-location-route-calculator')], +}); diff --git a/packages/@aws-cdk/aws-location-alpha/test/place-index.test.ts b/packages/@aws-cdk/aws-location-alpha/test/place-index.test.ts index a600705339445..610de8421a424 100644 --- a/packages/@aws-cdk/aws-location-alpha/test/place-index.test.ts +++ b/packages/@aws-cdk/aws-location-alpha/test/place-index.test.ts @@ -1,7 +1,8 @@ import { Match, Template } from 'aws-cdk-lib/assertions'; import * as iam from 'aws-cdk-lib/aws-iam'; import { Stack } from 'aws-cdk-lib'; -import { DataSource, IntendedUse, PlaceIndex } from '../lib/place-index'; +import { IntendedUse, PlaceIndex } from '../lib/place-index'; +import { DataSource } from '../lib'; let stack: Stack; beforeEach(() => { diff --git a/packages/@aws-cdk/aws-location-alpha/test/route-calculator.test.ts b/packages/@aws-cdk/aws-location-alpha/test/route-calculator.test.ts new file mode 100644 index 0000000000000..85ed0dce2e6b6 --- /dev/null +++ b/packages/@aws-cdk/aws-location-alpha/test/route-calculator.test.ts @@ -0,0 +1,102 @@ +import { Match, Template } from 'aws-cdk-lib/assertions'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { Stack } from 'aws-cdk-lib'; +import { DataSource } from '../lib'; +import { RouteCalculator } from '../lib/route-calculator'; + +let stack: Stack; +beforeEach(() => { + stack = new Stack(); +}); + +test('create a route calculator', () => { + new RouteCalculator(stack, 'RouteCalculator', { + dataSource: DataSource.ESRI, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Location::RouteCalculator', { + DataSource: 'Esri', + CalculatorName: 'RouteCalculator', + }); +}); + +test('creates a route calculator with empty description', () => { + new RouteCalculator(stack, 'RouteCalculator', { + description: '', + dataSource: DataSource.ESRI, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Location::RouteCalculator', { + Description: '', + }); +}); + +test('throws with invalid description', () => { + expect(() => new RouteCalculator(stack, 'RouteCalculator', { + description: 'a'.repeat(1001), + dataSource: DataSource.ESRI, + })).toThrow('`description` must be between 0 and 1000 characters. Received: 1001 characters'); +}); + +test('throws with invalid name', () => { + expect(() => new RouteCalculator(stack, 'RouteCalculator', { + routeCalculatorName: 'inv@lid', + dataSource: DataSource.ESRI, + })).toThrow(/Invalid route calculator name/); +}); + +test('grant read actions', () => { + const routeCalculator = new RouteCalculator(stack, 'RouteCalculator', { + dataSource: DataSource.HERE, + }); + + const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.ServicePrincipal('foo'), + }); + + routeCalculator.grantRead(role); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', Match.objectLike({ + PolicyDocument: Match.objectLike({ + Statement: [ + { + Action: 'geo:CalculateRoute', + Effect: 'Allow', + Resource: { + 'Fn::GetAtt': [ + 'RouteCalculator0F2D109D', + 'Arn', + ], + }, + }, + ], + }), + })); +}); + +test('import from arn', () => { + const routeCalculatorArn = stack.formatArn({ + service: 'geo', + resource: 'route-calculator', + resourceName: 'MyRouteCalculator', + }); + const routeCalculator = RouteCalculator.fromRouteCalculatorArn(stack, 'RouteCalculator', routeCalculatorArn); + + // THEN + expect(routeCalculator.routeCalculatorName).toEqual('MyRouteCalculator'); + expect(routeCalculator.routeCalculatorArn).toEqual(routeCalculatorArn); +}); + +test('import from name', () => { + // WHEN + const routeCalculatorName = 'MyRouteCalculator'; + const routeCalculator = RouteCalculator.fromRouteCalculatorName(stack, 'RouteCalculator', routeCalculatorName); + + // THEN + expect(routeCalculator.routeCalculatorName).toEqual(routeCalculatorName); + expect(routeCalculator.routeCalculatorArn).toEqual(stack.formatArn({ + service: 'geo', + resource: 'route-calculator', + resourceName: 'MyRouteCalculator', + })); +});