-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
797 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
160 changes: 160 additions & 0 deletions
160
packages/@aws-cdk/aws-location-alpha/lib/geofence-collection.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import * as iam from 'aws-cdk-lib/aws-iam'; | ||
import * as kms from 'aws-cdk-lib/aws-kms'; | ||
import { ArnFormat, IResource, Lazy, Resource, Stack, Token } from 'aws-cdk-lib/core'; | ||
import { Construct } from 'constructs'; | ||
import { CfnGeofenceCollection } from 'aws-cdk-lib/aws-location'; | ||
import { generateUniqueId } from './util'; | ||
|
||
/** | ||
* A Geofence Collection | ||
*/ | ||
export interface IGeofenceCollection extends IResource { | ||
/** | ||
* The name of the geofence collection | ||
* | ||
* @attribute | ||
*/ | ||
readonly geofenceCollectionName: string; | ||
|
||
/** | ||
* The Amazon Resource Name (ARN) of the geofence collection resource | ||
* | ||
* @attribute Arn, CollectionArn | ||
*/ | ||
readonly geofenceCollectionArn: string; | ||
} | ||
|
||
/** | ||
* Properties for a geofence collection | ||
*/ | ||
export interface GeofenceCollectionProps { | ||
/** | ||
* A name for the geofence collection | ||
* | ||
* @default - A name is automatically generated | ||
*/ | ||
readonly geofenceCollectionName?: string; | ||
|
||
/** | ||
* A description for the geofence collection | ||
* | ||
* @default - no description | ||
*/ | ||
readonly description?: string; | ||
|
||
/** | ||
* The customer managed to encrypt your data. | ||
* | ||
* @default - Use an AWS managed key | ||
* @see https://docs.aws.amazon.com/location/latest/developerguide/encryption-at-rest.html | ||
*/ | ||
readonly kmsKey?: kms.IKey; | ||
} | ||
|
||
abstract class GeofenceCollectionBase extends Resource implements IGeofenceCollection { | ||
public abstract readonly geofenceCollectionName: string; | ||
public abstract readonly geofenceCollectionArn: string; | ||
|
||
/** | ||
* Grant the given principal identity permissions to perform the actions on this geofence collection. | ||
*/ | ||
public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { | ||
return iam.Grant.addToPrincipal({ | ||
grantee: grantee, | ||
actions: actions, | ||
resourceArns: [this.geofenceCollectionArn], | ||
}); | ||
} | ||
|
||
/** | ||
* Grant the given identity permissions to read this geofence collection | ||
* | ||
* See https://docs.aws.amazon.com/location/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-read-only-geofences | ||
*/ | ||
public grantRead(grantee: iam.IGrantable): iam.Grant { | ||
return this.grant(grantee, | ||
'geo:ListGeofences', | ||
'geo:GetGeofence', | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* A Geofence Collection | ||
* | ||
* @see https://docs.aws.amazon.com/location/latest/developerguide/geofence-tracker-concepts.html#geofence-overview | ||
*/ | ||
export class GeofenceCollection extends GeofenceCollectionBase { | ||
/** | ||
* Use an existing geofence collection by name | ||
*/ | ||
public static fromGeofenceCollectionName(scope: Construct, id: string, geofenceCollectionName: string): IGeofenceCollection { | ||
const geofenceCollectionArn = Stack.of(scope).formatArn({ | ||
service: 'geo', | ||
resource: 'geofence-collection', | ||
resourceName: geofenceCollectionName, | ||
}); | ||
|
||
return GeofenceCollection.fromGeofenceCollectionArn(scope, id, geofenceCollectionArn); | ||
} | ||
|
||
/** | ||
* Use an existing geofence collection by ARN | ||
*/ | ||
public static fromGeofenceCollectionArn(scope: Construct, id: string, geofenceCollectionArn: string): IGeofenceCollection { | ||
const parsedArn = Stack.of(scope).splitArn(geofenceCollectionArn, ArnFormat.SLASH_RESOURCE_NAME); | ||
|
||
if (!parsedArn.resourceName) { | ||
throw new Error(`Geofence Collection Arn ${geofenceCollectionArn} does not have a resource name.`); | ||
} | ||
|
||
class Import extends GeofenceCollectionBase { | ||
public readonly geofenceCollectionName = parsedArn.resourceName!; | ||
public readonly geofenceCollectionArn = geofenceCollectionArn; | ||
} | ||
|
||
return new Import(scope, id, { | ||
account: parsedArn.account, | ||
region: parsedArn.region, | ||
}); | ||
} | ||
|
||
public readonly geofenceCollectionName: string; | ||
|
||
public readonly geofenceCollectionArn: string; | ||
|
||
/** | ||
* The timestamp for when the geofence collection resource was created in ISO 8601 forma | ||
* | ||
* @attribute | ||
*/ | ||
public readonly geofenceCollectionCreateTime: string; | ||
|
||
/** | ||
* The timestamp for when the geofence collection resource was last updated in ISO 8601 format | ||
* | ||
* @attribute | ||
*/ | ||
public readonly geofenceCollectionUpdateTime: string; | ||
|
||
constructor(scope: Construct, id: string, props: GeofenceCollectionProps = {}) { | ||
if (props.geofenceCollectionName && !Token.isUnresolved(props.geofenceCollectionName) && !/^[-.\w]{1,100}$/.test(props.geofenceCollectionName)) { | ||
throw new Error(`Invalid geofence collection name. The geofence collection name must be between 1 and 100 characters and contain only alphanumeric characters, hyphens, periods and underscores. Received: ${props.geofenceCollectionName}`); | ||
} | ||
|
||
super(scope, id, { | ||
physicalName: props.geofenceCollectionName ?? Lazy.string({ produce: () => generateUniqueId(this) }), | ||
}); | ||
|
||
const geofenceCollection = new CfnGeofenceCollection(this, 'Resource', { | ||
collectionName: this.physicalName, | ||
description: props.description, | ||
kmsKeyId: props.kmsKey?.keyArn, | ||
}); | ||
|
||
this.geofenceCollectionName = geofenceCollection.ref; | ||
this.geofenceCollectionArn = geofenceCollection.attrArn; | ||
this.geofenceCollectionCreateTime = geofenceCollection.attrCreateTime; | ||
this.geofenceCollectionUpdateTime = geofenceCollection.attrUpdateTime; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './geofence-collection'; | ||
export * from './place-index'; | ||
|
||
// AWS::Location CloudFormation Resources: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Names } from 'aws-cdk-lib/core'; | ||
|
||
export function generateUniqueId(context: any): string { | ||
const name = Names.uniqueId(context); | ||
if (name.length > 100) { | ||
return name.substring(0, 50) + name.substring(name.length - 50); | ||
} | ||
return name; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
packages/@aws-cdk/aws-location-alpha/test/geofence-collection.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { Match, Template } from 'aws-cdk-lib/assertions'; | ||
import * as iam from 'aws-cdk-lib/aws-iam'; | ||
import * as kms from 'aws-cdk-lib/aws-kms'; | ||
import { Stack } from 'aws-cdk-lib'; | ||
import { GeofenceCollection } from '../lib/geofence-collection'; | ||
|
||
let stack: Stack; | ||
beforeEach(() => { | ||
stack = new Stack(); | ||
}); | ||
|
||
test('create a geofence collecction', () => { | ||
new GeofenceCollection(stack, 'GeofenceCollection', { description: 'test' }); | ||
|
||
Template.fromStack(stack).hasResourceProperties('AWS::Location::GeofenceCollection', { | ||
CollectionName: 'GeofenceCollection', | ||
Description: 'test', | ||
}); | ||
}); | ||
|
||
test('throws with invalid name', () => { | ||
expect(() => new GeofenceCollection(stack, 'GeofenceCollection', { | ||
geofenceCollectionName: 'inv@lid', | ||
})).toThrow('Invalid geofence collection name. The geofence collection name must be between 1 and 100 characters and contain only alphanumeric characters, hyphens, periods and underscores. Received: inv@lid'); | ||
}); | ||
|
||
test('grant read actions', () => { | ||
const geofenceCollection = new GeofenceCollection(stack, 'GeofenceCollection', { | ||
}); | ||
|
||
const role = new iam.Role(stack, 'Role', { | ||
assumedBy: new iam.ServicePrincipal('foo'), | ||
}); | ||
|
||
geofenceCollection.grantRead(role); | ||
|
||
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', Match.objectLike({ | ||
PolicyDocument: Match.objectLike({ | ||
Statement: [ | ||
{ | ||
Action: [ | ||
'geo:ListGeofences', | ||
'geo:GetGeofence', | ||
], | ||
Effect: 'Allow', | ||
Resource: { | ||
'Fn::GetAtt': [ | ||
'GeofenceCollection6FAC681F', | ||
'Arn', | ||
], | ||
}, | ||
}, | ||
], | ||
}), | ||
})); | ||
}); | ||
|
||
test('import from arn', () => { | ||
const geofenceCollectionArn = stack.formatArn({ | ||
service: 'geo', | ||
resource: 'geofence-collection', | ||
resourceName: 'MyGeofenceCollection', | ||
}); | ||
const geofenceCollection = GeofenceCollection.fromGeofenceCollectionArn(stack, 'GeofenceCollection', geofenceCollectionArn); | ||
|
||
// THEN | ||
expect(geofenceCollection.geofenceCollectionName).toEqual('MyGeofenceCollection'); | ||
expect(geofenceCollection.geofenceCollectionArn).toEqual(geofenceCollectionArn); | ||
}); | ||
|
||
test('import from name', () => { | ||
// WHEN | ||
const geofenceCollectionName = 'MyGeofenceCollection'; | ||
const geofenceCollection = GeofenceCollection.fromGeofenceCollectionName(stack, 'GeofenceCollection', geofenceCollectionName); | ||
|
||
// THEN | ||
expect(geofenceCollection.geofenceCollectionName).toEqual(geofenceCollectionName); | ||
expect(geofenceCollection.geofenceCollectionArn).toEqual(stack.formatArn({ | ||
service: 'geo', | ||
resource: 'geofence-collection', | ||
resourceName: 'MyGeofenceCollection', | ||
})); | ||
}); | ||
|
||
test('create a geofence collection with a customer managed key)', () => { | ||
// GIVEN | ||
const kmsKey = new kms.Key(stack, 'Key'); | ||
|
||
// WHEN | ||
new GeofenceCollection(stack, 'GeofenceCollection', | ||
{ kmsKey }, | ||
); | ||
|
||
// THEN | ||
Template.fromStack(stack).hasResourceProperties('AWS::Location::GeofenceCollection', { | ||
KmsKeyId: stack.resolve(kmsKey.keyArn), | ||
}); | ||
}); |
19 changes: 19 additions & 0 deletions
19
...-collection.js.snapshot/GeofenceCollectionTestDefaultTestDeployAssert44609017.assets.json
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
36 changes: 36 additions & 0 deletions
36
...ollection.js.snapshot/GeofenceCollectionTestDefaultTestDeployAssert44609017.template.json
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
19 changes: 19 additions & 0 deletions
19
.../integ.geofence-collection.js.snapshot/cdk-integ-location-geofence-collection.assets.json
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.