Skip to content

Commit

Permalink
chore(docs): ensure code snippets in aws-lambda README compile (aws#1…
Browse files Browse the repository at this point in the history
…4753)

Update README in aws-lambda package to pass strict Rosetta compilation, ie., all the Typescript snippets in the README compile successfully. Also follows convention for unscoped usage of all local names (anything from the aws-lambda package) and scoped usage of all other names.

In particular:
- removes many `lambda.` qualifiers
- creates a "default" fixture with a stack already created (accessible as `this`) and lots of names from the package already supported
- creates a "function" fixture that includes an already-built function (accessible as `fn`)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
BenChaimberg authored and hollanddd committed Aug 26, 2021
1 parent 89e935b commit 24b02d5
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 82 deletions.
184 changes: 102 additions & 82 deletions packages/@aws-cdk/aws-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@
This construct library allows you to define AWS Lambda Functions.

```ts
import * as lambda from '@aws-cdk/aws-lambda';
import * as path from 'path';

const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
code: Code.fromAsset(path.join(__dirname, 'lambda-handler')),
});
```

Expand Down Expand Up @@ -65,8 +62,8 @@ The following `DockerImageFunction` construct uses a local folder with a
Dockerfile as the asset that will be used as the function handler.

```ts
new lambda.DockerImageFunction(this, 'AssetFunction', {
code: lambda.DockerImageCode.fromImageAsset(path.join(__dirname, 'docker-handler')),
new DockerImageFunction(this, 'AssetFunction', {
code: DockerImageCode.fromImageAsset(path.join(__dirname, 'docker-handler')),
});
```

Expand All @@ -76,8 +73,8 @@ You can also specify an image that already exists in ECR as the function handler
import * as ecr from '@aws-cdk/aws-ecr';
const repo = new ecr.Repository(this, 'Repository');

new lambda.DockerImageFunction(this, 'ECRFunction', {
code: lambda.DockerImageCode.fromEcr(repo),
new DockerImageFunction(this, 'ECRFunction', {
code: DockerImageCode.fromEcr(repo),
});
```

Expand All @@ -90,10 +87,11 @@ The autogenerated Role is automatically given permissions to execute the Lambda
function. To reference the autogenerated Role:

```ts
const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
code: Code.fromAsset(path.join(__dirname, 'lambda-handler')),
});

fn.role // the Role
```
Expand All @@ -103,15 +101,19 @@ be given permissions to execute the Lambda function. To provide a role and grant
it appropriate permissions:

```ts
const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
import * as iam from '@aws-cdk/aws-iam';
const myRole = new iam.Role(this, 'My Role', {
assumedBy: new iam.ServicePrincipal('sns.amazonaws.com'),
});
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
code: Code.fromAsset(path.join(__dirname, 'lambda-handler')),
role: myRole // user-provided role
});

myRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole"));
myRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaVPCAccessExecutionRole")); // only required if your function lives in a VPC
myRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole"));
myRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaVPCAccessExecutionRole")); // only required if your function lives in a VPC
```

## Resource-based Policies
Expand All @@ -123,7 +125,7 @@ functions. You can also restrict permissions given to AWS services by providing
a source account or ARN (representing the account and identifier of the resource
that accesses the function or layer).

```ts
```ts fixture=function
import * as iam from '@aws-cdk/aws-iam';
const principal = new iam.ServicePrincipal('my-service');

Expand All @@ -146,7 +148,7 @@ principal in question has conditions limiting the source account or ARN of the
operation (see above), these conditions will be automatically added to the
resource policy.

```ts
```ts fixture=function
import * as iam from '@aws-cdk/aws-iam';
const servicePrincipal = new iam.ServicePrincipal('my-service');
const sourceArn = 'arn:aws:s3:::my-bucket';
Expand Down Expand Up @@ -286,11 +288,16 @@ specify options for the current version through the `currentVersionOptions`
property.

```ts
const fn = new lambda.Function(this, 'MyFunction', {
import * as cdk from '@aws-cdk/core';

const fn = new Function(this, 'MyFunction', {
currentVersionOptions: {
removalPolicy: RemovalPolicy.RETAIN, // retain old versions
removalPolicy: cdk.RemovalPolicy.RETAIN, // retain old versions
retryAttempts: 1 // async retry attempts
}
},
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: Code.fromAsset(path.join(__dirname, 'lambda-handler')),
});

fn.currentVersion.addAlias('live');
Expand All @@ -308,9 +315,11 @@ By default, updating a layer creates a new layer version, and CloudFormation wil
Alternatively, a removal policy can be used to retain the old version:

```ts
import { LayerVersion } from '@aws-cdk/aws-lambda';
import * as cdk from '@aws-cdk/core';

new LayerVersion(this, 'MyLayer', {
removalPolicy: RemovalPolicy.RETAIN
removalPolicy: cdk.RemovalPolicy.RETAIN,
code: Code.fromAsset(path.join(__dirname, 'lambda-handler')),
});
```

Expand All @@ -319,9 +328,13 @@ new LayerVersion(this, 'MyLayer', {
You can use an AWS Lambda function as a target for an Amazon CloudWatch event
rule:

```ts
```ts fixture=function
import * as events from '@aws-cdk/aws-events';
import * as targets from '@aws-cdk/aws-events-targets';
rule.addTarget(new targets.LambdaFunction(myFunction));
const rule = new events.Rule(this, 'Schedule Rule', {
schedule: events.Schedule.cron({ minute: '0', hour: '4' }),
});
rule.addTarget(new targets.LambdaFunction(fn));
```

## Event Sources
Expand All @@ -339,17 +352,21 @@ includes classes for the various event sources supported by AWS Lambda.

For example, the following code adds an SQS queue as an event source for a function:

```ts
import { SqsEventSource } from '@aws-cdk/aws-lambda-event-sources';
fn.addEventSource(new SqsEventSource(queue));
```ts fixture=function
import * as eventsources from '@aws-cdk/aws-lambda-event-sources';
import * as sqs from '@aws-cdk/aws-sqs';
const queue = new sqs.Queue(this, 'Queue');
fn.addEventSource(new eventsources.SqsEventSource(queue));
```

The following code adds an S3 bucket notification as an event source:

```ts
import { S3EventSource } from '@aws-cdk/aws-lambda-event-sources';
fn.addEventSource(new S3EventSource(bucket, {
events: [ s3.EventType.OBJECT_CREATED, s3.EventType.OBJECT_DELETED ],
```ts fixture=function
import * as eventsources from '@aws-cdk/aws-lambda-event-sources';
import * as s3 from '@aws-cdk/aws-s3';
const bucket = new s3.Bucket(this, 'Bucket');
fn.addEventSource(new eventsources.S3EventSource(bucket, {
events: [ s3.EventType.OBJECT_CREATED, s3.EventType.OBJECT_REMOVED ],
filters: [ { prefix: 'subdir/' } ] // optional
}));
```
Expand All @@ -362,27 +379,24 @@ A dead-letter queue can be automatically created for a Lambda function by
setting the `deadLetterQueueEnabled: true` configuration.

```ts
import * as lambda from '@aws-cdk/aws-lambda';

const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
deadLetterQueueEnabled: true
});
```

It is also possible to provide a dead-letter queue instead of getting a new queue created:

```ts
import * as lambda from '@aws-cdk/aws-lambda';
import * as sqs from '@aws-cdk/aws-sqs';

const dlq = new sqs.Queue(this, 'DLQ');
const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
deadLetterQueue: dlq
});
```
Expand All @@ -393,13 +407,11 @@ to learn more about AWS Lambdas and DLQs.
## Lambda with X-Ray Tracing

```ts
import * as lambda from '@aws-cdk/aws-lambda';

const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
tracing: lambda.Tracing.ACTIVE
code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
tracing: Tracing.ACTIVE
});
```

Expand All @@ -414,10 +426,10 @@ profiling group -
```ts
import * as lambda from '@aws-cdk/aws-lambda';

const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.PYTHON_3_6,
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.PYTHON_3_6,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda-handler'),
code: Code.fromAsset('lambda-handler'),
profiling: true
});
```
Expand All @@ -432,12 +444,10 @@ to learn more about AWS Lambda's Profiling support.
## Lambda with Reserved Concurrent Executions

```ts
import * as lambda from '@aws-cdk/aws-lambda';

