Skip to content

Commit

Permalink
Merge pull request #48 from SaltyAga/feat/improvements-for-caching
Browse files Browse the repository at this point in the history
Feat/improvements for caching
  • Loading branch information
flaviostutz authored Dec 2, 2024
2 parents 21553eb + 09c014e commit 1567e05
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 13 deletions.
131 changes: 129 additions & 2 deletions lib/src/apigateway/openapi-gateway-lambda.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import {
import z from 'zod';
import type { oas30, oas31 } from 'openapi3-ts';
import { Converter } from '@apiture/openapi-down-convert';
import { EndpointType } from 'aws-cdk-lib/aws-apigateway';
import {
AccessLogFormat,
EndpointType,
LogGroupLogDestination,
MethodLoggingLevel,
} from 'aws-cdk-lib/aws-apigateway';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { App, Stack } from 'aws-cdk-lib/core';
import { App, Duration, Stack } from 'aws-cdk-lib/core';
import { Template } from 'aws-cdk-lib/assertions';
import { Construct } from 'constructs';
import { CfnFunction } from 'aws-cdk-lib/aws-lambda';
Expand All @@ -27,6 +32,7 @@ import {
generateOpenapiDocWithExtensions,
generateOperationId,
getPropsWithDefaults,
addLogGroupForTracing,
} from './openapi-gateway-lambda';

extendZodWithOpenApi(z);
Expand Down Expand Up @@ -475,6 +481,127 @@ describe('openapi-gateway-lambda', () => {
Principal: 'apigateway.amazonaws.com',
});
});

it('should correctly construct deployOptionsAccessLog without provided deploy options', () => {
const stack = new Stack();
const props: OpenApiGatewayLambdaProps = {
stage: 'dev',
openapiBasic: {
openapi: '3.0.3',
info: {
title: 'test api',
version: 'v1',
},
},
openapiOperations: [],
accessLogEnable: true,
};

const { deployOptions, logGroupAccessLog } = addLogGroupForTracing(stack, props);

if (!logGroupAccessLog) {
throw new Error('logGroupAccessLog should be defined');
}
expect(deployOptions.accessLogDestination).toStrictEqual(
new LogGroupLogDestination(logGroupAccessLog),
);
expect(deployOptions.accessLogFormat).toStrictEqual(AccessLogFormat.jsonWithStandardFields());
expect(deployOptions.loggingLevel).toBe(MethodLoggingLevel.INFO);
expect(deployOptions.dataTraceEnabled).toBe(false);
expect(deployOptions.tracingEnabled).toBe(true);
expect(deployOptions.metricsEnabled).toBe(true);
expect(logGroupAccessLog).toStrictEqual(logGroupAccessLog);
});

it('should correctly construct deployOptionsAccessLog with provided deployOptions', () => {
const stack = new Stack();
const props: OpenApiGatewayLambdaProps = {
stage: 'dev',
openapiBasic: {
openapi: '3.0.3',
info: {
title: 'test api',
version: 'v1',
},
},
openapiOperations: [],
accessLogEnable: true,
deployOptions: {
loggingLevel: MethodLoggingLevel.ERROR,
dataTraceEnabled: true,
stageName: 'dev',
cachingEnabled: true,
methodOptions: {
'/messages/GET': {
cachingEnabled: true,
cacheTtl: Duration.seconds(3600),
},
},
},
};

const { deployOptions, logGroupAccessLog } = addLogGroupForTracing(stack, props);

if (!logGroupAccessLog) {
throw new Error('logGroupAccessLog should be defined');
}
expect(deployOptions.accessLogDestination).toStrictEqual(
new LogGroupLogDestination(logGroupAccessLog),
);
expect(deployOptions.accessLogFormat).toStrictEqual(AccessLogFormat.jsonWithStandardFields());
expect(deployOptions.loggingLevel).toBe(MethodLoggingLevel.ERROR);
expect(deployOptions.dataTraceEnabled).toBe(true);
expect(deployOptions.tracingEnabled).toBe(true);
expect(deployOptions.metricsEnabled).toBe(true);
expect(deployOptions.stageName).toBe('dev');
expect(deployOptions.cachingEnabled).toBe(true);
expect(deployOptions.methodOptions).toStrictEqual({
'/messages/GET': {
cachingEnabled: true,
cacheTtl: Duration.seconds(3600),
},
});
expect(logGroupAccessLog).toStrictEqual(logGroupAccessLog);
});

