Skip to content

Commit 50422df

Browse files
authored
feat(location): PlaceIndex (#22853)
Add a L2 for the place index resource. ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [x] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [x] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 8e69c81 commit 50422df

16 files changed

+736
-22
lines changed

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

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,49 @@
99
>
1010
> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib
1111
12+
![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)
13+
14+
> The APIs of higher level constructs in this module are experimental and under active development.
15+
> They are subject to non-backward compatible changes or removal in any future version. These are
16+
> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be
17+
> announced in the release notes. This means that while you may use them, you may need to update
18+
> your source code when upgrading to a newer version of this package.
19+
1220
---
1321

1422
<!--END STABILITY BANNER-->
1523

1624
This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.
1725

18-
```ts nofixture
19-
import * as location from '@aws-cdk/aws-location';
20-
```
21-
22-
<!--BEGIN CFNONLY DISCLAIMER-->
26+
Amazon Location Service lets you add location data and functionality to applications, which
27+
includes capabilities such as maps, points of interest, geocoding, routing, geofences, and
28+
tracking. Amazon Location provides location-based services (LBS) using high-quality data from
29+
global, trusted providers Esri and HERE. With affordable data, tracking and geofencing
30+
capabilities, and built-in metrics for health monitoring, you can build sophisticated
31+
location-enabled applications.
2332

24-
There are no official hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. Here are some suggestions on how to proceed:
33+
## Place Index
2534

26-
- Search [Construct Hub for Location construct libraries](https://constructs.dev/search?q=location)
27-
- Use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, in the same way you would use [the CloudFormation AWS::Location resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Location.html) directly.
35+
A key function of Amazon Location Service is the ability to search the geolocation information.
36+
Amazon Location provides this functionality via the Place index resource. The place index includes
37+
which [data provider](https://docs.aws.amazon.com/location/latest/developerguide/what-is-data-provider.html)
38+
to use for the search.
2839

40+
To create a place index, define a `PlaceIndex`:
2941

30-
<!--BEGIN CFNONLY DISCLAIMER-->
31-
32-
There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet.
33-
However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly.
42+
```ts
43+
new location.PlaceIndex(this, 'PlaceIndex', {
44+
placeIndexName: 'MyPlaceIndex', // optional, defaults to a generated name
45+
dataSource: location.DataSource.HERE, // optional, defaults to Esri
46+
});
47+
```
3448

35-
For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::Location](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Location.html).
49+
Use the `grant()` or `grantSearch()` method to grant the given identity permissions to perform actions
50+
on the place index:
3651

37-
(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and submit an RFC if you are interested in contributing to this construct library.)
52+
```ts
53+
declare const role: iam.Role;
3854

39-
<!--END CFNONLY DISCLAIMER-->
55+
const placeIndex = new location.PlaceIndex(this, 'PlaceIndex');
56+
placeIndex.grantSearch(role);
57+
```
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
export * from './place-index';
2+
13
// AWS::Location CloudFormation Resources:
24
export * from './location.generated';
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import * as iam from '@aws-cdk/aws-iam';
2+
import { ArnFormat, IResource, Lazy, Names, Resource, Stack, Token } from '@aws-cdk/core';
3+
import { Construct } from 'constructs';
4+
import { CfnPlaceIndex } from './location.generated';
5+
6+
/**
7+
* A Place Index
8+
*/
9+
export interface IPlaceIndex extends IResource {
10+
/**
11+
* The name of the place index
12+
*
13+
* @attribute
14+
*/
15+
readonly placeIndexName: string;
16+
17+
/**
18+
* The Amazon Resource Name (ARN) of the place index resource
19+
*
20+
* @attribute Arn,IndexArn
21+
*/
22+
readonly placeIndexArn: string;
23+
}
24+
25+
/**
26+
* Properties for a place index
27+
*/
28+
export interface PlaceIndexProps {
29+
/**
30+
* A name for the place index
31+
*
32+
* @default - A name is automatically generated
33+
*/
34+
readonly placeIndexName?: string;
35+
36+
/**
37+
* Data source for the place index
38+
*
39+
* @default DataSource.ESRI
40+
*/
41+
readonly dataSource?: DataSource;
42+
43+
/**
44+
* Intend use for the results of an operation
45+
*
46+
* @default IntendedUse.SINGLE_USE
47+
*/
48+
readonly intendedUse?: IntendedUse;
49+
50+
/**
51+
* A description for the place index
52+
*
53+
* @default - no description
54+
*/
55+
readonly description?: string;
56+
}
57+
58+
/**
59+
* Data source for a place index
60+
*/
61+
export enum DataSource {
62+
/**
63+
* Esri
64+
*
65+
* @see https://docs.aws.amazon.com/location/latest/developerguide/esri.html
66+
*/
67+
ESRI = 'Esri',
68+
69+
/**
70+
* HERE
71+
*
72+
* @see https://docs.aws.amazon.com/location/latest/developerguide/HERE.html
73+
*/
74+
HERE = 'Here'
75+
}
76+
77+
/**
78+
* Intend use for the results of an operation
79+
*/
80+
export enum IntendedUse {
81+
/**
82+
* The results won't be stored
83+
*/
84+
SINGLE_USE = 'SingleUse',
85+
86+
/**
87+
* The result can be cached or stored in a database
88+
*/
89+
STORAGE = 'Storage'
90+
}
91+
92+
abstract class PlaceIndexBase extends Resource implements IPlaceIndex {
93+
public abstract readonly placeIndexName: string;
94+
public abstract readonly placeIndexArn: string;
95+
96+
/**
97+
* Grant the given principal identity permissions to perform the actions on this place index.
98+
*/
99+
public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant {
100+
return iam.Grant.addToPrincipal({
101+
grantee: grantee,
102+
actions: actions,
103+
resourceArns: [this.placeIndexArn],
104+
});
105+
}
106+
107+
/**
108+
* Grant the given identity permissions to search using this index
109+
*/
110+
public grantSearch(grantee: iam.IGrantable): iam.Grant {
111+
return this.grant(grantee,
112+
'geo:SearchPlaceIndexForPosition',
113+
'geo:SearchPlaceIndexForSuggestions',
114+
'geo:SearchPlaceIndexForText',
115+
);
116+
}
117+
}
118+
119+
/**
120+
* A Place Index
121+
*
122+
* @see https://docs.aws.amazon.com/location/latest/developerguide/places-concepts.html
123+
*/
124+
export class PlaceIndex extends PlaceIndexBase {
125+
/**
126+
* Use an existing place index by name
127+
*/
128+
public static fromPlaceIndexName(scope: Construct, id: string, placeIndexName: string): IPlaceIndex {
129+
const placeIndexArn = Stack.of(scope).formatArn({
130+
service: 'geo',
131+
resource: 'place-index',
132+
resourceName: placeIndexName,
133+
});
134+
135+
return PlaceIndex.fromPlaceIndexArn(scope, id, placeIndexArn);
136+
}
137+
138+
/**
139+
* Use an existing place index by ARN
140+
*/
141+
public static fromPlaceIndexArn(scope: Construct, id: string, placeIndexArn: string): IPlaceIndex {
142+
const parsedArn = Stack.of(scope).splitArn(placeIndexArn, ArnFormat.SLASH_RESOURCE_NAME);
143+
144+
if (!parsedArn.resourceName) {
145+
throw new Error(`Place Index Arn ${placeIndexArn} does not have a resource name.`);
146+
}
147+
148+
class Import extends PlaceIndexBase {
149+
public readonly placeIndexName = parsedArn.resourceName!;
150+
public readonly placeIndexArn = placeIndexArn;
151+
}
152+
153+
return new Import(scope, id, {
154+
account: parsedArn.account,
155+
region: parsedArn.region,
156+
});
157+
}
158+
159+
public readonly placeIndexName: string;
160+
161+
public readonly placeIndexArn: string;
162+
163+
/**
164+
* The timestamp for when the place index resource was created in ISO 8601 forma
165+
*
166+
* @attribute
167+
*/
168+
public readonly placeIndexCreateTime: string;
169+
170+
/**
171+
* The timestamp for when the place index resource was last updated in ISO 8601 format
172+
*
173+
* @attribute
174+
*/
175+
public readonly placeIndexUpdateTime: string;
176+
177+
178+
constructor(scope: Construct, id: string, props: PlaceIndexProps = {}) {
179+
if (props.placeIndexName && !Token.isUnresolved(props.placeIndexName) && !/^[-.\w]{1,100}$/.test(props.placeIndexName)) {
180+
throw new Error(`Invalid place index name. The place index name must be between 1 and 100 characters and contain only alphanumeric characters, hyphens, periods and underscores. Received: ${props.placeIndexName}`);
181+
}
182+
183+
super(scope, id, {
184+
physicalName: props.placeIndexName ?? Lazy.string({ produce: () => this.generateUniqueId() }),
185+
});
186+
187+
const placeIndex = new CfnPlaceIndex(this, 'Resource', {
188+
indexName: this.physicalName,
189+
dataSource: props.dataSource ?? DataSource.ESRI,
190+
dataSourceConfiguration: props.intendedUse
191+
? { intendedUse: props.intendedUse }
192+
: undefined,
193+
description: props.description,
194+
});
195+
196+
this.placeIndexName = placeIndex.ref;
197+
this.placeIndexArn = placeIndex.attrArn;
198+
this.placeIndexCreateTime = placeIndex.attrCreateTime;
199+
this.placeIndexUpdateTime = placeIndex.attrUpdateTime;
200+
}
201+
202+
private generateUniqueId(): string {
203+
const name = Names.uniqueId(this);
204+
if (name.length > 100) {
205+
return name.substring(0, 50) + name.substring(name.length - 50);
206+
}
207+
return name;
208+
}
209+
}

packages/@aws-cdk/aws-location/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,23 +85,27 @@
8585
"devDependencies": {
8686
"@aws-cdk/assertions": "0.0.0",
8787
"@aws-cdk/cdk-build-tools": "0.0.0",
88+
"@aws-cdk/integ-runner": "0.0.0",
89+
"@aws-cdk/integ-tests": "0.0.0",
8890
"@aws-cdk/cfn2ts": "0.0.0",
8991
"@aws-cdk/pkglint": "0.0.0",
9092
"@types/jest": "^27.5.2"
9193
},
9294
"dependencies": {
9395
"@aws-cdk/core": "0.0.0",
96+
"@aws-cdk/aws-iam": "0.0.0",
9497
"constructs": "^10.0.0"
9598
},
9699
"peerDependencies": {
97100
"@aws-cdk/core": "0.0.0",
101+
"@aws-cdk/aws-iam": "0.0.0",
98102
"constructs": "^10.0.0"
99103
},
100104
"engines": {
101105
"node": ">= 14.15.0"
102106
},
103107
"stability": "experimental",
104-
"maturity": "cfn-only",
108+
"maturity": "experimental",
105109
"awscdkio": {
106110
"announce": false
107111
},
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Fixture with packages imported, but nothing else
2+
import { Stack } from '@aws-cdk/core';
3+
import { Construct } from 'constructs';
4+
import * as location from '@aws-cdk/aws-location';
5+
import * as iam from '@aws-cdk/aws-iam';
6+
7+
class Fixture extends Stack {
8+
constructor(scope: Construct, id: string) {
9+
super(scope, id);
10+
11+
/// here
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
5+
"source": {
6+
"path": "PlaceIndexTestDefaultTestDeployAssert3F96C508.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"Parameters": {
3+
"BootstrapVersion": {
4+
"Type": "AWS::SSM::Parameter::Value<String>",
5+
"Default": "/cdk-bootstrap/hnb659fds/version",
6+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
7+
}
8+
},
9+
"Rules": {
10+
"CheckBootstrapVersion": {
11+
"Assertions": [
12+
{
13+
"Assert": {
14+
"Fn::Not": [
15+
{
16+
"Fn::Contains": [
17+
[
18+
"1",
19+
"2",
20+
"3",
21+
"4",
22+
"5"
23+
],
24+
{
25+
"Ref": "BootstrapVersion"
26+
}
27+
]
28+
}
29+
]
30+
},
31+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
32+
}
33+
]
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)