const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
const fn = new Function(this, 'MyFunction', {
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
code: Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
reservedConcurrentExecutions: 100
});
```
Expand All @@ -449,10 +459,11 @@ managing concurrency.

You can use Application AutoScaling to automatically configure the provisioned concurrency for your functions. AutoScaling can be set to track utilization or be based on a schedule. To configure AutoScaling on a function alias:

```ts
const alias = new lambda.Alias(stack, 'Alias', {
```ts fixture=function
import * as autoscaling from '@aws-cdk/aws-autoscaling';
const alias = new Alias(this, 'Alias', {
aliasName: 'prod',
version,
version: fn.latestVersion,
});

// Create AutoScaling target
Expand All @@ -465,7 +476,7 @@ as.scaleOnUtilization({

// Configure Scheduled Scaling
as.scaleOnSchedule('ScaleUpInTheMorning', {
schedule: appscaling.Schedule.cron({ hour: '8', minute: '0'}),
schedule: autoscaling.Schedule.cron({ hour: '8', minute: '0'}),
minCapacity: 20,
});
```
Expand Down Expand Up @@ -504,8 +515,14 @@ from lambda function, the Amazon EFS access point will be required.
The following sample allows the lambda function to mount the Amazon EFS access point to `/mnt/msg` in the runtime environment and access the filesystem with the POSIX identity defined in `posixUser`.

```ts
import * as ec2 from '@aws-cdk/aws-ec2';
import * as efs from '@aws-cdk/aws-efs';

// create a new VPC
const vpc = new ec2.Vpc(this, 'VPC');

// create a new Amazon EFS filesystem
const fileSystem = new efs.FileSystem(stack, 'Efs', { vpc });
const fileSystem = new efs.FileSystem(this, 'Efs', { vpc });

// create a new access point from the filesystem
const accessPoint = fileSystem.addAccessPoint('AccessPoint', {
Expand All @@ -524,13 +541,13 @@ const accessPoint = fileSystem.addAccessPoint('AccessPoint', {
},
});

const fn = new lambda.Function(stack, 'MyLambda', {
code,
handler,
runtime,
vpc,
const fn = new Function(this, 'MyLambda', {
// mount the access point to /mnt/msg in the lambda runtime environment
filesystem: lambda.FileSystem.fromEfsAccessPoint(accessPoint, '/mnt/msg'),
filesystem: FileSystem.fromEfsAccessPoint(accessPoint, '/mnt/msg'),
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: Code.fromAsset(path.join(__dirname, 'lambda-handler')),
vpc,
});
```

Expand Down Expand Up @@ -559,17 +576,17 @@ Docker container is responsible for putting content at `/asset-output`. The cont
Example with Python:

```ts
new lambda.Function(this, 'Function', {
code: lambda.Code.fromAsset(path.join(__dirname, 'my-python-handler'), {
new Function(this, 'Function', {
code: Code.fromAsset(path.join(__dirname, 'my-python-handler'), {
bundling: {
image: lambda.Runtime.PYTHON_3_8.bundlingImage,
image: Runtime.PYTHON_3_8.bundlingImage,
command: [
'bash', '-c',
'pip install -r requirements.txt -t /asset-output && cp -au . /asset-output'
],
},
}),
runtime: lambda.Runtime.PYTHON_3_8,
runtime: Runtime.PYTHON_3_8,
handler: 'index.handler',
});
```
Expand All @@ -582,8 +599,8 @@ Use `cdk.DockerImage.fromRegistry(image)` to use an existing image or
```ts
import * as cdk from '@aws-cdk/core';

new lambda.Function(this, 'Function', {
code: lambda.Code.fromAsset('/path/to/handler', {
new Function(this, 'Function', {
code: Code.fromAsset('/path/to/handler', {
bundling: {
image: cdk.DockerImage.fromBuild('/path/to/dir/with/DockerFile', {
buildArgs: {
Expand All @@ -593,7 +610,8 @@ new lambda.Function(this, 'Function', {
command: ['my', 'cool', 'command'],
},
}),
// ...
runtime: Runtime.PYTHON_3_8,
handler: 'index.handler',
});
```

Expand All @@ -614,16 +632,18 @@ The following code configures a function with code signing.
```typescript
import * as signer from '@aws-cdk/aws-signer';

const signerProfile = signer.SigningProfile(this, 'SigningProfile', {
platform: Platform.AWS_LAMBDA_SHA384_ECDSA
const signingProfile = new signer.SigningProfile(this, 'SigningProfile', {
platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA
});

const codeSigningConfig = new lambda.CodeSigningConfig(stack, 'CodeSigningConfig', {
signingProfiles: [signingProfile],
const codeSigningConfig = new CodeSigningConfig(this, 'CodeSigningConfig', {
signingProfiles: [signingProfile],
});

new lambda.Function(this, 'Function', {
codeSigningConfig,
// ...
new Function(this, 'Function', {
codeSigningConfig,
runtime: Runtime.NODEJS_12_X,
handler: 'index.handler',
code: Code.fromAsset(path.join(__dirname, 'lambda-handler')),
});
```
12 changes: 12 additions & 0 deletions packages/@aws-cdk/aws-lambda/rosetta/default.ts-fixture
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Fixture with packages imported, but nothing else
import * as path from 'path';
import { Construct, Stack } from '@aws-cdk/core';
import { Alias, Code, CodeSigningConfig, DockerImageCode, DockerImageFunction, FileSystem, Function, LayerVersion, Runtime, Tracing } from '@aws-cdk/aws-lambda';

class Fixture extends Stack {
constructor(scope: Construct, id: string) {
super(scope, id);

/// here
}
}
Loading

0 comments on commit 24b02d5

Please sign in to comment.