Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@ export type AwsSdkMetadata = {[key: string]: any};

const awsSdkMetadata: AwsSdkMetadata = metadata;

/**
* Physical ID of the custom resource.
*/
export class PhysicalResourceId {

/**
* Construct a resource id from the path to the data in the API call response.
*/
public static fromResponsePath(responsePath: string): PhysicalResourceId {
return new PhysicalResourceId(responsePath, undefined);
}

/**
* Construct a resource id from an explicit id.
*/
public static fromLiteralString(literalId: string): PhysicalResourceId {
return new PhysicalResourceId(undefined, literalId);
}

/**
* @param responsePath Path to a response data element to be used as the physical id.
* @param literalId Literal string to be used as the physical id.
*/
private constructor(public readonly responsePath?: string, public readonly literalId?: string) { }
}

/**
* An AWS SDK call.
*/
Expand All @@ -42,22 +68,12 @@ export interface AwsSdkCall {
readonly parameters?: any;

/**
* The path to the data in the API call response to use as the physical
* resource id. Either `physicalResourceId` or `physicalResourceIdPath`
* must be specified for onCreate or onUpdate calls.
*
* @default - no path
*/
readonly physicalResourceIdPath?: string;

/**
* The physical resource id of the custom resource for this call. Either
* `physicalResourceId` or `physicalResourceIdPath` must be specified for
* onCreate or onUpdate calls.
* The physical resource id of the custom resource for this call.
* Mandatory for onCreate or onUpdate calls.
*
* @default - no physical resource id
*/
readonly physicalResourceId?: string;
readonly physicalResourceId?: PhysicalResourceId;

/**
* The regex pattern to use to catch API errors. The `code` property of the
Expand Down Expand Up @@ -174,8 +190,8 @@ export class AwsCustomResource extends cdk.Construct implements iam.IGrantable {
}

for (const call of [props.onCreate, props.onUpdate]) {
if (call && !call.physicalResourceId && !call.physicalResourceIdPath) {
throw new Error('Either `physicalResourceId` or `physicalResourceIdPath` must be specified for onCreate and onUpdate calls.');
if (call && !call.physicalResourceId) {
throw new Error('`physicalResourceId` must be specified for onCreate and onUpdate calls.');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
let physicalResourceId: string;
switch (event.RequestType) {
case 'Create':
physicalResourceId = event.ResourceProperties.Create?.physicalResourceId ??
event.ResourceProperties.Update?.physicalResourceId ??
event.ResourceProperties.Delete?.physicalResourceId ??
physicalResourceId = event.ResourceProperties.Create?.physicalResourceId.id ??
event.ResourceProperties.Update?.physicalResourceId.id ??
event.ResourceProperties.Delete?.physicalResourceId.id ??
event.LogicalResourceId;
break;
case 'Update':
case 'Delete':
physicalResourceId = event.ResourceProperties[event.RequestType]?.physicalResourceId ?? event.PhysicalResourceId;
physicalResourceId = event.ResourceProperties[event.RequestType]?.physicalResourceId.id ?? event.PhysicalResourceId;
break;
}

Expand Down Expand Up @@ -127,8 +127,8 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
}
}

if (call.physicalResourceIdPath) {
physicalResourceId = flatData[call.physicalResourceIdPath];
if (call.physicalResourceId?.responsePath) {
physicalResourceId = flatData[call.physicalResourceId.responsePath];
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import '@aws-cdk/assert/jest';
import * as iam from '@aws-cdk/aws-iam';
import * as cdk from '@aws-cdk/core';
import { AwsCustomResource } from '../../lib';
import { AwsCustomResource, PhysicalResourceId } from '../../lib';

// tslint:disable:object-literal-key-quotes

Expand All @@ -19,7 +19,7 @@ test('aws sdk js custom resource with onCreate and onDelete', () => {
logGroupName: '/aws/lambda/loggroup',
retentionInDays: 90
},
physicalResourceId: 'loggroup'
physicalResourceId: PhysicalResourceId.fromLiteralString('loggroup')
},
onDelete: {
service: 'CloudWatchLogs',
Expand Down Expand Up @@ -84,7 +84,7 @@ test('onCreate defaults to onUpdate', () => {
Key: 'my-key',
Body: 'my-body'
},
physicalResourceIdPath: 'ETag'
physicalResourceId: PhysicalResourceId.fromResponsePath('ETag')
},
});

Expand Down Expand Up @@ -127,7 +127,7 @@ test('with custom policyStatements', () => {
Key: 'my-key',
Body: 'my-body'
},
physicalResourceIdPath: 'ETag'
physicalResourceId: PhysicalResourceId.fromResponsePath('ETag')
},
policyStatements: [
new iam.PolicyStatement({
Expand Down Expand Up @@ -169,7 +169,7 @@ test('fails when no physical resource method is specified', () => {
retentionInDays: 90
}
}
})).toThrow(/`physicalResourceId`.+`physicalResourceIdPath`/);
})).toThrow(/`physicalResourceId`/);
});

test('encodes booleans', () => {
Expand All @@ -188,7 +188,7 @@ test('encodes booleans', () => {
falseBoolean: false,
falseString: 'false'
},
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromResponsePath('id')
},
});

Expand Down Expand Up @@ -217,7 +217,7 @@ test('timeout defaults to 2 minutes', () => {
onCreate: {
service: 'service',
action: 'action',
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromLiteralString('id')
}
});

Expand All @@ -236,7 +236,7 @@ test('can specify timeout', () => {
onCreate: {
service: 'service',
action: 'action',
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromLiteralString('id')
},
timeout: cdk.Duration.minutes(15)
});
Expand All @@ -257,7 +257,7 @@ test('implements IGrantable', () => {
onCreate: {
service: 'service',
action: 'action',
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromLiteralString('id')
}
});

Expand Down Expand Up @@ -298,7 +298,7 @@ test('can use existing role', () => {
onCreate: {
service: 'service',
action: 'action',
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromLiteralString('id')
},
role
});
Expand All @@ -318,7 +318,7 @@ test('getData', () => {
onCreate: {
service: 'service',
action: 'action',
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromLiteralString('id')
}
});

Expand All @@ -341,7 +341,7 @@ test('getDataString', () => {
onCreate: {
service: 'service',
action: 'action',
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromLiteralString('id')
}
});

Expand All @@ -353,7 +353,7 @@ test('getDataString', () => {
parameters: {
a: awsSdk.getDataString('Data')
},
physicalResourceId: 'id'
physicalResourceId: PhysicalResourceId.fromLiteralString('id')
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import * as sns from '@aws-cdk/aws-sns';
import * as ssm from '@aws-cdk/aws-ssm';
import * as cdk from '@aws-cdk/core';
import { AwsCustomResource } from '../../lib';
import { AwsCustomResource, PhysicalResourceId } from '../../lib';

const app = new cdk.App();

Expand All @@ -19,15 +19,15 @@ const snsPublish = new AwsCustomResource(stack, 'Publish', {
Message: 'hello',
TopicArn: topic.topicArn
},
physicalResourceId: topic.topicArn,
physicalResourceId: PhysicalResourceId.fromLiteralString(topic.topicArn),
}
});

const listTopics = new AwsCustomResource(stack, 'ListTopics', {
onUpdate: {
service: 'SNS',
action: 'listTopics',
physicalResourceIdPath: 'Topics.0.TopicArn'
physicalResourceId: PhysicalResourceId.fromResponsePath('Topics.0.TopicArn')
}
});
listTopics.node.addDependency(topic);
Expand All @@ -44,7 +44,7 @@ const getParameter = new AwsCustomResource(stack, 'GetParameter', {
Name: ssmParameter.parameterName,
WithDecryption: true
},
physicalResourceIdPath: 'Parameter.ARN'
physicalResourceId: PhysicalResourceId.fromResponsePath('Parameter.ARN')
}
});

Expand Down