From 94b0060cd632468c3e3e1f7768637845db73c1cd Mon Sep 17 00:00:00 2001 From: James Fleming Date: Fri, 2 Jul 2021 19:29:08 +0000 Subject: [PATCH 01/27] feat(lambda): enable insights for function --- packages/@aws-cdk/aws-lambda/lib/function.ts | 29 ++++++++++++++- packages/@aws-cdk/aws-lambda/lib/index.ts | 2 +- .../aws-lambda/lib/lambda-insights.ts | 24 ++++++++++++ .../aws-lambda/test/lambda-insights.test.ts | 37 +++++++++++++++++++ 4 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts create mode 100644 packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index 93777c3394a9c..e1d87174a8045 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -15,9 +15,10 @@ import { FileSystem } from './filesystem'; import { FunctionAttributes, FunctionBase, IFunction } from './function-base'; import { calculateFunctionHash, trimFromStart } from './function-hash'; import { Handler } from './handler'; +import { LambdaInsightsVersion } from './lambda-insights'; import { Version, VersionOptions } from './lambda-version'; import { CfnFunction } from './lambda.generated'; -import { ILayerVersion } from './layers'; +import { LayerVersion, ILayerVersion } from './layers'; import { Runtime } from './runtime'; // keep this import separate from other imports to reduce chance for merge conflicts with v2-main @@ -214,6 +215,14 @@ export interface FunctionOptions extends EventInvokeConfigOptions { */ readonly profilingGroup?: IProfilingGroup; + /** + * Enable Lambda Insights + * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights.html + * + * @default - No Lambda Insights + */ + readonly insightsVersion?: LambdaInsightsVersion; + /** * A list of layers to add to the function's execution environment. You can configure your Lambda function to pull in * additional code during initialization in the form of layers. Layers are packages of libraries or other dependencies @@ -649,7 +658,7 @@ export class Function extends FunctionBase { zipFile: code.inlineCode, imageUri: code.image?.imageUri, }, - layers: Lazy.list({ produce: () => this.layers.map(layer => layer.layerVersionArn) }, { omitEmpty: true }), + layers: Lazy.list({ produce: () => this.layers.map(layer => layer.layerVersionArn) }, { omitEmpty: true }), // Evaluated on synthesis handler: props.handler === Handler.FROM_IMAGE ? undefined : props.handler, timeout: props.timeout && props.timeout.toSeconds(), packageType: props.runtime === Runtime.FROM_IMAGE ? 'Image' : undefined, @@ -747,6 +756,11 @@ export class Function extends FunctionBase { }); }); } + + // Configure Lambda insights + if (props.insightsVersion !== undefined) { + this.configureLambdaInsights(props.insightsVersion); + } } /** @@ -863,6 +877,17 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett return; } + /** + * Configured lambda insights on the function if specified. This is acheived by adding an imported layer which is added to the + * list of lambda layers on synthesis. + * + * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html + */ + private configureLambdaInsights(insightsVersion: LambdaInsightsVersion): void { + this.addLayers(LayerVersion.fromLayerVersionArn(this, 'LambdaInsightsLayer', insightsVersion.layerVersionArn)); + this.role?.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLambdaInsightsExecutionRolePolicy')); + } + private renderEnvironment() { if (!this.environment || Object.keys(this.environment).length === 0) { return undefined; diff --git a/packages/@aws-cdk/aws-lambda/lib/index.ts b/packages/@aws-cdk/aws-lambda/lib/index.ts index 2d936755d6ad1..41c77bb8d038d 100644 --- a/packages/@aws-cdk/aws-lambda/lib/index.ts +++ b/packages/@aws-cdk/aws-lambda/lib/index.ts @@ -17,7 +17,7 @@ export * from './destination'; export * from './event-invoke-config'; export * from './scalable-attribute-api'; export * from './code-signing-config'; - +export * from './lambda-insights'; export * from './log-retention'; // AWS::Lambda CloudFormation Resources: diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts new file mode 100644 index 0000000000000..96f32fff6c646 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -0,0 +1,24 @@ +/** + * Version of Lambda Insights. + */ +export class LambdaInsightsVersion { + + /** + * Use the insight version associated with the provided ARN. Make sure the ARN is associated + * with same region as your function + * + * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html + */ + public static fromInsightVersionArn(arn: string): LambdaInsightsVersion { + return new LambdaInsightsVersion(arn); + } + + /** + * The ARN of the Lambda insights lambda layer. + */ + readonly layerVersionArn: string; + + private constructor(arn: string) { + this.layerVersionArn = arn; + } +} diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts new file mode 100644 index 0000000000000..4b34c380abd62 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -0,0 +1,37 @@ +import '@aws-cdk/assert-internal/jest'; +import { ResourcePart } from '@aws-cdk/assert-internal'; +import * as cdk from '@aws-cdk/core'; +import * as lambda from '../lib'; + +describe('lambda-insights', () => { + test('can enable insights on function', () => { + const stack = new cdk.Stack(); + const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; + new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn), + }); + + expect(stack).toHaveResource('AWS::IAM::Role', { + ManagedPolicyArns: + [ + { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole']] }, + { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy']] }, + ], + }); + + expect(stack).toHaveResource('AWS::Lambda::Function', { + Properties: + { + Code: { ZipFile: 'foo' }, + Handler: 'index.handler', + Role: { 'Fn::GetAtt': ['MyLambdaServiceRole4539ECB6', 'Arn'] }, + Runtime: 'nodejs10.x', + Layers: [layerArn], + }, + DependsOn: ['MyLambdaServiceRole4539ECB6'], + }, ResourcePart.CompleteDefinition); + }); +}); From a0e4ba58d19f74092fdad1ed776d924eb34ccd32 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 6 Jul 2021 22:32:50 +0000 Subject: [PATCH 02/27] Add lookup by version and region --- packages/@aws-cdk/aws-lambda/lib/function.ts | 6 +- .../aws-lambda/lib/lambda-insights.ts | 156 +++++++++++++++++- .../aws-lambda/test/lambda-insights.test.ts | 26 ++- 3 files changed, 181 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index e1d87174a8045..c067d5b6c51e0 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -15,7 +15,7 @@ import { FileSystem } from './filesystem'; import { FunctionAttributes, FunctionBase, IFunction } from './function-base'; import { calculateFunctionHash, trimFromStart } from './function-hash'; import { Handler } from './handler'; -import { LambdaInsightsVersion } from './lambda-insights'; +import { LambdaInsightsLayerVersion } from './lambda-insights'; import { Version, VersionOptions } from './lambda-version'; import { CfnFunction } from './lambda.generated'; import { LayerVersion, ILayerVersion } from './layers'; @@ -221,7 +221,7 @@ export interface FunctionOptions extends EventInvokeConfigOptions { * * @default - No Lambda Insights */ - readonly insightsVersion?: LambdaInsightsVersion; + readonly insightsVersion?: LambdaInsightsLayerVersion; /** * A list of layers to add to the function's execution environment. You can configure your Lambda function to pull in @@ -883,7 +883,7 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett * * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html */ - private configureLambdaInsights(insightsVersion: LambdaInsightsVersion): void { + private configureLambdaInsights(insightsVersion: LambdaInsightsLayerVersion): void { this.addLayers(LayerVersion.fromLayerVersionArn(this, 'LambdaInsightsLayer', insightsVersion.layerVersionArn)); this.role?.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLambdaInsightsExecutionRolePolicy')); } diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 96f32fff6c646..9434310e0660a 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,7 +1,7 @@ /** * Version of Lambda Insights. */ -export class LambdaInsightsVersion { +export class LambdaInsightsLayerVersion { /** * Use the insight version associated with the provided ARN. Make sure the ARN is associated @@ -9,8 +9,16 @@ export class LambdaInsightsVersion { * * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html */ - public static fromInsightVersionArn(arn: string): LambdaInsightsVersion { - return new LambdaInsightsVersion(arn); + public static fromInsightVersionArn(arn: string): LambdaInsightsLayerVersion { + return new LambdaInsightsLayerVersion(arn); + } + + /** + * Use the insight version associated with the given region and version. + */ + public static fromVersionAndRegion(props: LambdaInsightsVersionProps): LambdaInsightsLayerVersion { + return new LambdaInsightsLayerVersion( + LambdaInsightsVersionLookup.fromVersionAndRegion(props.insightsVersion, props.region)); } /** @@ -22,3 +30,145 @@ export class LambdaInsightsVersion { this.layerVersionArn = arn; } } + +/** + * Available versions of Lambda Insights + */ +export enum LambdaInsightsVersion { + + /** + * 1.0.98.0 + */ + VERSION_1_0_98_0 = '1.0.98.0', + + /** + * 1.0.89.0 + */ + VERSION_1_0_89_0 = '1.0.89.0', + + /** + * 1.0.86.0 + */ + VERSION_1_0_86_0 = '1.0.86.0', + + /** + * 1.0.54.0 + */ + VERSION_1_0_54_0 = '1.0.54.0' +} + +/** + * Properties that define a Lambda Insights version. + */ +export interface LambdaInsightsVersionProps { + + /** + * The version of Lambda Insights to use, like 1.0.98.0 + * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html + */ + readonly insightsVersion: LambdaInsightsVersion; + + /** + * Region that Lambda Insights will be used in. + */ + readonly region: string; +} + + +/** + * Lookup of known lambda insights versions. These come from + * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html + */ +class LambdaInsightsVersionLookup { + + public static fromVersionAndRegion(version: string, region: string): string { + if (!this.lookupTable.hasOwnProperty(version)) { + throw new Error(`Insights version ${version} is not a valid version, available versions are ${Object.keys(this.lookupTable)}`); + } + if (!this.lookupTable[version].hasOwnProperty(region)) { + throw new Error(`Insights version ${version} is not supported in region ${region}`); + } + return this.lookupTable[version][region]; + } + + private static readonly lookupTable: { [key: string]: any } = { + '1.0.98.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:14', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:14', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:14', + 'af-south-1': 'arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8', + 'ap-east-1': 'arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:8', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:14', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:14', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:14', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:14', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:14', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:14', + 'cn-north-1': 'arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:8', + 'cn-northwest-1': 'arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:8', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:14', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:14', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:14', + 'eu-south-1': 'arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:8', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:14', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:14', + 'me-south-1': 'arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:8', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:14', + }, + '1.0.89.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:12', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:12', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:12', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:12', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:12', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:12', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:12', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:12', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:12', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:12', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:12', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:12', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:12', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:12', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:12', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:12', + }, + '1.0.86.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:11', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:11', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:11', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:11', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:11', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:11', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:11', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:11', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:11', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:11', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:11', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:11', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:11', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:11', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:11', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:11', + }, + '1.0.54.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:2', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:2', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:2', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:2', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:2', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:2', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:2', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:2', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:2', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:2', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:2', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:2', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:2', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:2', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:2', + }, + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index 4b34c380abd62..b1c3edfb8208f 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -11,7 +11,7 @@ describe('lambda-insights', () => { code: new lambda.InlineCode('foo'), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn), + insightsVersion: lambda.LambdaInsightsLayerVersion.fromInsightVersionArn(layerArn), }); expect(stack).toHaveResource('AWS::IAM::Role', { @@ -34,4 +34,28 @@ describe('lambda-insights', () => { DependsOn: ['MyLambdaServiceRole4539ECB6'], }, ResourcePart.CompleteDefinition); }); + + test('unsupported version/region throws error', () => { + const stack = new cdk.Stack(); + + expect(() => new lambda.Function(stack, 'BadVersion', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion({ + insightsVersion: 'UNSUPPORTED_VERSION' as lambda.LambdaInsightsVersion, + region: 'us-west-2', + }), + })).toThrow(); + + expect(() => new lambda.Function(stack, 'BadRegion', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion({ + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0, + region: 'UNSUPPORTED_REGION', + }), + })).toThrow(); + }); }); From 22bcbfc87af4d6168c259c186d9bebc8522c9207 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 6 Jul 2021 22:47:16 +0000 Subject: [PATCH 03/27] Add readme --- packages/@aws-cdk/aws-lambda/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 0a452182153bc..57a59b3f76cba 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -323,6 +323,27 @@ new LayerVersion(this, 'MyLayer', { }); ``` +## Lambda Insights + +Lambda functions can be configured to use CloudWatch [Lambda Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights.html) +which provides low-level runtime metrics for a Lambda functions. + +```ts +import * as lambda from '@aws-cdk/lambda'; + +new Function(this, 'MyFunction', { + insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion({ + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0, + region: 'us-west-2', + }) +}) + +// Can also provide your own arn if a new version comes out +new Function(this, 'MyFunction', { + insightsVersion: lambda.LambdaInsightsLayerVersion.fromInsightVersionArn() +}) +``` + ## Event Rule Target You can use an AWS Lambda function as a target for an Amazon CloudWatch event From 6f371ee88a89e77f881934be652bd62e42f42d28 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 20 Jul 2021 19:22:48 +0000 Subject: [PATCH 04/27] Review feedback: put lookup table into Facts and RegionInfo --- .../aws-lambda/lib/lambda-insights.ts | 127 ++---------------- packages/@aws-cdk/aws-lambda/package.json | 4 +- .../aws-lambda/test/lambda-insights.test.ts | 30 +++-- 3 files changed, 32 insertions(+), 129 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 9434310e0660a..20b42e3fe201f 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,3 +1,5 @@ +import { RegionInfo } from '@aws-cdk/region-info'; + /** * Version of Lambda Insights. */ @@ -16,9 +18,12 @@ export class LambdaInsightsLayerVersion { /** * Use the insight version associated with the given region and version. */ - public static fromVersionAndRegion(props: LambdaInsightsVersionProps): LambdaInsightsLayerVersion { - return new LambdaInsightsLayerVersion( - LambdaInsightsVersionLookup.fromVersionAndRegion(props.insightsVersion, props.region)); + public static fromVersionAndRegion(insightsVersion: LambdaInsightsVersion, region: string): LambdaInsightsLayerVersion { + const arn = RegionInfo.get(region).cloudwatchLambdaInsightsArn(insightsVersion); + if (arn === undefined) { + throw new Error(`Insights version ${insightsVersion} does not exist or is not supported in region ${region}`); + } + return LambdaInsightsLayerVersion.fromInsightVersionArn(arn); } /** @@ -56,119 +61,3 @@ export enum LambdaInsightsVersion { */ VERSION_1_0_54_0 = '1.0.54.0' } - -/** - * Properties that define a Lambda Insights version. - */ -export interface LambdaInsightsVersionProps { - - /** - * The version of Lambda Insights to use, like 1.0.98.0 - * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html - */ - readonly insightsVersion: LambdaInsightsVersion; - - /** - * Region that Lambda Insights will be used in. - */ - readonly region: string; -} - - -/** - * Lookup of known lambda insights versions. These come from - * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html - */ -class LambdaInsightsVersionLookup { - - public static fromVersionAndRegion(version: string, region: string): string { - if (!this.lookupTable.hasOwnProperty(version)) { - throw new Error(`Insights version ${version} is not a valid version, available versions are ${Object.keys(this.lookupTable)}`); - } - if (!this.lookupTable[version].hasOwnProperty(region)) { - throw new Error(`Insights version ${version} is not supported in region ${region}`); - } - return this.lookupTable[version][region]; - } - - private static readonly lookupTable: { [key: string]: any } = { - '1.0.98.0': { - 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14', - 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:14', - 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:14', - 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:14', - 'af-south-1': 'arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8', - 'ap-east-1': 'arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:8', - 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:14', - 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:14', - 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:14', - 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:14', - 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:14', - 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:14', - 'cn-north-1': 'arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:8', - 'cn-northwest-1': 'arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:8', - 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:14', - 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:14', - 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:14', - 'eu-south-1': 'arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:8', - 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:14', - 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:14', - 'me-south-1': 'arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:8', - 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:14', - }, - '1.0.89.0': { - 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:12', - 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:12', - 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:12', - 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:12', - 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:12', - 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:12', - 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:12', - 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:12', - 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:12', - 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:12', - 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:12', - 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:12', - 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:12', - 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:12', - 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:12', - 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:12', - }, - '1.0.86.0': { - 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:11', - 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:11', - 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:11', - 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:11', - 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:11', - 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:11', - 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:11', - 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:11', - 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:11', - 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:11', - 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:11', - 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:11', - 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:11', - 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:11', - 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:11', - 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:11', - }, - '1.0.54.0': { - 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2', - 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:2', - 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:2', - 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:2', - 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:2', - 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:2', - 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:2', - 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:2', - 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:2', - 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:2', - 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:2', - 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:2', - 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:2', - 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:2', - 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:2', - 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:2', - }, - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index e83aaf00c6e10..70557e964bd18 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -106,6 +106,7 @@ "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/region-info": "0.0.0", "constructs": "^3.3.69" }, "homepage": "https://github.com/aws/aws-cdk", @@ -127,7 +128,8 @@ "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", - "constructs": "^3.3.69" + "constructs": "^3.3.69", + "@aws-cdk/region-info": "0.0.0" }, "engines": { "node": ">= 10.13.0 <13 || >=13.7.0" diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index b1c3edfb8208f..e59e4e3c21a0c 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -35,27 +35,39 @@ describe('lambda-insights', () => { }, ResourcePart.CompleteDefinition); }); - test('unsupported version/region throws error', () => { + test('nonexistent version/region throws error', () => { const stack = new cdk.Stack(); expect(() => new lambda.Function(stack, 'BadVersion', { code: new lambda.InlineCode('foo'), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion({ - insightsVersion: 'UNSUPPORTED_VERSION' as lambda.LambdaInsightsVersion, - region: 'us-west-2', - }), + insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion( + 'NONEXISTENT_VERSION' as lambda.LambdaInsightsVersion, + 'us-west-2'), })).toThrow(); expect(() => new lambda.Function(stack, 'BadRegion', { code: new lambda.InlineCode('foo'), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion({ - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0, - region: 'UNSUPPORTED_REGION', - }), + insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion( + lambda.LambdaInsightsVersion.VERSION_1_0_98_0, + 'NONEXISTENT_REGION'), + })).toThrow(); + }); + + test('existing region with existing but unsupported version throws error', () => { + const stack = new cdk.Stack(); + + // AF-SOUTH-1 exists, 1.0.54.0 exists, but 1.0.54.0 isn't supported in AF-SOUTH-1 + expect(() => new lambda.Function(stack, 'BadVersion', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion( + lambda.LambdaInsightsVersion.VERSION_1_0_54_0, + 'af-south-1'), })).toThrow(); }); }); From e4b859d6a782b4c53cf13871e5008c87da04e8b3 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 20 Jul 2021 20:17:11 +0000 Subject: [PATCH 05/27] Review feedback: actually add the region info --- .../region-info/build-tools/fact-tables.ts | 81 +++++++++++++++++++ .../build-tools/generate-static-data.ts | 9 ++- packages/@aws-cdk/region-info/lib/fact.ts | 20 +++++ .../@aws-cdk/region-info/lib/region-info.ts | 9 +++ 4 files changed, 118 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts index c2ce689f3aaf3..707e412a82570 100644 --- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts +++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts @@ -158,3 +158,84 @@ export const APPMESH_ECR_ACCOUNTS: { [region: string]: string } = { 'us-west-1': '840364872350', 'us-west-2': '840364872350', }; + +export const CLOUDWATCH_LAMBDA_INSIGHTS_ARNS: { [key: string]: any } = { + '1.0.98.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:14', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:14', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:14', + 'af-south-1': 'arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8', + 'ap-east-1': 'arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:8', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:14', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:14', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:14', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:14', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:14', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:14', + 'cn-north-1': 'arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:8', + 'cn-northwest-1': 'arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:8', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:14', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:14', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:14', + 'eu-south-1': 'arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:8', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:14', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:14', + 'me-south-1': 'arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:8', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:14', + }, + '1.0.89.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:12', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:12', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:12', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:12', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:12', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:12', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:12', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:12', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:12', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:12', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:12', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:12', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:12', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:12', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:12', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:12', + }, + '1.0.86.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:11', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:11', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:11', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:11', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:11', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:11', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:11', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:11', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:11', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:11', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:11', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:11', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:11', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:11', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:11', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:11', + }, + '1.0.54.0': { + 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2', + 'us-east-2': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:2', + 'us-west-1': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:2', + 'us-west-2': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:2', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:2', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:2', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:2', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:2', + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:2', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:2', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:2', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:2', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:2', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:2', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:2', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:2', + }, +}; diff --git a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts index d23704b6d0062..384b712b7d339 100644 --- a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts +++ b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts @@ -3,7 +3,7 @@ import * as fs from 'fs-extra'; import { Default } from '../lib/default'; import { AWS_REGIONS, AWS_SERVICES } from './aws-entities'; import { - APPMESH_ECR_ACCOUNTS, AWS_CDK_METADATA, AWS_OLDER_REGIONS, DLC_REPOSITORY_ACCOUNTS, ELBV2_ACCOUNTS, PARTITION_MAP, + APPMESH_ECR_ACCOUNTS, AWS_CDK_METADATA, AWS_OLDER_REGIONS, CLOUDWATCH_LAMBDA_INSIGHTS_ARNS, DLC_REPOSITORY_ACCOUNTS, ELBV2_ACCOUNTS, PARTITION_MAP, ROUTE_53_BUCKET_WEBSITE_ZONE_IDS, } from './fact-tables'; @@ -61,6 +61,13 @@ async function main(): Promise { registerFact(region, 'APPMESH_ECR_ACCOUNT', APPMESH_ECR_ACCOUNTS[region]); + // Need to register a fact for each version of CW Lambda Insights + for (const version in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS) { + // Fact name is like CLOUDWATCH_LAMBDA_INSIGHTS_VERSIONS_1_0_98_0 + const factName = 'CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_' + version.split('.').join('_'); + registerFact(region, factName, CLOUDWATCH_LAMBDA_INSIGHTS_ARNS[version][region]); + } + const vpcEndpointServiceNamePrefix = `${domainSuffix.split('.').reverse().join('.')}.vpce`; registerFact(region, 'VPC_ENDPOINT_SERVICE_NAME_PREFIX', vpcEndpointServiceNamePrefix); diff --git a/packages/@aws-cdk/region-info/lib/fact.ts b/packages/@aws-cdk/region-info/lib/fact.ts index 3b5e57835cc7e..06362a862703f 100644 --- a/packages/@aws-cdk/region-info/lib/fact.ts +++ b/packages/@aws-cdk/region-info/lib/fact.ts @@ -152,6 +152,26 @@ export class FactName { */ public static readonly APPMESH_ECR_ACCOUNT = 'appMeshRepositoryAccount'; + /** + * The ARN of CloudWatch Lambda Insights for version 1.0.98.0. + */ + public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_98_0 = 'cloudwatch-lambda-insights-versions:1.0.98.0'; + + /** + * The ARN of CloudWatch Lambda Insights for version 1.0.89.0. + */ + public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_89_0 = 'cloudwatch-lambda-insights-versions:1.0.89.0'; + + /** + * The ARN of CloudWatch Lambda Insights for version 1.0.86.0. + */ + public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_86_0 = 'cloudwatch-lambda-insights-versions:1.0.86.0'; + + /** + * The ARN of CloudWatch Lambda Insights for version 1.0.54.0. + */ + public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_54_0 = 'cloudwatch-lambda-insights-versions:1.0.54.0'; + /** * The name of the regional service principal for a given service. * diff --git a/packages/@aws-cdk/region-info/lib/region-info.ts b/packages/@aws-cdk/region-info/lib/region-info.ts index 042b3cec9c177..e58663b264127 100644 --- a/packages/@aws-cdk/region-info/lib/region-info.ts +++ b/packages/@aws-cdk/region-info/lib/region-info.ts @@ -110,6 +110,15 @@ export class RegionInfo { return Fact.find(this.name, FactName.DLC_REPOSITORY_ACCOUNT); } + /** + * The ID of the AWS account that owns the public ECR repository containing the + * AWS Deep Learning Containers images in this region. + */ + public cloudwatchLambdaInsightsArn(insightsVersion: string): string | undefined { + const factName = 'CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_' + insightsVersion.split('.').join('_'); + return Fact.find(this.name, factName); + } + /** * The ID of the AWS account that owns the public ECR repository that contains the * AWS App Mesh Envoy Proxy images in a given region. From 833a6783c957566405a0f2054e72e5d2d59cf72d Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 20 Jul 2021 20:20:32 +0000 Subject: [PATCH 06/27] Add link to information source --- packages/@aws-cdk/region-info/build-tools/fact-tables.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts index 707e412a82570..fceeb24a2d2d1 100644 --- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts +++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts @@ -159,6 +159,7 @@ export const APPMESH_ECR_ACCOUNTS: { [region: string]: string } = { 'us-west-2': '840364872350', }; +// https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html export const CLOUDWATCH_LAMBDA_INSIGHTS_ARNS: { [key: string]: any } = { '1.0.98.0': { 'us-east-1': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14', From ce06da62b89c912e5042df44f400934e7a457b1d Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 20 Jul 2021 23:27:52 +0000 Subject: [PATCH 07/27] Found a better way to do a parameterized fact, and added tests of the data --- .../build-tools/generate-static-data.ts | 11 +- packages/@aws-cdk/region-info/lib/fact.ts | 19 +- .../@aws-cdk/region-info/lib/region-info.ts | 7 +- .../__snapshots__/region-info.test.js.snap | 162 ++++++++++++++++++ .../region-info/test/region-info.test.ts | 8 + 5 files changed, 180 insertions(+), 27 deletions(-) diff --git a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts index 384b712b7d339..bf1bc63e03829 100644 --- a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts +++ b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts @@ -61,19 +61,16 @@ async function main(): Promise { registerFact(region, 'APPMESH_ECR_ACCOUNT', APPMESH_ECR_ACCOUNTS[region]); - // Need to register a fact for each version of CW Lambda Insights - for (const version in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS) { - // Fact name is like CLOUDWATCH_LAMBDA_INSIGHTS_VERSIONS_1_0_98_0 - const factName = 'CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_' + version.split('.').join('_'); - registerFact(region, factName, CLOUDWATCH_LAMBDA_INSIGHTS_ARNS[version][region]); - } - const vpcEndpointServiceNamePrefix = `${domainSuffix.split('.').reverse().join('.')}.vpce`; registerFact(region, 'VPC_ENDPOINT_SERVICE_NAME_PREFIX', vpcEndpointServiceNamePrefix); for (const service of AWS_SERVICES) { registerFact(region, ['servicePrincipal', service], Default.servicePrincipal(service, region, domainSuffix)); } + + for (const version in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS) { + registerFact(region, ['cloudwatchLambdaInsightsVersion', version], CLOUDWATCH_LAMBDA_INSIGHTS_ARNS[version][region]); + } } lines.push(' }'); lines.push(''); diff --git a/packages/@aws-cdk/region-info/lib/fact.ts b/packages/@aws-cdk/region-info/lib/fact.ts index 06362a862703f..fb6c7b65ae153 100644 --- a/packages/@aws-cdk/region-info/lib/fact.ts +++ b/packages/@aws-cdk/region-info/lib/fact.ts @@ -155,22 +155,9 @@ export class FactName { /** * The ARN of CloudWatch Lambda Insights for version 1.0.98.0. */ - public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_98_0 = 'cloudwatch-lambda-insights-versions:1.0.98.0'; - - /** - * The ARN of CloudWatch Lambda Insights for version 1.0.89.0. - */ - public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_89_0 = 'cloudwatch-lambda-insights-versions:1.0.89.0'; - - /** - * The ARN of CloudWatch Lambda Insights for version 1.0.86.0. - */ - public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_86_0 = 'cloudwatch-lambda-insights-versions:1.0.86.0'; - - /** - * The ARN of CloudWatch Lambda Insights for version 1.0.54.0. - */ - public static readonly CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_1_0_54_0 = 'cloudwatch-lambda-insights-versions:1.0.54.0'; + public static cloudwatchLambdaInsightsVersion(version: string) { + return `cloudwatch-lambda-insights-version:${version.split('.').join('_')}`; + } /** * The name of the regional service principal for a given service. diff --git a/packages/@aws-cdk/region-info/lib/region-info.ts b/packages/@aws-cdk/region-info/lib/region-info.ts index e58663b264127..a6b14ad70f325 100644 --- a/packages/@aws-cdk/region-info/lib/region-info.ts +++ b/packages/@aws-cdk/region-info/lib/region-info.ts @@ -111,12 +111,11 @@ export class RegionInfo { } /** - * The ID of the AWS account that owns the public ECR repository containing the - * AWS Deep Learning Containers images in this region. + * The ARN of the CloudWatch Lambda Insights extension, for the given version. + * @param insightsVersion the version (e.g. 1.0.98.0) */ public cloudwatchLambdaInsightsArn(insightsVersion: string): string | undefined { - const factName = 'CLOUDWATCH_LAMBDA_INSIGHTS_VERSION_' + insightsVersion.split('.').join('_'); - return Fact.find(this.name, factName); + return Fact.find(this.name, FactName.cloudwatchLambdaInsightsVersion(insightsVersion)); } /** diff --git a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap index eb7c82b6eb28d..f1797f8083af5 100644 --- a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap +++ b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap @@ -5,6 +5,12 @@ Object { "af-south-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": "arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.af-south-1.amazonaws.com", "servicePrincipals": Object { @@ -25,6 +31,12 @@ Object { "ap-east-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": "arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:8", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.ap-east-1.amazonaws.com", "servicePrincipals": Object { @@ -45,6 +57,12 @@ Object { "ap-northeast-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-ap-northeast-1.amazonaws.com", "servicePrincipals": Object { @@ -65,6 +83,12 @@ Object { "ap-northeast-2": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.ap-northeast-2.amazonaws.com", "servicePrincipals": Object { @@ -85,6 +109,12 @@ Object { "ap-northeast-3": Object { "cdkMetadataResourceAvailable": false, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": undefined, + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.ap-northeast-3.amazonaws.com", "servicePrincipals": Object { @@ -105,6 +135,12 @@ Object { "ap-south-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.ap-south-1.amazonaws.com", "servicePrincipals": Object { @@ -125,6 +161,12 @@ Object { "ap-southeast-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-ap-southeast-1.amazonaws.com", "servicePrincipals": Object { @@ -145,6 +187,12 @@ Object { "ap-southeast-2": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-ap-southeast-2.amazonaws.com", "servicePrincipals": Object { @@ -165,6 +213,12 @@ Object { "ca-central-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.ca-central-1.amazonaws.com", "servicePrincipals": Object { @@ -185,6 +239,12 @@ Object { "cn-north-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com.cn", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": "arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:8", + }, "partition": "aws-cn", "s3StaticWebsiteEndpoint": "s3-website.cn-north-1.amazonaws.com.cn", "servicePrincipals": Object { @@ -205,6 +265,12 @@ Object { "cn-northwest-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com.cn", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": "arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:8", + }, "partition": "aws-cn", "s3StaticWebsiteEndpoint": "s3-website.cn-northwest-1.amazonaws.com.cn", "servicePrincipals": Object { @@ -225,6 +291,12 @@ Object { "eu-central-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.eu-central-1.amazonaws.com", "servicePrincipals": Object { @@ -245,6 +317,12 @@ Object { "eu-north-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.eu-north-1.amazonaws.com", "servicePrincipals": Object { @@ -265,6 +343,12 @@ Object { "eu-south-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": "arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:8", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.eu-south-1.amazonaws.com", "servicePrincipals": Object { @@ -285,6 +369,12 @@ Object { "eu-west-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-eu-west-1.amazonaws.com", "servicePrincipals": Object { @@ -305,6 +395,12 @@ Object { "eu-west-2": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.eu-west-2.amazonaws.com", "servicePrincipals": Object { @@ -325,6 +421,12 @@ Object { "eu-west-3": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.eu-west-3.amazonaws.com", "servicePrincipals": Object { @@ -345,6 +447,12 @@ Object { "me-south-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": "arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:8", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.me-south-1.amazonaws.com", "servicePrincipals": Object { @@ -365,6 +473,12 @@ Object { "sa-east-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-sa-east-1.amazonaws.com", "servicePrincipals": Object { @@ -385,6 +499,12 @@ Object { "us-east-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-us-east-1.amazonaws.com", "servicePrincipals": Object { @@ -405,6 +525,12 @@ Object { "us-east-2": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website.us-east-2.amazonaws.com", "servicePrincipals": Object { @@ -425,6 +551,12 @@ Object { "us-gov-east-1": Object { "cdkMetadataResourceAvailable": false, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": undefined, + }, "partition": "aws-us-gov", "s3StaticWebsiteEndpoint": "s3-website.us-gov-east-1.amazonaws.com", "servicePrincipals": Object { @@ -445,6 +577,12 @@ Object { "us-gov-west-1": Object { "cdkMetadataResourceAvailable": false, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": undefined, + }, "partition": "aws-us-gov", "s3StaticWebsiteEndpoint": "s3-website-us-gov-west-1.amazonaws.com", "servicePrincipals": Object { @@ -465,6 +603,12 @@ Object { "us-iso-east-1": Object { "cdkMetadataResourceAvailable": false, "domainSuffix": "c2s.ic.gov", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": undefined, + }, "partition": "aws-iso", "s3StaticWebsiteEndpoint": "s3-website.us-iso-east-1.c2s.ic.gov", "servicePrincipals": Object { @@ -485,6 +629,12 @@ Object { "us-isob-east-1": Object { "cdkMetadataResourceAvailable": false, "domainSuffix": "sc2s.sgov.gov", + "lambdaInsightsVersions": Object { + "1.0.54.0": undefined, + "1.0.86.0": undefined, + "1.0.89.0": undefined, + "1.0.98.0": undefined, + }, "partition": "aws-iso-b", "s3StaticWebsiteEndpoint": "s3-website.us-isob-east-1.sc2s.sgov.gov", "servicePrincipals": Object { @@ -505,6 +655,12 @@ Object { "us-west-1": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-us-west-1.amazonaws.com", "servicePrincipals": Object { @@ -525,6 +681,12 @@ Object { "us-west-2": Object { "cdkMetadataResourceAvailable": true, "domainSuffix": "amazonaws.com", + "lambdaInsightsVersions": Object { + "1.0.54.0": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:2", + "1.0.86.0": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:11", + "1.0.89.0": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:12", + "1.0.98.0": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:14", + }, "partition": "aws", "s3StaticWebsiteEndpoint": "s3-website-us-west-2.amazonaws.com", "servicePrincipals": Object { diff --git a/packages/@aws-cdk/region-info/test/region-info.test.ts b/packages/@aws-cdk/region-info/test/region-info.test.ts index 5f9f68ea4a787..8c06907052b23 100644 --- a/packages/@aws-cdk/region-info/test/region-info.test.ts +++ b/packages/@aws-cdk/region-info/test/region-info.test.ts @@ -1,4 +1,5 @@ import { AWS_REGIONS, AWS_SERVICES } from '../build-tools/aws-entities'; +import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '../build-tools/fact-tables'; import { RegionInfo } from '../lib'; test('built-in data is correct', () => { @@ -7,8 +8,14 @@ test('built-in data is correct', () => { const region = RegionInfo.get(name); const servicePrincipals: { [service: string]: string | undefined } = {}; + const lambdaInsightsVersions: { [service: string]: string | undefined } = {}; + AWS_SERVICES.forEach(service => servicePrincipals[service] = region.servicePrincipal(service)); + for (const version in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS) { + lambdaInsightsVersions[version] = region.cloudwatchLambdaInsightsArn(version); + }; + snapshot[name] = { cdkMetadataResourceAvailable: region.cdkMetadataResourceAvailable, domainSuffix: region.domainSuffix, @@ -16,6 +23,7 @@ test('built-in data is correct', () => { s3StaticWebsiteEndpoint: region.s3StaticWebsiteEndpoint, vpcEndPointServiceNamePrefix: region.vpcEndpointServiceNamePrefix, servicePrincipals, + lambdaInsightsVersions, }; } expect(snapshot).toMatchSnapshot(); From 4ee6ccbb0ee333fd2fe9f1e6668d9b55d367c003 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 20 Jul 2021 23:34:59 +0000 Subject: [PATCH 08/27] Add test using version --- .../aws-lambda/lib/lambda-insights.ts | 2 +- .../aws-lambda/test/lambda-insights.test.ts | 32 ++++++++++++++++++- packages/@aws-cdk/region-info/lib/fact.ts | 2 +- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 20b42e3fe201f..4807ac30a2648 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,4 +1,4 @@ -import { RegionInfo } from '@aws-cdk/region-info'; +import { Fact, RegionInfo } from '@aws-cdk/region-info'; /** * Version of Lambda Insights. diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index e59e4e3c21a0c..d0269bda31fab 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -4,7 +4,7 @@ import * as cdk from '@aws-cdk/core'; import * as lambda from '../lib'; describe('lambda-insights', () => { - test('can enable insights on function', () => { + test('can provide arn to enable insights', () => { const stack = new cdk.Stack(); const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; new lambda.Function(stack, 'MyLambda', { @@ -35,6 +35,36 @@ describe('lambda-insights', () => { }, ResourcePart.CompleteDefinition); }); + test('can provide a version to enable insights', () => { + const stack = new cdk.Stack(); + new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion(lambda.LambdaInsightsVersion.VERSION_1_0_54_0, 'us-east-1'), + }); + + expect(stack).toHaveResource('AWS::IAM::Role', { + ManagedPolicyArns: + [ + { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole']] }, + { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy']] }, + ], + }); + + expect(stack).toHaveResource('AWS::Lambda::Function', { + Properties: + { + Code: { ZipFile: 'foo' }, + Handler: 'index.handler', + Role: { 'Fn::GetAtt': ['MyLambdaServiceRole4539ECB6', 'Arn'] }, + Runtime: 'nodejs10.x', + Layers: ['arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2'], + }, + DependsOn: ['MyLambdaServiceRole4539ECB6'], + }, ResourcePart.CompleteDefinition); + }); + test('nonexistent version/region throws error', () => { const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/region-info/lib/fact.ts b/packages/@aws-cdk/region-info/lib/fact.ts index fb6c7b65ae153..7dcca3105be8e 100644 --- a/packages/@aws-cdk/region-info/lib/fact.ts +++ b/packages/@aws-cdk/region-info/lib/fact.ts @@ -153,7 +153,7 @@ export class FactName { public static readonly APPMESH_ECR_ACCOUNT = 'appMeshRepositoryAccount'; /** - * The ARN of CloudWatch Lambda Insights for version 1.0.98.0. + * The ARN of CloudWatch Lambda Insights for a version (e.g. 1.0.98.0) */ public static cloudwatchLambdaInsightsVersion(version: string) { return `cloudwatch-lambda-insights-version:${version.split('.').join('_')}`; From dd85e049ae95c5ce76fea428644b5f5cab3133e6 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Tue, 20 Jul 2021 23:55:50 +0000 Subject: [PATCH 09/27] Remove stray import --- packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 4807ac30a2648..20b42e3fe201f 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,4 +1,4 @@ -import { Fact, RegionInfo } from '@aws-cdk/region-info'; +import { RegionInfo } from '@aws-cdk/region-info'; /** * Version of Lambda Insights. From 912ecac6108e6accf5dd9f7b0c32c95b0f2f8a6b Mon Sep 17 00:00:00 2001 From: James Fleming Date: Wed, 21 Jul 2021 00:40:35 +0000 Subject: [PATCH 10/27] Get the region at synthesis time so the user doesn't have to provide it --- packages/@aws-cdk/aws-lambda/lib/function.ts | 6 +- .../aws-lambda/lib/lambda-insights.ts | 101 +++++++++++------- .../aws-lambda/test/lambda-insights.test.ts | 48 ++++----- 3 files changed, 84 insertions(+), 71 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index c067d5b6c51e0..e1d87174a8045 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -15,7 +15,7 @@ import { FileSystem } from './filesystem'; import { FunctionAttributes, FunctionBase, IFunction } from './function-base'; import { calculateFunctionHash, trimFromStart } from './function-hash'; import { Handler } from './handler'; -import { LambdaInsightsLayerVersion } from './lambda-insights'; +import { LambdaInsightsVersion } from './lambda-insights'; import { Version, VersionOptions } from './lambda-version'; import { CfnFunction } from './lambda.generated'; import { LayerVersion, ILayerVersion } from './layers'; @@ -221,7 +221,7 @@ export interface FunctionOptions extends EventInvokeConfigOptions { * * @default - No Lambda Insights */ - readonly insightsVersion?: LambdaInsightsLayerVersion; + readonly insightsVersion?: LambdaInsightsVersion; /** * A list of layers to add to the function's execution environment. You can configure your Lambda function to pull in @@ -883,7 +883,7 @@ Environment variables can be marked for removal when used in Lambda@Edge by sett * * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html */ - private configureLambdaInsights(insightsVersion: LambdaInsightsLayerVersion): void { + private configureLambdaInsights(insightsVersion: LambdaInsightsVersion): void { this.addLayers(LayerVersion.fromLayerVersionArn(this, 'LambdaInsightsLayer', insightsVersion.layerVersionArn)); this.role?.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLambdaInsightsExecutionRolePolicy')); } diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 20b42e3fe201f..5fd19b4636f53 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,63 +1,88 @@ +import { Lazy, Stack, Token } from '@aws-cdk/core'; import { RegionInfo } from '@aws-cdk/region-info'; +import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '@aws-cdk/region-info/build-tools/fact-tables'; + +// To add new versions, update fact-tables.ts `CLOUDWATCH_LAMBDA_INSIGHTS_ARNS` and create a new `public static readonly VERSION_A_B_C_D` /** - * Version of Lambda Insights. + * Version of CloudWatch Lambda Insights */ -export class LambdaInsightsLayerVersion { +export class LambdaInsightsVersion { /** - * Use the insight version associated with the provided ARN. Make sure the ARN is associated - * with same region as your function - * - * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html + * Version 1.0.54.0 */ - public static fromInsightVersionArn(arn: string): LambdaInsightsLayerVersion { - return new LambdaInsightsLayerVersion(arn); - } + public static readonly VERSION_1_0_54_0 = LambdaInsightsVersion.fromInsightsVersion('1.0.54.0'); /** - * Use the insight version associated with the given region and version. + * Version 1.0.86.0 */ - public static fromVersionAndRegion(insightsVersion: LambdaInsightsVersion, region: string): LambdaInsightsLayerVersion { - const arn = RegionInfo.get(region).cloudwatchLambdaInsightsArn(insightsVersion); - if (arn === undefined) { - throw new Error(`Insights version ${insightsVersion} does not exist or is not supported in region ${region}`); - } - return LambdaInsightsLayerVersion.fromInsightVersionArn(arn); - } + public static readonly VERSION_1_0_86_0 = LambdaInsightsVersion.fromInsightsVersion('1.0.86.0'); /** - * The ARN of the Lambda insights lambda layer. + * Version 1.0.89.0 */ - readonly layerVersionArn: string; - - private constructor(arn: string) { - this.layerVersionArn = arn; - } -} - -/** - * Available versions of Lambda Insights - */ -export enum LambdaInsightsVersion { + public static readonly VERSION_1_0_89_0 = LambdaInsightsVersion.fromInsightsVersion('1.0.89.0'); /** - * 1.0.98.0 + * Version 1.0.98.0 */ - VERSION_1_0_98_0 = '1.0.98.0', + public static readonly VERSION_1_0_98_0 = LambdaInsightsVersion.fromInsightsVersion('1.0.98.0'); /** - * 1.0.89.0 + * Use the insights extension associated with the provided ARN. Make sure the ARN is associated + * with same region as your function + * + * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html */ - VERSION_1_0_89_0 = '1.0.89.0', + public static fromInsightVersionArn(arn: string): LambdaInsightsVersion { + return new LambdaInsightsVersion(undefined, arn); + } + + // Use the verison to build the object. Not meant to be called by the user -- user should use e.g. VERSION_1_0_54_0 + private static fromInsightsVersion(insightsVersion: string) { + return new LambdaInsightsVersion(insightsVersion, undefined); + } /** - * 1.0.86.0 + * The arn of the Lambda Insights extension */ - VERSION_1_0_86_0 = '1.0.86.0', + public readonly layerVersionArn: string; + + private constructor(insightsVersion?: string, arn?: string) { + if (arn !== undefined) { + // Use arn if explicitly provided + this.layerVersionArn = arn; + } else if (insightsVersion !== undefined) { + // Look up the arn (runs at synthesis time) + this.layerVersionArn = Lazy.uncachedString({ + produce: (context) => this.getVersionArn(context, insightsVersion), + }); + } else { + throw new Error('Cannot use Lambda Insights without providing a version or an ARN'); + } + } /** - * 1.0.54.0 + * Meant to run at synthesis. It will look up the region in RegionInfo */ - VERSION_1_0_54_0 = '1.0.54.0' -} + private getVersionArn(context: any, insightsVersion: string): string { + const region = Stack.of(context.scope).region; + + // Check if insights version is valid. This should only happen if one of the public static readonly versions are set incorrectly + if (!(insightsVersion in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS)) { + throw new Error(`Insights version ${insightsVersion} does not exist. Available versions are ${CLOUDWATCH_LAMBDA_INSIGHTS_ARNS.keys()}`); + } + + // Region is defined, look up the arn, or throw an error if the version isn't supported by a region + if (region !== undefined && !Token.isUnresolved(region)) { + const arn = RegionInfo.get(region).cloudwatchLambdaInsightsArn(insightsVersion); + if (arn === undefined) { + throw new Error(`Insights version ${insightsVersion} is not supported in region ${region}`); + } + return arn; + } + // Otherwise, need to add a mapping to be looked up at deployment time + return ''; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index d0269bda31fab..2ee3819759bc2 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -11,7 +11,7 @@ describe('lambda-insights', () => { code: new lambda.InlineCode('foo'), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsLayerVersion.fromInsightVersionArn(layerArn), + insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn), }); expect(stack).toHaveResource('AWS::IAM::Role', { @@ -36,12 +36,15 @@ describe('lambda-insights', () => { }); test('can provide a version to enable insights', () => { - const stack = new cdk.Stack(); + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack', { + env: { account: '123456789012', region: 'us-east-1' }, + }); new lambda.Function(stack, 'MyLambda', { code: new lambda.InlineCode('foo'), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion(lambda.LambdaInsightsVersion.VERSION_1_0_54_0, 'us-east-1'), + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, }); expect(stack).toHaveResource('AWS::IAM::Role', { @@ -63,41 +66,26 @@ describe('lambda-insights', () => { }, DependsOn: ['MyLambdaServiceRole4539ECB6'], }, ResourcePart.CompleteDefinition); - }); - - test('nonexistent version/region throws error', () => { - const stack = new cdk.Stack(); - - expect(() => new lambda.Function(stack, 'BadVersion', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion( - 'NONEXISTENT_VERSION' as lambda.LambdaInsightsVersion, - 'us-west-2'), - })).toThrow(); - expect(() => new lambda.Function(stack, 'BadRegion', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion( - lambda.LambdaInsightsVersion.VERSION_1_0_98_0, - 'NONEXISTENT_REGION'), - })).toThrow(); + // On synthesis it should not throw an error + expect(() => app.synth()).not.toThrow(); }); test('existing region with existing but unsupported version throws error', () => { - const stack = new cdk.Stack(); + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack', { + env: { account: '123456789012', region: 'af-south-1' }, + }); // AF-SOUTH-1 exists, 1.0.54.0 exists, but 1.0.54.0 isn't supported in AF-SOUTH-1 - expect(() => new lambda.Function(stack, 'BadVersion', { + new lambda.Function(stack, 'BadVersion', { code: new lambda.InlineCode('foo'), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion( - lambda.LambdaInsightsVersion.VERSION_1_0_54_0, - 'af-south-1'), - })).toThrow(); + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, + }); + + // On synthesis it should throw an error + expect(() => app.synth()).toThrow(); }); }); From 907e9ae966dd73288d99150f2c1af704675deab6 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Wed, 21 Jul 2021 01:11:03 +0000 Subject: [PATCH 11/27] Create mapping if no region is provided --- .../aws-lambda/lib/lambda-insights.ts | 15 +++++++- .../aws-lambda/test/lambda-insights.test.ts | 37 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 5fd19b4636f53..f4e0cd5df2940 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,7 +1,10 @@ -import { Lazy, Stack, Token } from '@aws-cdk/core'; +import { Aws, CfnMapping, Fn, Lazy, Stack, Token } from '@aws-cdk/core'; import { RegionInfo } from '@aws-cdk/region-info'; import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '@aws-cdk/region-info/build-tools/fact-tables'; +// This is the name of the mapping that will be added to the CloudFormation template, if a stack is region agnostic +const defaultMappingName = 'CloudWatchLambdaInsightsVersions'; + // To add new versions, update fact-tables.ts `CLOUDWATCH_LAMBDA_INSIGHTS_ARNS` and create a new `public static readonly VERSION_A_B_C_D` /** @@ -83,6 +86,14 @@ export class LambdaInsightsVersion { return arn; } // Otherwise, need to add a mapping to be looked up at deployment time - return ''; + const scopeStack = Stack.of(context.scope); + // Only create the mapping once + if (!scopeStack.node.tryFindChild(defaultMappingName)) { + new CfnMapping(scopeStack, defaultMappingName, { + mapping: CLOUDWATCH_LAMBDA_INSIGHTS_ARNS, + }); + } + // The ARN will be looked up at deployment time from the mapping we created + return Fn.findInMap(defaultMappingName, insightsVersion, Aws.REGION); } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index 2ee3819759bc2..16fb10b9eddb4 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -88,4 +88,41 @@ describe('lambda-insights', () => { // On synthesis it should throw an error expect(() => app.synth()).toThrow(); }); + + test('using a specific version without providing a region', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack', {}); + + // AF-SOUTH-1 exists, 1.0.54.0 exists, but 1.0.54.0 isn't supported in AF-SOUTH-1 + new lambda.Function(stack, 'MyLambda', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, + }); + + // Should be looking up a mapping + expect(stack).toHaveResource('AWS::Lambda::Function', { + Properties: + { + Code: { ZipFile: 'foo' }, + Handler: 'index.handler', + Role: { 'Fn::GetAtt': ['MyLambdaServiceRole4539ECB6', 'Arn'] }, + Runtime: 'nodejs10.x', + Layers: [{ + 'Fn::FindInMap': [ + 'CloudWatchLambdaInsightsVersions', + '1.0.54.0', + { + Ref: 'AWS::Region', + }, + ], + }], + }, + DependsOn: ['MyLambdaServiceRole4539ECB6'], + }, ResourcePart.CompleteDefinition); + + // On synthesis it should not throw an error + expect(() => app.synth()).not.toThrow(); + }); }); From 384bbc087c6f5b84b0fc90a352d3e6a1171238e9 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Wed, 21 Jul 2021 02:05:57 +0000 Subject: [PATCH 12/27] Add integ test which validates the mappings for region agnostic stacks --- .../aws-lambda/lib/lambda-insights.ts | 26 +- ...nteg.lambda-insights-mapping.expected.json | 516 ++++++++++++++++++ .../test/integ.lambda-insights-mapping.ts | 42 ++ .../aws-lambda/test/lambda-insights.test.ts | 4 +- 4 files changed, 578 insertions(+), 10 deletions(-) create mode 100644 packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json create mode 100644 packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.ts diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index f4e0cd5df2940..d458125fc134e 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,9 +1,9 @@ import { Aws, CfnMapping, Fn, Lazy, Stack, Token } from '@aws-cdk/core'; -import { RegionInfo } from '@aws-cdk/region-info'; +import { FactName, RegionInfo } from '@aws-cdk/region-info'; import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '@aws-cdk/region-info/build-tools/fact-tables'; // This is the name of the mapping that will be added to the CloudFormation template, if a stack is region agnostic -const defaultMappingName = 'CloudWatchLambdaInsightsVersions'; +const defaultMappingNamePrefix = 'CloudWatchLambdaInsightsVersions'; // To add new versions, update fact-tables.ts `CLOUDWATCH_LAMBDA_INSIGHTS_ARNS` and create a new `public static readonly VERSION_A_B_C_D` @@ -87,13 +87,23 @@ export class LambdaInsightsVersion { } // Otherwise, need to add a mapping to be looked up at deployment time const scopeStack = Stack.of(context.scope); - // Only create the mapping once - if (!scopeStack.node.tryFindChild(defaultMappingName)) { - new CfnMapping(scopeStack, defaultMappingName, { - mapping: CLOUDWATCH_LAMBDA_INSIGHTS_ARNS, - }); + + // Map name has to include the version, so the primary key becomes the region. + // Secondary keys must be alphanumberic. This strategy avoids using secondary keys + // because both the version and region are non-alphanumeric + const mapName = defaultMappingNamePrefix + insightsVersion.split('.').join(''); + // Only create the part of the mapping that's necessary + const mapping: { [k1: string]: { [k2: string]: any } } = {}; + const region2arns = RegionInfo.regionMap(FactName.cloudwatchLambdaInsightsVersion(insightsVersion)); + for (const [reg, arn] of Object.entries(region2arns)) { + mapping[reg] = { arn }; + } + + // Only create the mapping once. If another version is used elsewhere, that mapping will also be present + if (!scopeStack.node.tryFindChild(mapName)) { + new CfnMapping(scopeStack, mapName, { mapping }); } // The ARN will be looked up at deployment time from the mapping we created - return Fn.findInMap(defaultMappingName, insightsVersion, Aws.REGION); + return Fn.findInMap(mapName, Aws.REGION, 'arn'); } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json new file mode 100644 index 0000000000000..431a9186b4f94 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json @@ -0,0 +1,516 @@ +{ + "Resources": { + "MyFunc1ServiceRoleF96C5B5C": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy" + ] + ] + } + ] + } + }, + "MyFunc11BE70A62": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc1ServiceRoleF96C5B5C", + "Arn" + ] + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::FindInMap": [ + "CloudWatchLambdaInsightsVersions10540", + { + "Ref": "AWS::Region" + }, + "arn" + ] + } + ], + "Runtime": "nodejs10.x" + }, + "DependsOn": [ + "MyFunc1ServiceRoleF96C5B5C" + ] + }, + "MyFunc2ServiceRole68E50443": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy" + ] + ] + } + ] + } + }, + "MyFunc242557A97": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc2ServiceRole68E50443", + "Arn" + ] + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::FindInMap": [ + "CloudWatchLambdaInsightsVersions10860", + { + "Ref": "AWS::Region" + }, + "arn" + ] + } + ], + "Runtime": "nodejs10.x" + }, + "DependsOn": [ + "MyFunc2ServiceRole68E50443" + ] + }, + "MyFunc3ServiceRoleA69795ED": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy" + ] + ] + } + ] + } + }, + "MyFunc3666B7A2F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc3ServiceRoleA69795ED", + "Arn" + ] + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::FindInMap": [ + "CloudWatchLambdaInsightsVersions10890", + { + "Ref": "AWS::Region" + }, + "arn" + ] + } + ], + "Runtime": "nodejs10.x" + }, + "DependsOn": [ + "MyFunc3ServiceRoleA69795ED" + ] + }, + "MyFunc4ServiceRole93C4DEFF": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy" + ] + ] + } + ] + } + }, + "MyFunc4B88F85C6": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function handler(event, _context, callback) {\n console.log(JSON.stringify(event, undefined, 2));\n return callback();\n}" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunc4ServiceRole93C4DEFF", + "Arn" + ] + }, + "Handler": "index.handler", + "Layers": [ + { + "Fn::FindInMap": [ + "CloudWatchLambdaInsightsVersions10980", + { + "Ref": "AWS::Region" + }, + "arn" + ] + } + ], + "Runtime": "nodejs10.x" + }, + "DependsOn": [ + "MyFunc4ServiceRole93C4DEFF" + ] + } + }, + "Mappings": { + "CloudWatchLambdaInsightsVersions10540": { + "ap-northeast-1": { + "arn": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "ap-northeast-2": { + "arn": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:2" + }, + "ap-south-1": { + "arn": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "ap-southeast-1": { + "arn": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "ap-southeast-2": { + "arn": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:2" + }, + "ca-central-1": { + "arn": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "eu-central-1": { + "arn": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "eu-north-1": { + "arn": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "eu-west-1": { + "arn": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "eu-west-2": { + "arn": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:2" + }, + "eu-west-3": { + "arn": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:2" + }, + "sa-east-1": { + "arn": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "us-east-1": { + "arn": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "us-east-2": { + "arn": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:2" + }, + "us-west-1": { + "arn": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:2" + }, + "us-west-2": { + "arn": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:2" + } + }, + "CloudWatchLambdaInsightsVersions10860": { + "ap-northeast-1": { + "arn": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "ap-northeast-2": { + "arn": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:11" + }, + "ap-south-1": { + "arn": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "ap-southeast-1": { + "arn": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "ap-southeast-2": { + "arn": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:11" + }, + "ca-central-1": { + "arn": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "eu-central-1": { + "arn": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "eu-north-1": { + "arn": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "eu-west-1": { + "arn": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "eu-west-2": { + "arn": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:11" + }, + "eu-west-3": { + "arn": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:11" + }, + "sa-east-1": { + "arn": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "us-east-1": { + "arn": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "us-east-2": { + "arn": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:11" + }, + "us-west-1": { + "arn": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:11" + }, + "us-west-2": { + "arn": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:11" + } + }, + "CloudWatchLambdaInsightsVersions10890": { + "ap-northeast-1": { + "arn": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "ap-northeast-2": { + "arn": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:12" + }, + "ap-south-1": { + "arn": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "ap-southeast-1": { + "arn": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "ap-southeast-2": { + "arn": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:12" + }, + "ca-central-1": { + "arn": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "eu-central-1": { + "arn": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "eu-north-1": { + "arn": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "eu-west-1": { + "arn": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "eu-west-2": { + "arn": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:12" + }, + "eu-west-3": { + "arn": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:12" + }, + "sa-east-1": { + "arn": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "us-east-1": { + "arn": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "us-east-2": { + "arn": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:12" + }, + "us-west-1": { + "arn": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:12" + }, + "us-west-2": { + "arn": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:12" + } + }, + "CloudWatchLambdaInsightsVersions10980": { + "af-south-1": { + "arn": "arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8" + }, + "ap-east-1": { + "arn": "arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:8" + }, + "ap-northeast-1": { + "arn": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "ap-northeast-2": { + "arn": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:14" + }, + "ap-south-1": { + "arn": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "ap-southeast-1": { + "arn": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "ap-southeast-2": { + "arn": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:14" + }, + "ca-central-1": { + "arn": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "cn-north-1": { + "arn": "arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:8" + }, + "cn-northwest-1": { + "arn": "arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:8" + }, + "eu-central-1": { + "arn": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "eu-north-1": { + "arn": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "eu-south-1": { + "arn": "arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:8" + }, + "eu-west-1": { + "arn": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "eu-west-2": { + "arn": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:14" + }, + "eu-west-3": { + "arn": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:14" + }, + "me-south-1": { + "arn": "arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:8" + }, + "sa-east-1": { + "arn": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "us-east-1": { + "arn": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "us-east-2": { + "arn": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:14" + }, + "us-west-1": { + "arn": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:14" + }, + "us-west-2": { + "arn": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:14" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.ts b/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.ts new file mode 100644 index 0000000000000..78cf8d74106ed --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.ts @@ -0,0 +1,42 @@ +import * as cdk from '@aws-cdk/core'; +import * as lambda from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'stack'); + +new lambda.Function(stack, 'MyFunc1', { + runtime: lambda.Runtime.NODEJS_10_X, + handler: 'index.handler', + code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`), + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, +}); + +new lambda.Function(stack, 'MyFunc2', { + runtime: lambda.Runtime.NODEJS_10_X, + handler: 'index.handler', + code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`), + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_86_0, +}); + +new lambda.Function(stack, 'MyFunc3', { + runtime: lambda.Runtime.NODEJS_10_X, + handler: 'index.handler', + code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`), + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_89_0, +}); + +new lambda.Function(stack, 'MyFunc4', { + runtime: lambda.Runtime.NODEJS_10_X, + handler: 'index.handler', + code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`), + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0, +}); + +app.synth(); + +/* eslint-disable no-console */ +function handler(event: any, _context: any, callback: any) { + console.log(JSON.stringify(event, undefined, 2)); + return callback(); +} diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index 16fb10b9eddb4..408292a32dcd6 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -111,11 +111,11 @@ describe('lambda-insights', () => { Runtime: 'nodejs10.x', Layers: [{ 'Fn::FindInMap': [ - 'CloudWatchLambdaInsightsVersions', - '1.0.54.0', + 'CloudWatchLambdaInsightsVersions10540', { Ref: 'AWS::Region', }, + 'arn', ], }], }, From 4743f1dc5a16097ba8b306826772cb16c143b6ae Mon Sep 17 00:00:00 2001 From: James Fleming Date: Wed, 21 Jul 2021 02:11:22 +0000 Subject: [PATCH 13/27] Update readme --- packages/@aws-cdk/aws-lambda/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 57a59b3f76cba..86e5edb4e41f0 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -332,15 +332,14 @@ which provides low-level runtime metrics for a Lambda functions. import * as lambda from '@aws-cdk/lambda'; new Function(this, 'MyFunction', { - insightsVersion: lambda.LambdaInsightsLayerVersion.fromVersionAndRegion({ - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0, - region: 'us-west-2', + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0 }) }) // Can also provide your own arn if a new version comes out +const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; new Function(this, 'MyFunction', { - insightsVersion: lambda.LambdaInsightsLayerVersion.fromInsightVersionArn() + insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn) }) ``` From a71a539fd46064a79072ad1f8257b013bfd33502 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Wed, 21 Jul 2021 02:12:27 +0000 Subject: [PATCH 14/27] Update readme --- packages/@aws-cdk/aws-lambda/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 86e5edb4e41f0..0a68bd1a68476 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -333,7 +333,6 @@ import * as lambda from '@aws-cdk/lambda'; new Function(this, 'MyFunction', { insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0 - }) }) // Can also provide your own arn if a new version comes out From dfbd04506c21e5ee06b7f56bd10cd2e95450976c Mon Sep 17 00:00:00 2001 From: James Fleming Date: Mon, 26 Jul 2021 15:31:36 +0000 Subject: [PATCH 15/27] Fix build failure --- .../region-info/build-tools/generate-static-data.ts | 4 ++-- packages/@aws-cdk/region-info/lib/fact.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts index 750808948734a..847c1ddc77572 100644 --- a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts +++ b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts @@ -3,8 +3,8 @@ import * as fs from 'fs-extra'; import { Default } from '../lib/default'; import { AWS_REGIONS, AWS_SERVICES } from './aws-entities'; import { - APPMESH_ECR_ACCOUNTS, AWS_CDK_METADATA, AWS_OLDER_REGIONS, CLOUDWATCH_LAMBDA_INSIGHTS_ARNS, DLC_REPOSITORY_ACCOUNTS, ELBV2_ACCOUNTS, FIREHOSE_CIDR_BLOCKS, PARTITION_MAP, - ROUTE_53_BUCKET_WEBSITE_ZONE_IDS, + APPMESH_ECR_ACCOUNTS, AWS_CDK_METADATA, AWS_OLDER_REGIONS, CLOUDWATCH_LAMBDA_INSIGHTS_ARNS, DLC_REPOSITORY_ACCOUNTS, + ELBV2_ACCOUNTS, FIREHOSE_CIDR_BLOCKS, PARTITION_MAP, ROUTE_53_BUCKET_WEBSITE_ZONE_IDS, } from './fact-tables'; async function main(): Promise { diff --git a/packages/@aws-cdk/region-info/lib/fact.ts b/packages/@aws-cdk/region-info/lib/fact.ts index 7e3ad230ab6c7..c099aced9fd55 100644 --- a/packages/@aws-cdk/region-info/lib/fact.ts +++ b/packages/@aws-cdk/region-info/lib/fact.ts @@ -152,6 +152,11 @@ export class FactName { */ public static readonly APPMESH_ECR_ACCOUNT = 'appMeshRepositoryAccount'; + /** + * The CIDR block used by Kinesis Data Firehose servers. + */ + public static readonly FIREHOSE_CIDR_BLOCK = 'firehoseCidrBlock'; + /** * The ARN of CloudWatch Lambda Insights for a version (e.g. 1.0.98.0) */ @@ -159,11 +164,6 @@ export class FactName { return `cloudwatch-lambda-insights-version:${version.split('.').join('_')}`; } - /** - * The CIDR block used by Kinesis Data Firehose servers. - */ - public static readonly FIREHOSE_CIDR_BLOCK = 'firehoseCidrBlock'; - /** * The name of the regional service principal for a given service. * From 594621bed1b65263b49deba032dc4e2c9a64fd71 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Mon, 26 Jul 2021 15:44:27 +0000 Subject: [PATCH 16/27] Add verification that all regions exist in the map of version->region->arn --- .../build-tools/generate-static-data.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts index 847c1ddc77572..dd42309b78c8a 100644 --- a/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts +++ b/packages/@aws-cdk/region-info/build-tools/generate-static-data.ts @@ -13,6 +13,7 @@ async function main(): Promise { checkRegions(ELBV2_ACCOUNTS); checkRegions(FIREHOSE_CIDR_BLOCKS); checkRegions(ROUTE_53_BUCKET_WEBSITE_ZONE_IDS); + checkRegionsSubMap(CLOUDWATCH_LAMBDA_INSIGHTS_ARNS); const lines = [ "import { Fact, FactName } from './fact';", @@ -104,6 +105,21 @@ function checkRegions(map: Record) { } } +/** + * Verifies that the provided map of to region to fact does not contain an entry + * for a region that was not registered in `AWS_REGIONS`. + */ +function checkRegionsSubMap(map: Record>) { + const allRegions = new Set(AWS_REGIONS); + for (const key of Object.keys(map)) { + for (const region of Object.keys(map[key])) { + if (!allRegions.has(region)) { + throw new Error(`Un-registered region fact found: ${region}. Add to AWS_REGIONS list!`); + } + } + } +} + main().catch(e => { // eslint-disable-next-line no-console console.error(e); From 99f742f250ce95ce1b9f31314801a2bfcd2b2860 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Mon, 26 Jul 2021 16:56:59 +0000 Subject: [PATCH 17/27] Add sanity check test for mapping, and use synthesis in all tests --- .../aws-lambda/test/lambda-insights.test.ts | 71 ++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index 408292a32dcd6..9cbdb439d2bfb 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -3,9 +3,11 @@ import { ResourcePart } from '@aws-cdk/assert-internal'; import * as cdk from '@aws-cdk/core'; import * as lambda from '../lib'; +// This test code has app.synth() because the lambda-insights code has functions that are only run on synthesis describe('lambda-insights', () => { test('can provide arn to enable insights', () => { - const stack = new cdk.Stack(); + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack', {}); const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; new lambda.Function(stack, 'MyLambda', { code: new lambda.InlineCode('foo'), @@ -33,6 +35,9 @@ describe('lambda-insights', () => { }, DependsOn: ['MyLambdaServiceRole4539ECB6'], }, ResourcePart.CompleteDefinition); + + // On synthesis it should not throw an error + expect(() => app.synth()).not.toThrow(); }); test('can provide a version to enable insights', () => { @@ -93,7 +98,6 @@ describe('lambda-insights', () => { const app = new cdk.App(); const stack = new cdk.Stack(app, 'Stack', {}); - // AF-SOUTH-1 exists, 1.0.54.0 exists, but 1.0.54.0 isn't supported in AF-SOUTH-1 new lambda.Function(stack, 'MyLambda', { code: new lambda.InlineCode('foo'), handler: 'index.handler', @@ -125,4 +129,67 @@ describe('lambda-insights', () => { // On synthesis it should not throw an error expect(() => app.synth()).not.toThrow(); }); + + // Here we're error checking the code which verifies if the mapping exists already + test('can create two functions in a region agnostic stack with the same version', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack', {}); + + new lambda.Function(stack, 'MyLambda1', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, + }); + + new lambda.Function(stack, 'MyLambda2', { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, + }); + + expect(stack).toHaveResource('AWS::Lambda::Function', { + Properties: + { + Code: { ZipFile: 'foo' }, + Handler: 'index.handler', + Role: { 'Fn::GetAtt': ['MyLambda1ServiceRole69A7E1EA', 'Arn'] }, + Runtime: 'nodejs10.x', + Layers: [{ + 'Fn::FindInMap': [ + 'CloudWatchLambdaInsightsVersions10540', + { + Ref: 'AWS::Region', + }, + 'arn', + ], + }], + }, + DependsOn: ['MyLambda1ServiceRole69A7E1EA'], + }, ResourcePart.CompleteDefinition); + + expect(stack).toHaveResource('AWS::Lambda::Function', { + Properties: + { + Code: { ZipFile: 'foo' }, + Handler: 'index.handler', + Role: { 'Fn::GetAtt': ['MyLambda2ServiceRoleD09B370C', 'Arn'] }, + Runtime: 'nodejs10.x', + Layers: [{ + 'Fn::FindInMap': [ + 'CloudWatchLambdaInsightsVersions10540', + { + Ref: 'AWS::Region', + }, + 'arn', + ], + }], + }, + DependsOn: ['MyLambda2ServiceRoleD09B370C'], + }, ResourcePart.CompleteDefinition); + + // On synthesis it should not throw an error + expect(() => app.synth()).not.toThrow(); + }); }); From 3c1dd9c2176be6e851f9e6d9518febe6b1646ab7 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 29 Jul 2021 13:42:30 +0000 Subject: [PATCH 18/27] Use all caps for the default mapping prefix --- .../@aws-cdk/aws-lambda/lib/lambda-insights.ts | 4 ++-- .../integ.lambda-insights-mapping.expected.json | 16 ++++++++-------- .../aws-lambda/test/lambda-insights.test.ts | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index d458125fc134e..66437ed0686c9 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -3,7 +3,7 @@ import { FactName, RegionInfo } from '@aws-cdk/region-info'; import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '@aws-cdk/region-info/build-tools/fact-tables'; // This is the name of the mapping that will be added to the CloudFormation template, if a stack is region agnostic -const defaultMappingNamePrefix = 'CloudWatchLambdaInsightsVersions'; +const DEFAULT_MAPPING_PREFIX = 'LambdaInsightsVersions'; // To add new versions, update fact-tables.ts `CLOUDWATCH_LAMBDA_INSIGHTS_ARNS` and create a new `public static readonly VERSION_A_B_C_D` @@ -91,7 +91,7 @@ export class LambdaInsightsVersion { // Map name has to include the version, so the primary key becomes the region. // Secondary keys must be alphanumberic. This strategy avoids using secondary keys // because both the version and region are non-alphanumeric - const mapName = defaultMappingNamePrefix + insightsVersion.split('.').join(''); + const mapName = DEFAULT_MAPPING_PREFIX + insightsVersion.split('.').join(''); // Only create the part of the mapping that's necessary const mapping: { [k1: string]: { [k2: string]: any } } = {}; const region2arns = RegionInfo.regionMap(FactName.cloudwatchLambdaInsightsVersion(insightsVersion)); diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json index 431a9186b4f94..7c6fabf1b1fa2 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json @@ -59,7 +59,7 @@ "Layers": [ { "Fn::FindInMap": [ - "CloudWatchLambdaInsightsVersions10540", + "LambdaInsightsVersions10540", { "Ref": "AWS::Region" }, @@ -132,7 +132,7 @@ "Layers": [ { "Fn::FindInMap": [ - "CloudWatchLambdaInsightsVersions10860", + "LambdaInsightsVersions10860", { "Ref": "AWS::Region" }, @@ -205,7 +205,7 @@ "Layers": [ { "Fn::FindInMap": [ - "CloudWatchLambdaInsightsVersions10890", + "LambdaInsightsVersions10890", { "Ref": "AWS::Region" }, @@ -278,7 +278,7 @@ "Layers": [ { "Fn::FindInMap": [ - "CloudWatchLambdaInsightsVersions10980", + "LambdaInsightsVersions10980", { "Ref": "AWS::Region" }, @@ -294,7 +294,7 @@ } }, "Mappings": { - "CloudWatchLambdaInsightsVersions10540": { + "LambdaInsightsVersions10540": { "ap-northeast-1": { "arn": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:2" }, @@ -344,7 +344,7 @@ "arn": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:2" } }, - "CloudWatchLambdaInsightsVersions10860": { + "LambdaInsightsVersions10860": { "ap-northeast-1": { "arn": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:11" }, @@ -394,7 +394,7 @@ "arn": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:11" } }, - "CloudWatchLambdaInsightsVersions10890": { + "LambdaInsightsVersions10890": { "ap-northeast-1": { "arn": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:12" }, @@ -444,7 +444,7 @@ "arn": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:12" } }, - "CloudWatchLambdaInsightsVersions10980": { + "LambdaInsightsVersions10980": { "af-south-1": { "arn": "arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8" }, diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index 9cbdb439d2bfb..daa9233b958b6 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -115,7 +115,7 @@ describe('lambda-insights', () => { Runtime: 'nodejs10.x', Layers: [{ 'Fn::FindInMap': [ - 'CloudWatchLambdaInsightsVersions10540', + 'LambdaInsightsVersions10540', { Ref: 'AWS::Region', }, @@ -158,7 +158,7 @@ describe('lambda-insights', () => { Runtime: 'nodejs10.x', Layers: [{ 'Fn::FindInMap': [ - 'CloudWatchLambdaInsightsVersions10540', + 'LambdaInsightsVersions10540', { Ref: 'AWS::Region', }, @@ -178,7 +178,7 @@ describe('lambda-insights', () => { Runtime: 'nodejs10.x', Layers: [{ 'Fn::FindInMap': [ - 'CloudWatchLambdaInsightsVersions10540', + 'LambdaInsightsVersions10540', { Ref: 'AWS::Region', }, From 519ca293c69a37d3e8554edeab30b82882beabaf Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 29 Jul 2021 13:43:53 +0000 Subject: [PATCH 19/27] Use IResolveContext instead of any --- packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 66437ed0686c9..7354d6443dc1f 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -1,4 +1,4 @@ -import { Aws, CfnMapping, Fn, Lazy, Stack, Token } from '@aws-cdk/core'; +import { Aws, CfnMapping, Fn, IResolveContext, Lazy, Stack, Token } from '@aws-cdk/core'; import { FactName, RegionInfo } from '@aws-cdk/region-info'; import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '@aws-cdk/region-info/build-tools/fact-tables'; @@ -69,7 +69,7 @@ export class LambdaInsightsVersion { /** * Meant to run at synthesis. It will look up the region in RegionInfo */ - private getVersionArn(context: any, insightsVersion: string): string { + private getVersionArn(context: IResolveContext, insightsVersion: string): string { const region = Stack.of(context.scope).region; // Check if insights version is valid. This should only happen if one of the public static readonly versions are set incorrectly From a6ca92f88028f87ceeca74b0d5eb084d34efaa6d Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 29 Jul 2021 14:08:04 +0000 Subject: [PATCH 20/27] Only verify the layers property, and add some helper test functions --- .../aws-lambda/test/lambda-insights.test.ts | 195 +++++++----------- 1 file changed, 69 insertions(+), 126 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index daa9233b958b6..76511b2987d25 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -1,40 +1,45 @@ import '@aws-cdk/assert-internal/jest'; -import { ResourcePart } from '@aws-cdk/assert-internal'; import * as cdk from '@aws-cdk/core'; import * as lambda from '../lib'; +/** + * Boilerplate code to create a Function with a given insights version + */ +function functionWithInsightsVersion(stack: cdk.Stack, id: string, insightsVersion: lambda.LambdaInsightsVersion): lambda.IFunction { + return new lambda.Function(stack, id, { + code: new lambda.InlineCode('foo'), + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_10_X, + insightsVersion, + }); +} + +/** + * Check if the function's Role has the Lambda Insights IAM policy + */ +function verifyRoleHasCorrectPolicies(stack: cdk.Stack): any { + return expect(stack).toHaveResource('AWS::IAM::Role', { + ManagedPolicyArns: + [ + { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole']] }, + { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy']] }, + ], + }); +} + // This test code has app.synth() because the lambda-insights code has functions that are only run on synthesis describe('lambda-insights', () => { test('can provide arn to enable insights', () => { const app = new cdk.App(); const stack = new cdk.Stack(app, 'Stack', {}); const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; - new lambda.Function(stack, 'MyLambda', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn), - }); + functionWithInsightsVersion(stack, 'MyLambda', lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn)); - expect(stack).toHaveResource('AWS::IAM::Role', { - ManagedPolicyArns: - [ - { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole']] }, - { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy']] }, - ], - }); + verifyRoleHasCorrectPolicies(stack); expect(stack).toHaveResource('AWS::Lambda::Function', { - Properties: - { - Code: { ZipFile: 'foo' }, - Handler: 'index.handler', - Role: { 'Fn::GetAtt': ['MyLambdaServiceRole4539ECB6', 'Arn'] }, - Runtime: 'nodejs10.x', - Layers: [layerArn], - }, - DependsOn: ['MyLambdaServiceRole4539ECB6'], - }, ResourcePart.CompleteDefinition); + Layers: [layerArn], + }); // On synthesis it should not throw an error expect(() => app.synth()).not.toThrow(); @@ -45,32 +50,13 @@ describe('lambda-insights', () => { const stack = new cdk.Stack(app, 'Stack', { env: { account: '123456789012', region: 'us-east-1' }, }); - new lambda.Function(stack, 'MyLambda', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, - }); + functionWithInsightsVersion(stack, 'MyLambda', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); - expect(stack).toHaveResource('AWS::IAM::Role', { - ManagedPolicyArns: - [ - { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole']] }, - { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy']] }, - ], - }); + verifyRoleHasCorrectPolicies(stack); expect(stack).toHaveResource('AWS::Lambda::Function', { - Properties: - { - Code: { ZipFile: 'foo' }, - Handler: 'index.handler', - Role: { 'Fn::GetAtt': ['MyLambdaServiceRole4539ECB6', 'Arn'] }, - Runtime: 'nodejs10.x', - Layers: ['arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2'], - }, - DependsOn: ['MyLambdaServiceRole4539ECB6'], - }, ResourcePart.CompleteDefinition); + Layers: ['arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2'], + }); // On synthesis it should not throw an error expect(() => app.synth()).not.toThrow(); @@ -83,12 +69,7 @@ describe('lambda-insights', () => { }); // AF-SOUTH-1 exists, 1.0.54.0 exists, but 1.0.54.0 isn't supported in AF-SOUTH-1 - new lambda.Function(stack, 'BadVersion', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, - }); + functionWithInsightsVersion(stack, 'BadVersion', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); // On synthesis it should throw an error expect(() => app.synth()).toThrow(); @@ -98,33 +79,20 @@ describe('lambda-insights', () => { const app = new cdk.App(); const stack = new cdk.Stack(app, 'Stack', {}); - new lambda.Function(stack, 'MyLambda', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, - }); + functionWithInsightsVersion(stack, 'MyLambda', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); // Should be looking up a mapping expect(stack).toHaveResource('AWS::Lambda::Function', { - Properties: - { - Code: { ZipFile: 'foo' }, - Handler: 'index.handler', - Role: { 'Fn::GetAtt': ['MyLambdaServiceRole4539ECB6', 'Arn'] }, - Runtime: 'nodejs10.x', - Layers: [{ - 'Fn::FindInMap': [ - 'LambdaInsightsVersions10540', - { - Ref: 'AWS::Region', - }, - 'arn', - ], - }], - }, - DependsOn: ['MyLambdaServiceRole4539ECB6'], - }, ResourcePart.CompleteDefinition); + Layers: [{ + 'Fn::FindInMap': [ + 'LambdaInsightsVersions10540', + { + Ref: 'AWS::Region', + }, + 'arn', + ], + }], + }); // On synthesis it should not throw an error expect(() => app.synth()).not.toThrow(); @@ -135,59 +103,34 @@ describe('lambda-insights', () => { const app = new cdk.App(); const stack = new cdk.Stack(app, 'Stack', {}); - new lambda.Function(stack, 'MyLambda1', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, - }); - - new lambda.Function(stack, 'MyLambda2', { - code: new lambda.InlineCode('foo'), - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_10_X, - insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_54_0, - }); + functionWithInsightsVersion(stack, 'MyLambda1', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); + functionWithInsightsVersion(stack, 'MyLambda2', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); expect(stack).toHaveResource('AWS::Lambda::Function', { - Properties: - { - Code: { ZipFile: 'foo' }, - Handler: 'index.handler', - Role: { 'Fn::GetAtt': ['MyLambda1ServiceRole69A7E1EA', 'Arn'] }, - Runtime: 'nodejs10.x', - Layers: [{ - 'Fn::FindInMap': [ - 'LambdaInsightsVersions10540', - { - Ref: 'AWS::Region', - }, - 'arn', - ], - }], - }, - DependsOn: ['MyLambda1ServiceRole69A7E1EA'], - }, ResourcePart.CompleteDefinition); + Role: { 'Fn::GetAtt': ['MyLambda1ServiceRole69A7E1EA', 'Arn'] }, + Layers: [{ + 'Fn::FindInMap': [ + 'LambdaInsightsVersions10540', + { + Ref: 'AWS::Region', + }, + 'arn', + ], + }], + }); expect(stack).toHaveResource('AWS::Lambda::Function', { - Properties: - { - Code: { ZipFile: 'foo' }, - Handler: 'index.handler', - Role: { 'Fn::GetAtt': ['MyLambda2ServiceRoleD09B370C', 'Arn'] }, - Runtime: 'nodejs10.x', - Layers: [{ - 'Fn::FindInMap': [ - 'LambdaInsightsVersions10540', - { - Ref: 'AWS::Region', - }, - 'arn', - ], - }], - }, - DependsOn: ['MyLambda2ServiceRoleD09B370C'], - }, ResourcePart.CompleteDefinition); + Role: { 'Fn::GetAtt': ['MyLambda2ServiceRoleD09B370C', 'Arn'] }, + Layers: [{ + 'Fn::FindInMap': [ + 'LambdaInsightsVersions10540', + { + Ref: 'AWS::Region', + }, + 'arn', + ], + }], + }); // On synthesis it should not throw an error expect(() => app.synth()).not.toThrow(); From 81cb64b57e1ff7f9f22b7fcc1a6a990b8c1a7925 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 29 Jul 2021 14:11:13 +0000 Subject: [PATCH 21/27] Check for specific error message --- packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index 76511b2987d25..85d8c06b3f7df 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -72,7 +72,7 @@ describe('lambda-insights', () => { functionWithInsightsVersion(stack, 'BadVersion', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); // On synthesis it should throw an error - expect(() => app.synth()).toThrow(); + expect(() => app.synth()).toThrow('Insights version 1.0.54.0 is not supported in region af-south-1'); }); test('using a specific version without providing a region', () => { From 4051f2699932e1bbfd2b68f498fec592ab0f6efb Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 29 Jul 2021 14:58:10 +0000 Subject: [PATCH 22/27] Make comments on mapping clearer, and simplify the code per nija-at's recommendation --- .../aws-lambda/lib/lambda-insights.ts | 129 +++++++++++------- 1 file changed, 77 insertions(+), 52 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts index 7354d6443dc1f..7a95dc18ea15c 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts @@ -10,7 +10,7 @@ const DEFAULT_MAPPING_PREFIX = 'LambdaInsightsVersions'; /** * Version of CloudWatch Lambda Insights */ -export class LambdaInsightsVersion { +export abstract class LambdaInsightsVersion { /** * Version 1.0.54.0 @@ -39,71 +39,96 @@ export class LambdaInsightsVersion { * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html */ public static fromInsightVersionArn(arn: string): LambdaInsightsVersion { - return new LambdaInsightsVersion(undefined, arn); + class InsightsArn extends LambdaInsightsVersion { + public readonly layerVersionArn = arn; + } + return new InsightsArn(); } // Use the verison to build the object. Not meant to be called by the user -- user should use e.g. VERSION_1_0_54_0 - private static fromInsightsVersion(insightsVersion: string) { - return new LambdaInsightsVersion(insightsVersion, undefined); + private static fromInsightsVersion(insightsVersion: string): LambdaInsightsVersion { + + // Check if insights version is valid. This should only happen if one of the public static readonly versions are set incorrectly + if (!(insightsVersion in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS)) { + throw new Error(`Insights version ${insightsVersion} does not exist. Available versions are ${CLOUDWATCH_LAMBDA_INSIGHTS_ARNS.keys()}`); + } + + class InsightsVersion extends LambdaInsightsVersion { + public readonly layerVersionArn = Lazy.uncachedString({ + produce: (context) => getVersionArn(context, insightsVersion), + }); + } + return new InsightsVersion(); } /** * The arn of the Lambda Insights extension */ - public readonly layerVersionArn: string; - - private constructor(insightsVersion?: string, arn?: string) { - if (arn !== undefined) { - // Use arn if explicitly provided - this.layerVersionArn = arn; - } else if (insightsVersion !== undefined) { - // Look up the arn (runs at synthesis time) - this.layerVersionArn = Lazy.uncachedString({ - produce: (context) => this.getVersionArn(context, insightsVersion), - }); - } else { - throw new Error('Cannot use Lambda Insights without providing a version or an ARN'); + public readonly layerVersionArn: string = ''; +} + +/** + * Function to retrieve the correct Lambda Insights ARN from RegionInfo, + * or create a mapping to look it up at stack deployment time. + * + * This function is run on CDK synthesis. + */ +function getVersionArn(context: IResolveContext, insightsVersion: string): string { + + const scopeStack = Stack.of(context.scope); + const region = scopeStack.region; + + // Region is defined, look up the arn, or throw an error if the version isn't supported by a region + if (region !== undefined && !Token.isUnresolved(region)) { + const arn = RegionInfo.get(region).cloudwatchLambdaInsightsArn(insightsVersion); + if (arn === undefined) { + throw new Error(`Insights version ${insightsVersion} is not supported in region ${region}`); } + return arn; } + // Otherwise, need to add a mapping to be looked up at deployment time + /** - * Meant to run at synthesis. It will look up the region in RegionInfo + * See this for the context as to why the mappings are the way they are + * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html + * + * Mappings have to have a structure like this, and no functions can be used inside them: + * + * - + * -- { : "value1"}, + * -- { : "value2"} + * + * So we cannot have an otherwise ideal mapping like this, because '1.0.98.0' is non-alphanumeric: + * LambdaInsightsVersions + * - us-east-1 + * -- {'1.0.98.0': 'arn1'}, + * -- {'1.0.89.0': 'arn2'} + * + * To get around this limitation, this is the mapping structure: + * LambdaInsightsVersions10980 // for version 1.0.98.0 + * - us-east-1 + * -- {'arn': 'arn1'}, + * - us-east-2 + * -- {'arn': 'arn2'} + * LambdaInsightsVersions10890 // a separate mapping version 1.0.89.0 + * - us-east-1 + * -- {'arn': 'arn3'}, + * - us-east-2 + * -- {'arn': 'arn4'} */ - private getVersionArn(context: IResolveContext, insightsVersion: string): string { - const region = Stack.of(context.scope).region; - - // Check if insights version is valid. This should only happen if one of the public static readonly versions are set incorrectly - if (!(insightsVersion in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS)) { - throw new Error(`Insights version ${insightsVersion} does not exist. Available versions are ${CLOUDWATCH_LAMBDA_INSIGHTS_ARNS.keys()}`); - } - // Region is defined, look up the arn, or throw an error if the version isn't supported by a region - if (region !== undefined && !Token.isUnresolved(region)) { - const arn = RegionInfo.get(region).cloudwatchLambdaInsightsArn(insightsVersion); - if (arn === undefined) { - throw new Error(`Insights version ${insightsVersion} is not supported in region ${region}`); - } - return arn; - } - // Otherwise, need to add a mapping to be looked up at deployment time - const scopeStack = Stack.of(context.scope); - - // Map name has to include the version, so the primary key becomes the region. - // Secondary keys must be alphanumberic. This strategy avoids using secondary keys - // because both the version and region are non-alphanumeric - const mapName = DEFAULT_MAPPING_PREFIX + insightsVersion.split('.').join(''); - // Only create the part of the mapping that's necessary - const mapping: { [k1: string]: { [k2: string]: any } } = {}; - const region2arns = RegionInfo.regionMap(FactName.cloudwatchLambdaInsightsVersion(insightsVersion)); - for (const [reg, arn] of Object.entries(region2arns)) { - mapping[reg] = { arn }; - } + const mapName = DEFAULT_MAPPING_PREFIX + insightsVersion.split('.').join(''); + const mapping: { [k1: string]: { [k2: string]: any } } = {}; + const region2arns = RegionInfo.regionMap(FactName.cloudwatchLambdaInsightsVersion(insightsVersion)); + for (const [reg, arn] of Object.entries(region2arns)) { + mapping[reg] = { arn }; + } - // Only create the mapping once. If another version is used elsewhere, that mapping will also be present - if (!scopeStack.node.tryFindChild(mapName)) { - new CfnMapping(scopeStack, mapName, { mapping }); - } - // The ARN will be looked up at deployment time from the mapping we created - return Fn.findInMap(mapName, Aws.REGION, 'arn'); + // Only create a given mapping once. If another version of insights is used elsewhere, that mapping will also exist + if (!scopeStack.node.tryFindChild(mapName)) { + new CfnMapping(scopeStack, mapName, { mapping }); } + // The ARN will be looked up at deployment time from the mapping we created + return Fn.findInMap(mapName, Aws.REGION, 'arn'); } \ No newline at end of file From 6c3b4d47c9d21c734bdb5c1e38cf52151f614775 Mon Sep 17 00:00:00 2001 From: flemjame-at-amazon <57235867+flemjame-at-amazon@users.noreply.github.com> Date: Thu, 29 Jul 2021 11:48:46 -0400 Subject: [PATCH 23/27] Update packages/@aws-cdk/aws-lambda/package.json Co-authored-by: Niranjan Jayakar --- packages/@aws-cdk/aws-lambda/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index 7b9f1566f0748..7c2ece3a6bd33 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -128,8 +128,8 @@ "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", - "constructs": "^3.3.69", - "@aws-cdk/region-info": "0.0.0" + "@aws-cdk/region-info": "0.0.0", + "constructs": "^3.3.69" }, "engines": { "node": ">= 10.13.0 <13 || >=13.7.0" From b468557f2d23adf7c4f0e1ff8c2d540511681b40 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 29 Jul 2021 16:03:31 +0000 Subject: [PATCH 24/27] Remove unnecessary return, and add template match to unit test --- .../aws-lambda/test/lambda-insights.test.ts | 230 ++++++++++++++++-- 1 file changed, 204 insertions(+), 26 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts index 85d8c06b3f7df..990c0c7fb7405 100644 --- a/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts @@ -1,4 +1,5 @@ import '@aws-cdk/assert-internal/jest'; +import { MatchStyle } from '@aws-cdk/assert-internal'; import * as cdk from '@aws-cdk/core'; import * as lambda from '../lib'; @@ -17,8 +18,8 @@ function functionWithInsightsVersion(stack: cdk.Stack, id: string, insightsVersi /** * Check if the function's Role has the Lambda Insights IAM policy */ -function verifyRoleHasCorrectPolicies(stack: cdk.Stack): any { - return expect(stack).toHaveResource('AWS::IAM::Role', { +function verifyRoleHasCorrectPolicies(stack: cdk.Stack) { + expect(stack).toHaveResource('AWS::IAM::Role', { ManagedPolicyArns: [ { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole']] }, @@ -106,32 +107,209 @@ describe('lambda-insights', () => { functionWithInsightsVersion(stack, 'MyLambda1', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); functionWithInsightsVersion(stack, 'MyLambda2', lambda.LambdaInsightsVersion.VERSION_1_0_54_0); - expect(stack).toHaveResource('AWS::Lambda::Function', { - Role: { 'Fn::GetAtt': ['MyLambda1ServiceRole69A7E1EA', 'Arn'] }, - Layers: [{ - 'Fn::FindInMap': [ - 'LambdaInsightsVersions10540', - { - Ref: 'AWS::Region', + /* eslint-disable quote-props */ + expect(stack).toMatchTemplate({ + Resources: { + MyLambda1ServiceRole69A7E1EA: { + 'Type': 'AWS::IAM::Role', + 'Properties': { + 'AssumeRolePolicyDocument': { + 'Statement': [ + { + 'Action': 'sts:AssumeRole', + 'Effect': 'Allow', + 'Principal': { + 'Service': 'lambda.amazonaws.com', + }, + }, + ], + 'Version': '2012-10-17', + }, + 'ManagedPolicyArns': [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + 'Ref': 'AWS::Partition', + }, + ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + 'Ref': 'AWS::Partition', + }, + ':iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy', + ], + ], + }, + ], }, - 'arn', - ], - }], - }); - - expect(stack).toHaveResource('AWS::Lambda::Function', { - Role: { 'Fn::GetAtt': ['MyLambda2ServiceRoleD09B370C', 'Arn'] }, - Layers: [{ - 'Fn::FindInMap': [ - 'LambdaInsightsVersions10540', - { - Ref: 'AWS::Region', + }, + MyLambda1AAFB4554: { + 'Type': 'AWS::Lambda::Function', + 'Properties': { + 'Code': { + 'ZipFile': 'foo', + }, + 'Role': { + 'Fn::GetAtt': [ + 'MyLambda1ServiceRole69A7E1EA', + 'Arn', + ], + }, + 'Handler': 'index.handler', + 'Layers': [ + { + 'Fn::FindInMap': [ + 'LambdaInsightsVersions10540', + { + 'Ref': 'AWS::Region', + }, + 'arn', + ], + }, + ], + 'Runtime': 'nodejs10.x', }, - 'arn', - ], - }], - }); - + 'DependsOn': [ + 'MyLambda1ServiceRole69A7E1EA', + ], + }, + MyLambda2ServiceRoleD09B370C: { + 'Type': 'AWS::IAM::Role', + 'Properties': { + 'AssumeRolePolicyDocument': { + 'Statement': [ + { + 'Action': 'sts:AssumeRole', + 'Effect': 'Allow', + 'Principal': { + 'Service': 'lambda.amazonaws.com', + }, + }, + ], + 'Version': '2012-10-17', + }, + 'ManagedPolicyArns': [ + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + 'Ref': 'AWS::Partition', + }, + ':iam::aws:policy/service-role/AWSLambdaBasicExecutionRole', + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { + 'Ref': 'AWS::Partition', + }, + ':iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy', + ], + ], + }, + ], + }, + }, + MyLambda2254B54D5: { + 'Type': 'AWS::Lambda::Function', + 'Properties': { + 'Code': { + 'ZipFile': 'foo', + }, + 'Role': { + 'Fn::GetAtt': [ + 'MyLambda2ServiceRoleD09B370C', + 'Arn', + ], + }, + 'Handler': 'index.handler', + 'Layers': [ + { + 'Fn::FindInMap': [ + 'LambdaInsightsVersions10540', + { + 'Ref': 'AWS::Region', + }, + 'arn', + ], + }, + ], + 'Runtime': 'nodejs10.x', + }, + 'DependsOn': [ + 'MyLambda2ServiceRoleD09B370C', + ], + }, + }, + Mappings: { + LambdaInsightsVersions10540: { + 'ap-northeast-1': { + arn: 'arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'ap-northeast-2': { + 'arn': 'arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:2', + }, + 'ap-south-1': { + 'arn': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'ap-southeast-1': { + 'arn': 'arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'ap-southeast-2': { + 'arn': 'arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:2', + }, + 'ca-central-1': { + 'arn': 'arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'eu-central-1': { + 'arn': 'arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'eu-north-1': { + 'arn': 'arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'eu-west-1': { + 'arn': 'arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'eu-west-2': { + 'arn': 'arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:2', + }, + 'eu-west-3': { + 'arn': 'arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:2', + }, + 'sa-east-1': { + 'arn': 'arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'us-east-1': { + 'arn': 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'us-east-2': { + 'arn': 'arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:2', + }, + 'us-west-1': { + 'arn': 'arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:2', + }, + 'us-west-2': { + 'arn': 'arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:2', + }, + }, + }, + }, MatchStyle.EXACT); // On synthesis it should not throw an error expect(() => app.synth()).not.toThrow(); }); From 155e3158cac044c4ce3d217fe1874c62baa02238 Mon Sep 17 00:00:00 2001 From: flemjame-at-amazon <57235867+flemjame-at-amazon@users.noreply.github.com> Date: Thu, 29 Jul 2021 12:04:35 -0400 Subject: [PATCH 25/27] Update packages/@aws-cdk/aws-lambda/lib/function.ts Co-authored-by: Niranjan Jayakar --- packages/@aws-cdk/aws-lambda/lib/function.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index e1d87174a8045..2d2fadc8d808b 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -216,7 +216,7 @@ export interface FunctionOptions extends EventInvokeConfigOptions { readonly profilingGroup?: IProfilingGroup; /** - * Enable Lambda Insights + * Specify the version of CloudWatch Lambda insights to use for monitoring * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights.html * * @default - No Lambda Insights From f570793ed15e383140604c8d7c4f157c01aeb0d5 Mon Sep 17 00:00:00 2001 From: flemjame-at-amazon <57235867+flemjame-at-amazon@users.noreply.github.com> Date: Thu, 29 Jul 2021 12:04:45 -0400 Subject: [PATCH 26/27] Update packages/@aws-cdk/aws-lambda/README.md Co-authored-by: Niranjan Jayakar --- packages/@aws-cdk/aws-lambda/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 0a68bd1a68476..b523fc52420b6 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -334,8 +334,11 @@ import * as lambda from '@aws-cdk/lambda'; new Function(this, 'MyFunction', { insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_98_0 }) +``` + +If the version of insights is not yet available in the CDK, you can also provide the ARN directly as so - -// Can also provide your own arn if a new version comes out +``` const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; new Function(this, 'MyFunction', { insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn) From 4b868224e4c6db3381f4a742be1e66508624c401 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 29 Jul 2021 16:18:26 +0000 Subject: [PATCH 27/27] Fenced code blocks need language --- packages/@aws-cdk/aws-lambda/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index b523fc52420b6..03839a99a2155 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -338,7 +338,7 @@ new Function(this, 'MyFunction', { If the version of insights is not yet available in the CDK, you can also provide the ARN directly as so - -``` +```ts const layerArn = 'arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14'; new Function(this, 'MyFunction', { insightsVersion: lambda.LambdaInsightsVersion.fromInsightVersionArn(layerArn)