it('should correctly merge lambdaOp.integrationOptions into x-amazon-apigateway-integration', () => {
const awsRegion = 'eu-west-1';
const lambdaArn = 'arn:aws:lambda:eu-west-1:123123123:function:my-function:live';
const gatewayProps = {
...testGatewayProps(),
openapiOperations: [
{
...testGatewayProps().openapiOperations[0],
integrationOptions: {
cacheKeyParameters: [
'method.request.querystring.portal',
'method.request.querystring.active',
],
requestParameters: {
'integration.request.querystring.portal': 'method.request.querystring.portal',
'integration.request.querystring.active': 'method.request.querystring.active',
},
},
},
],
};
const openapidoc = generateOpenapiDocWithExtensions(gatewayProps, awsRegion);

// @ts-ignore
expect(openapidoc.paths['/users/{id}'].get['x-amazon-apigateway-integration']).toStrictEqual({
uri: `arn:aws:apigateway:${awsRegion}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations`,
httpMethod: 'POST',
type: 'AWS_PROXY',
cacheKeyParameters: [
'method.request.querystring.portal',
'method.request.querystring.active',
],
requestParameters: {
'integration.request.querystring.portal': 'method.request.querystring.portal',
'integration.request.querystring.active': 'method.request.querystring.active',
},
});
});
});

const testUserGetOperation = (scope: Construct, lambdaConfig: BaseNodeJsProps): LambdaOperation => {
Expand Down
19 changes: 9 additions & 10 deletions lib/src/apigateway/openapi-gateway-lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,10 @@ const getRestApiExecutionArn = (scope: Construct, specRestApi: SpecRestApi): str
/**
* Setup log groups for access log
*/
const addLogGroupForTracing = (
export const addLogGroupForTracing = (
scope: Construct,
props: OpenApiGatewayLambdaProps,
): { deployOptions: StageOptions; logGroupAccessLog?: LogGroup } => {
if (props.accessLogEnable && props.deployOptions) {
throw new Error("When 'accessLogEnable' is defined, 'deployOptions' cannot be defined");
}

if (props.accessLogEnable) {
const logGroupAccessLog = new LogGroup(scope, 'AccessLogGroup', {
logGroupName: `apigateway-accesslogs-${scope.node.id}`,
Expand All @@ -182,11 +178,13 @@ const addLogGroupForTracing = (

const deployOptionsAccessLog: StageOptions = {
...props.deployOptions,
accessLogDestination: new LogGroupLogDestination(logGroupAccessLog),
accessLogFormat: AccessLogFormat.jsonWithStandardFields(),
loggingLevel: MethodLoggingLevel.INFO,
dataTraceEnabled: false,
tracingEnabled: true,
accessLogDestination:
props.deployOptions?.accessLogDestination ?? new LogGroupLogDestination(logGroupAccessLog),
accessLogFormat:
props.deployOptions?.accessLogFormat ?? AccessLogFormat.jsonWithStandardFields(),
loggingLevel: props.deployOptions?.loggingLevel ?? MethodLoggingLevel.INFO,
dataTraceEnabled: props.deployOptions?.dataTraceEnabled ?? false,
tracingEnabled: props.deployOptions?.tracingEnabled ?? true,
metricsEnabled: props.deployOptions?.metricsEnabled ?? true,
};

Expand Down Expand Up @@ -307,6 +305,7 @@ export const generateOpenapiDocWithExtensions = (
// https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-integration.html
// @ts-ignore
jsonObj['x-amazon-apigateway-integration'] = {
...lambdaOp.integrationOptions,
// We need to use a api gw lambda invocation function to invocate the lambda we are integrating
// https://stackoverflow.com/a/50696321
uri: `arn:aws:apigateway:${awsRegion}:lambda:path/2015-03-31/functions/${lambdaOp.lambdaAlias.functionArn}/invocations`,
Expand Down
3 changes: 2 additions & 1 deletion lib/src/apigateway/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EndpointType, SpecRestApiProps } from 'aws-cdk-lib/aws-apigateway';
import { EndpointType, IntegrationOptions, SpecRestApiProps } from 'aws-cdk-lib/aws-apigateway';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { RouteConfig } from '@asteasolutions/zod-to-openapi';
import { IAlias } from 'aws-cdk-lib/aws-lambda';
Expand Down Expand Up @@ -46,4 +46,5 @@ export type LambdaOperation = {
routeConfig: RouteConfig;
lambdaAlias: LambdaAlias;
awsExtensions?: AwsExtensions;
integrationOptions?: IntegrationOptions;
};

0 comments on commit 1567e05

Please sign in to comment.