Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pipes-targets): add API Gateway #31954

Merged
merged 14 commits into from
Nov 26, 2024
46 changes: 46 additions & 0 deletions packages/@aws-cdk/aws-pipes-targets-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ For more details see the [service documentation](https://docs.aws.amazon.com/eve
Pipe targets are the end point of an EventBridge Pipe. The following targets are supported:

* `targets.ApiDestinationTarget`: [Send event source to an EventBridge API destination](#amazon-eventbridge-api-destination)
* `targets.ApiGatewayTarget`: [Send event source to an API Gateway REST API](#amazon-api-gateway-rest-api)
* `targets.CloudWatchLogsTarget`: [Send event source to a CloudWatch Logs log group](#amazon-cloudwatch-logs-log-group)
* `targets.EventBridgeTarget`: [Send event source to an EventBridge event bus](#amazon-eventbridge-event-bus)
* `targets.KinesisTarget`: [Send event source to a Kinesis data stream](#amazon-kinesis-data-stream)
Expand Down Expand Up @@ -67,6 +68,51 @@ const pipe = new pipes.Pipe(this, 'Pipe', {
});
```

### Amazon API Gateway Rest API

A REST API can be used as a target for a pipe.
The REST API will receive the (enriched/filtered) source payload.

```ts
declare const sourceQueue: sqs.Queue;

const fn = new lambda.Function( this, 'MyFunc', {
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_LATEST,
code: lambda.Code.fromInline( 'exports.handler = e => {}' ),
});

const restApi = new api.LambdaRestApi( this, 'MyRestAPI', { handler: fn } );
const apiTarget = new targets.ApiGatewayTarget(restApi);

const pipe = new pipes.Pipe(this, 'Pipe', {
source: new SqsSource(sourceQueue),
target: apiTarget,
});
```

The input to the target REST API can be transformed:

```ts
declare const sourceQueue: sqs.Queue;

const fn = new lambda.Function( this, 'MyFunc', {
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_LATEST,
code: lambda.Code.fromInline( 'exports.handler = e => {}' ),
});

const restApi = new api.LambdaRestApi( this, 'MyRestAPI', { handler: fn } );
const apiTarget = new targets.ApiGatewayTarget(restApi, {
inputTransformation: pipes.InputTransformation.fromObject({ body: "👀" }),
});

const pipe = new pipes.Pipe(this, 'Pipe', {
source: new SqsSource(sourceQueue),
target: apiTarget,
});
```

### Amazon CloudWatch Logs Log Group

A CloudWatch Logs log group can be used as a target for a pipe.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface ApiDestinationTargetParameters {
}

/**
* A EventBridge Pipes target that sends messages to an EventBridge API destination.
* An EventBridge Pipes target that sends messages to an EventBridge API destination.
*/
export class ApiDestinationTarget implements ITarget {
private destination: IApiDestination;
Expand Down
110 changes: 110 additions & 0 deletions packages/@aws-cdk/aws-pipes-targets-alpha/lib/api-gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { IInputTransformation, IPipe, ITarget, TargetConfig } from '@aws-cdk/aws-pipes-alpha';
import { IRestApi } from 'aws-cdk-lib/aws-apigateway';
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';

/**
* API Gateway REST API target properties.
*/
export interface ApiGatewayTargetParameters {
/**
* The input transformation to apply to the message before sending it to the target.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargetparameters.html#cfn-pipes-pipe-pipetargetparameters-inputtemplate
* @default - none
*/
readonly inputTransformation?: IInputTransformation;

/**
* The method for API Gateway resource.
*
* @default '*' - ANY
*/
readonly method?: string;

/**
* The path for the API Gateway resource.
*
* @default '/'
*/
readonly path?: string;

/**
* The deployment stage for the API Gateway resource.
*
* @default - the value of `deploymentStage.stageName` of target API Gateway resource.
*/
readonly stage?: string;

/**
* The headers to send as part of the request invoking the API Gateway REST API.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargethttpparameters.html#cfn-pipes-pipe-pipetargethttpparameters-headerparameters
* @default - none
*/
readonly headerParameters?: Record<string, string>;

/**
* The path parameter values used to populate the API Gateway REST API path wildcards ("*").
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargethttpparameters.html#cfn-pipes-pipe-pipetargethttpparameters-pathparametervalues
* @default - none
*/
readonly pathParameterValues?: string[];

/**
* The query string keys/values that need to be sent as part of request invoking the API Gateway REST API.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pipes-pipe-pipetargethttpparameters.html#cfn-pipes-pipe-pipetargethttpparameters-querystringparameters
* @default - none
*/
readonly queryStringParameters?: Record<string, string>;
}

/**
* An EventBridge Pipes target that sends messages to an EventBridge API destination.
*/
export class ApiGatewayTarget implements ITarget {
private restApi: IRestApi;
private restApiParameters?: ApiGatewayTargetParameters;
private restApiArn: string;
public readonly targetArn;

constructor(restApi: IRestApi, parameters?: ApiGatewayTargetParameters) {
this.restApi = restApi;
this.restApiParameters = parameters;

if (this.restApiParameters?.stage === undefined && this.restApi.deploymentStage === undefined) {
throw Error('The REST API must have a deployed stage.');
}

this.restApiArn = this.restApi.arnForExecuteApi(
this.restApiParameters?.method,
this.restApiParameters?.path || '/',
this.restApiParameters?.stage || this.restApi.deploymentStage.stageName,
);

this.targetArn = this.restApiArn;
}

grantPush(grantee: IRole): void {
grantee.addToPrincipalPolicy(new PolicyStatement({
resources: [this.restApiArn],
actions: ['execute-api:Invoke'],
}));
}

bind(pipe: IPipe): TargetConfig {
if (!this.restApiParameters) {
return {
targetParameters: {},
};
}

return {
targetParameters: {
inputTemplate: this.restApiParameters.inputTransformation?.bind(pipe).inputTemplate,
httpParameters: this.restApiParameters,
},
};
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-pipes-targets-alpha/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './api-destination';
export * from './api-gateway';
export * from './cloudwatch-logs';
export * from './event-bridge';
export * from './kinesis';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Fixture with packages imported, but nothing else
import * as cdk from 'aws-cdk-lib';
import * as api from 'aws-cdk-lib/aws-apigateway';
import * as events from 'aws-cdk-lib/aws-events';
import * as kinesis from 'aws-cdk-lib/aws-kinesis';
import * as logs from 'aws-cdk-lib/aws-logs';
Expand Down
Loading