Skip to content

Commit f594fae

Browse files
authored
feat(pipes-targets): add lambda function (#30271)
### Issue # (if applicable) Closes #30270. ### Reason for this change Lambda Function target is not supported yet by pipes-targets. ### Description of changes - Added LambdaFunction as a pipes target. - Default LambdaFunctionInvocationType to `LambdaFunctionInvocationType.REQUEST_RESPONSE` - Allowed grant Invoke on Lambda by Pipes ### Description of how you validated changes ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 9437b4d commit f594fae

File tree

20 files changed

+33905
-2
lines changed

20 files changed

+33905
-2
lines changed

Diff for: packages/@aws-cdk/aws-pipes-targets-alpha/README.md

+51-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ Pipe targets are the end point of a EventBridge Pipe.
3030
The following targets are supported:
3131

3232
1. `targets.SqsTarget`: [Send event source to a Queue](#amazon-sqs)
33-
2. `targets.SfnStateMachine`: [Invoke a State Machine from an event source](#aws-step-functions)
33+
2. `targets.SfnStateMachine`: [Invoke a State Machine from an event source](#aws-step-functions-state-machine)
34+
3. `targets.LambdaFunction`: [Send event source to a Lambda Function](#aws-lambda-function)
3435

3536
### Amazon SQS
3637

@@ -71,7 +72,7 @@ const pipe = new pipes.Pipe(this, 'Pipe', {
7172

7273
### AWS Step Functions State Machine
7374

74-
A State Machine can be used as a target for a pipe. The State Machine will be invoked with the (enriched/filtered) source payload.
75+
A State Machine can be used as a target for a pipe. The State Machine will be invoked with the (enriched) source payload.
7576

7677
```ts
7778
declare const sourceQueue: sqs.Queue;
@@ -122,3 +123,51 @@ const pipe = new pipes.Pipe(this, 'Pipe', {
122123
target: pipeTarget
123124
});
124125
```
126+
127+
### AWS Lambda Function
128+
129+
A Lambda Function can be used as a target for a pipe. The Lambda Function will be invoked with the (enriched) source payload.
130+
131+
```ts
132+
declare const sourceQueue: sqs.Queue;
133+
declare const targetFunction: lambda.IFunction;
134+
135+
const pipeTarget = new targets.LambdaFunction(targetFunction,{});
136+
137+
const pipe = new pipes.Pipe(this, 'Pipe', {
138+
source: new SomeSource(sourceQueue),
139+
target: pipeTarget
140+
});
141+
```
142+
143+
The target Lambda Function is invoked synchronously by default. You can also choose to invoke the Lambda Function asynchronously by setting `invocationType` property to `FIRE_AND_FORGET`.
144+
145+
```ts
146+
declare const sourceQueue: sqs.Queue;
147+
declare const targetFunction: lambda.IFunction;
148+
149+
const pipeTarget = new targets.LambdaFunction(targetFunction, {
150+
invocationType: targets.LambdaFunctionInvocationType.FIRE_AND_FORGET,
151+
});
152+
153+
const pipe = new pipes.Pipe(this, 'Pipe', {
154+
source: new SomeSource(sourceQueue),
155+
target: pipeTarget
156+
});
157+
```
158+
159+
The input to the target Lambda Function can be transformed:
160+
161+
```ts
162+
declare const sourceQueue: sqs.Queue;
163+
declare const targetFunction: lambda.IFunction;
164+
165+
const pipeTarget = new targets.LambdaFunction(targetFunction, {
166+
inputTransformation: pipes.InputTransformation.fromObject({ body: "👀" }),
167+
});
168+
169+
const pipe = new pipes.Pipe(this, 'Pipe', {
170+
source: new SomeSource(sourceQueue),
171+
target: pipeTarget
172+
});
173+
```
+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from './lambda';
12
export * from './sqs';
23
export * from './stepfunctions';
+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { IInputTransformation, IPipe, ITarget, TargetConfig } from '@aws-cdk/aws-pipes-alpha';
2+
import { IRole } from 'aws-cdk-lib/aws-iam';
3+
import * as lambda from 'aws-cdk-lib/aws-lambda';
4+
5+
/**
6+
* Parameters for the LambdaFunction target
7+
*/
8+
export interface LambdaFunctionParameters {
9+
10+
/**
11+
* The input transformation to apply to the message before sending it to the target.
12+
*
13+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargetparameters.html#cfn-pipes-pipe-pipetargetparameters-inputtemplate
14+
* @default none
15+
*/
16+
readonly inputTransformation?: IInputTransformation;
17+
18+
/**
19+
* Specify whether to invoke the Lambda Function synchronously (`REQUEST_RESPONSE`) or asynchronously (`FIRE_AND_FORGET`).
20+
*
21+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargetlambdafunctionparameters.html
22+
* @default LambdaFunctionInvocationType.REQUEST_RESPONSE
23+
*/
24+
readonly invocationType?: LambdaFunctionInvocationType;
25+
}
26+
27+
/**
28+
* InvocationType for invoking the Lambda Function.
29+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargetlambdafunctionparameters.html
30+
*/
31+
export enum LambdaFunctionInvocationType {
32+
/**
33+
* Invoke Lambda Function asynchronously (`Invoke`). `InvocationType` is set to `Event` on `Invoke`, see https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html for more details.
34+
*/
35+
FIRE_AND_FORGET = 'FIRE_AND_FORGET',
36+
37+
/**
38+
* Invoke Lambda Function synchronously (`Invoke`) and wait for the response. `InvocationType` is set to `RequestResponse` on `Invoke`, see https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html for more details.
39+
*/
40+
REQUEST_RESPONSE = 'REQUEST_RESPONSE',
41+
}
42+
43+
/**
44+
* An EventBridge Pipes target that sends messages to an AWS Lambda Function.
45+
*/
46+
export class LambdaFunction implements ITarget {
47+
public readonly targetArn: string;
48+
49+
private readonly lambdaFunction: lambda.IFunction;
50+
private readonly invocationType: LambdaFunctionInvocationType;
51+
private readonly inputTemplate?: IInputTransformation;
52+
53+
constructor(
54+
lambdaFunction: lambda.IFunction,
55+
parameters: LambdaFunctionParameters,
56+
) {
57+
this.lambdaFunction = lambdaFunction;
58+
this.targetArn = lambdaFunction.functionArn;
59+
this.invocationType =
60+
parameters.invocationType ??
61+
LambdaFunctionInvocationType.REQUEST_RESPONSE;
62+
this.inputTemplate = parameters.inputTransformation;
63+
}
64+
65+
grantPush(grantee: IRole): void {
66+
this.lambdaFunction.grantInvoke(grantee);
67+
}
68+
69+
bind(pipe: IPipe): TargetConfig {
70+
return {
71+
targetParameters: {
72+
inputTemplate: this.inputTemplate?.bind(pipe).inputTemplate,
73+
lambdaFunctionParameters: {
74+
invocationType: this.invocationType,
75+
},
76+
},
77+
};
78+
}
79+
}

Diff for: packages/@aws-cdk/aws-pipes-targets-alpha/rosetta/default.ts-fixture

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import * as cdk from 'aws-cdk-lib';
33
import * as sqs from 'aws-cdk-lib/aws-sqs';
44
import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
5+
import * as lambda from 'aws-cdk-lib/aws-lambda';
56
import { Construct } from 'constructs';
67
import * as pipes from '@aws-cdk/aws-pipes-alpha';
78
import * as targets from '@aws-cdk/aws-pipes-targets-alpha';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`lambda-function should grant lambda function invoke 1`] = `
4+
{
5+
"MyLambdaPipeRoleEF32F0E5": {
6+
"Properties": {
7+
"AssumeRolePolicyDocument": {
8+
"Statement": [
9+
{
10+
"Action": "sts:AssumeRole",
11+
"Effect": "Allow",
12+
"Principal": {
13+
"Service": "pipes.amazonaws.com",
14+
},
15+
},
16+
],
17+
"Version": "2012-10-17",
18+
},
19+
},
20+
"Type": "AWS::IAM::Role",
21+
},
22+
}
23+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// eslint-disable-next-line import/no-extraneous-dependencies
2+
import { LambdaClient, TagResourceCommand } from '@aws-sdk/client-lambda';
3+
4+
exports.handler = async (event: any, context: any) => {
5+
const client = new LambdaClient();
6+
const input = {
7+
Resource: context.invokedFunctionArn,
8+
Tags: {
9+
Identifier: event[0].body, // event is received in batches, we just take the first message to update the tag. See https://docs.aws.amazon.com/eventbridge/latest/userguide/pipes-targets-specifics.html
10+
},
11+
};
12+
const command = new TagResourceCommand(input);
13+
await client.send(command);
14+
};

Diff for: packages/@aws-cdk/aws-pipes-targets-alpha/test/integ.lambda.js.snapshot/asset.6f50ad1670be7195f01a64eddc86541c357b2087e992904bdcb9f5ae67c82ecb.handler/handler.d.ts

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/@aws-cdk/aws-pipes-targets-alpha/test/integ.lambda.js.snapshot/asset.6f50ad1670be7195f01a64eddc86541c357b2087e992904bdcb9f5ae67c82ecb.handler/handler.js

+16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/@aws-cdk/aws-pipes-targets-alpha/test/integ.lambda.js.snapshot/asset.6f50ad1670be7195f01a64eddc86541c357b2087e992904bdcb9f5ae67c82ecb.handler/handler.ts

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)