Skip to content

Commit ce8e69b

Browse files
authored
test(NODE-4693): test lambda function (#3569)
1 parent d6d76b4 commit ce8e69b

File tree

13 files changed

+2735
-2
lines changed

13 files changed

+2735
-2
lines changed

.evergreen/config.in.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,31 @@ functions:
156156
PROJECT_DIRECTORY="${PROJECT_DIRECTORY}" \
157157
bash ${PROJECT_DIRECTORY}/.evergreen/run-oidc-tests.sh
158158
159+
"run deployed aws lambda tests":
160+
- command: ec2.assume_role
161+
params:
162+
role_arn: ${LAMBDA_AWS_ROLE_ARN}
163+
duration_seconds: 3600
164+
- command: subprocess.exec
165+
params:
166+
working_dir: src
167+
binary: bash
168+
args:
169+
- .evergreen/run-deployed-lambda-aws-tests.sh
170+
env:
171+
TEST_LAMBDA_DIRECTORY: ${PROJECT_DIRECTORY}/test/lambda
172+
DRIVERS_TOOLS: ${DRIVERS_TOOLS}
173+
DRIVERS_ATLAS_PUBLIC_API_KEY: ${DRIVERS_ATLAS_PUBLIC_API_KEY}
174+
DRIVERS_ATLAS_PRIVATE_API_KEY: ${DRIVERS_ATLAS_PRIVATE_API_KEY}
175+
DRIVERS_ATLAS_LAMBDA_USER: ${DRIVERS_ATLAS_LAMBDA_USER}
176+
DRIVERS_ATLAS_LAMBDA_PASSWORD: ${DRIVERS_ATLAS_LAMBDA_PASSWORD}
177+
DRIVERS_ATLAS_GROUP_ID: ${DRIVERS_ATLAS_GROUP_ID}
178+
LAMBDA_STACK_NAME: dbx-node-lambda
179+
AWS_REGION: us-east-1
180+
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
181+
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
182+
AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN}
183+
159184
"run tests":
160185
- command: shell.exec
161186
type: test

.evergreen/config.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,30 @@ functions:
126126
AWS_WEB_IDENTITY_TOKEN_FILE="/tmp/tokens/test1" \
127127
PROJECT_DIRECTORY="${PROJECT_DIRECTORY}" \
128128
bash ${PROJECT_DIRECTORY}/.evergreen/run-oidc-tests.sh
129+
run deployed aws lambda tests:
130+
- command: ec2.assume_role
131+
params:
132+
role_arn: ${LAMBDA_AWS_ROLE_ARN}
133+
duration_seconds: 3600
134+
- command: subprocess.exec
135+
params:
136+
working_dir: src
137+
binary: bash
138+
args:
139+
- .evergreen/run-deployed-lambda-aws-tests.sh
140+
env:
141+
TEST_LAMBDA_DIRECTORY: ${PROJECT_DIRECTORY}/test/lambda
142+
DRIVERS_TOOLS: ${DRIVERS_TOOLS}
143+
DRIVERS_ATLAS_PUBLIC_API_KEY: ${DRIVERS_ATLAS_PUBLIC_API_KEY}
144+
DRIVERS_ATLAS_PRIVATE_API_KEY: ${DRIVERS_ATLAS_PRIVATE_API_KEY}
145+
DRIVERS_ATLAS_LAMBDA_USER: ${DRIVERS_ATLAS_LAMBDA_USER}
146+
DRIVERS_ATLAS_LAMBDA_PASSWORD: ${DRIVERS_ATLAS_LAMBDA_PASSWORD}
147+
DRIVERS_ATLAS_GROUP_ID: ${DRIVERS_ATLAS_GROUP_ID}
148+
LAMBDA_STACK_NAME: dbx-node-lambda
149+
AWS_REGION: us-east-1
150+
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
151+
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
152+
AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN}
129153
run tests:
130154
- command: shell.exec
131155
type: test
@@ -2957,6 +2981,13 @@ tasks:
29572981
VERSION: rapid
29582982
TOPOLOGY: server
29592983
- func: run lambda handler example tests
2984+
- name: test-deployed-lambda
2985+
tags:
2986+
- latest
2987+
- lambda
2988+
commands:
2989+
- func: install dependencies
2990+
- func: run deployed aws lambda tests
29602991
- name: test-lambda-aws-auth-example
29612992
tags:
29622993
- latest
@@ -3672,3 +3703,4 @@ buildvariants:
36723703
tasks:
36733704
- test-lambda-example
36743705
- test-lambda-aws-auth-example
3706+
- test-deployed-lambda

.evergreen/generate_evergreen_tasks.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,16 @@ AWS_LAMBDA_HANDLER_TASKS.push({
296296
]
297297
});
298298

299+
// Add the deployed lambda function tests.
300+
AWS_LAMBDA_HANDLER_TASKS.push({
301+
name: 'test-deployed-lambda',
302+
tags: ['latest', 'lambda'],
303+
commands: [
304+
{ func: 'install dependencies' },
305+
{ func: 'run deployed aws lambda tests' }
306+
]
307+
});
308+
299309
// Add task for testing lambda example with aws auth.
300310
AWS_LAMBDA_HANDLER_TASKS.push({
301311
name: 'test-lambda-aws-auth-example',
@@ -689,7 +699,7 @@ BUILD_VARIANTS.push({
689699
name: 'rhel8-test-lambda',
690700
display_name: 'AWS Lambda handler tests',
691701
run_on: DEFAULT_OS,
692-
tasks: ['test-lambda-example', 'test-lambda-aws-auth-example']
702+
tasks: ['test-lambda-example', 'test-lambda-aws-auth-example', 'test-deployed-lambda']
693703
});
694704

695705
// TODO(NODE-4575): unskip zstd and snappy on node 16
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
set -o errexit # Exit the script with error if any of the commands fail
3+
4+
. ${DRIVERS_TOOLS}/.evergreen/run-deployed-lambda-aws-tests.sh

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ etc/docs/build
8888
!docs/**/*.css
8989
!docs/**/*.js
9090
.nvmrc
91-
9291
node_index.tab
9392
node-artifacts
9493
.npmrc
94+
95+
# AWS SAM generated
96+
test/lambda/.aws-sam
97+
test/lambda/env.json

test/lambda/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
AWS Lambda Testing
2+
------------------
3+
4+
Running locally
5+
===============
6+
7+
Prerequisites:
8+
9+
- AWS SAM CLI
10+
- Docker daemon running
11+
12+
Steps
13+
=====
14+
15+
- `sam build` from the `test/lambda`.
16+
17+
- `sam local invoke --parameter-overrides "MongoDbUri=mongodb://127.0.0.1:27017"`

test/lambda/events/event.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"body": "{\"message\": \"hello world\"}",
3+
"resource": "/{proxy+}",
4+
"path": "/path/to/resource",
5+
"httpMethod": "POST",
6+
"isBase64Encoded": false,
7+
"queryStringParameters": {
8+
"foo": "bar"
9+
},
10+
"pathParameters": {
11+
"proxy": "/path/to/resource"
12+
},
13+
"stageVariables": {
14+
"baz": "qux"
15+
},
16+
"headers": {
17+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
18+
"Accept-Encoding": "gzip, deflate, sdch",
19+
"Accept-Language": "en-US,en;q=0.8",
20+
"Cache-Control": "max-age=0",
21+
"CloudFront-Forwarded-Proto": "https",
22+
"CloudFront-Is-Desktop-Viewer": "true",
23+
"CloudFront-Is-Mobile-Viewer": "false",
24+
"CloudFront-Is-SmartTV-Viewer": "false",
25+
"CloudFront-Is-Tablet-Viewer": "false",
26+
"CloudFront-Viewer-Country": "US",
27+
"Host": "1234567890.execute-api.us-east-1.amazonaws.com",
28+
"Upgrade-Insecure-Requests": "1",
29+
"User-Agent": "Custom User Agent String",
30+
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
31+
"X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
32+
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
33+
"X-Forwarded-Port": "443",
34+
"X-Forwarded-Proto": "https"
35+
},
36+
"requestContext": {
37+
"accountId": "123456789012",
38+
"resourceId": "123456",
39+
"stage": "prod",
40+
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
41+
"requestTime": "09/Apr/2015:12:34:56 +0000",
42+
"requestTimeEpoch": 1428582896000,
43+
"identity": {
44+
"cognitoIdentityPoolId": null,
45+
"accountId": null,
46+
"cognitoIdentityId": null,
47+
"caller": null,
48+
"accessKey": null,
49+
"sourceIp": "127.0.0.1",
50+
"cognitoAuthenticationType": null,
51+
"cognitoAuthenticationProvider": null,
52+
"userArn": null,
53+
"userAgent": "Custom User Agent String",
54+
"user": null
55+
},
56+
"path": "/prod/path/to/resource",
57+
"resourcePath": "/{proxy+}",
58+
"httpMethod": "POST",
59+
"apiId": "1234567890",
60+
"protocol": "HTTP/1.1"
61+
}
62+
}

test/lambda/mongodb/.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
.aws-sam

test/lambda/mongodb/.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tests/*

test/lambda/mongodb/app.mjs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { MongoClient } from 'mongodb';
2+
3+
// Creates the client that is cached for all requests, subscribes to
4+
// relevant events, and forces the connection pool to get populated.
5+
const mongoClient = new MongoClient(process.env.MONGODB_URI, {
6+
monitorCommands: true
7+
});
8+
9+
let openConnections = 0;
10+
let heartbeatCount = 0;
11+
let totalHeartbeatDuration = 0;
12+
let totalCommands = 0;
13+
let totalCommandDuration = 0;
14+
15+
mongoClient.on('commandStarted', (event) => {
16+
console.log('commandStarted', event);
17+
});
18+
19+
mongoClient.on('commandSucceeded', (event) => {
20+
totalCommands++;
21+
totalCommandDuration += event.duration;
22+
console.log('commandSucceeded', event);
23+
});
24+
25+
mongoClient.on('commandFailed', (event) => {
26+
totalCommands++;
27+
totalCommandDuration += event.duration;
28+
console.log('commandFailed', event);
29+
});
30+
31+
mongoClient.on('serverHeartbeatStarted', (event) => {
32+
console.log('serverHeartbeatStarted', event);
33+
});
34+
35+
mongoClient.on('serverHeartbeatSucceeded', (event) => {
36+
heartbeatCount++;
37+
totalHeartbeatDuration += event.duration;
38+
console.log('serverHeartbeatSucceeded', event);
39+
});
40+
41+
mongoClient.on('serverHeartbeatFailed', (event) => {
42+
heartbeatCount++;
43+
totalHeartbeatDuration += event.duration;
44+
console.log('serverHeartbeatFailed', event);
45+
});
46+
47+
mongoClient.on('connectionCreated', (event) => {
48+
openConnections++;
49+
console.log('connectionCreated', event);
50+
});
51+
52+
mongoClient.on('connectionClosed', (event) => {
53+
openConnections--;
54+
console.log('connectionClosed', event);
55+
});
56+
57+
// Populate the connection pool.
58+
await mongoClient.connect();
59+
60+
// Create the response to send back.
61+
function createResponse() {
62+
return {
63+
averageCommandDuration: totalCommandDuration / totalCommands,
64+
averageHeartbeatDuration: totalHeartbeatDuration / heartbeatCount,
65+
openConnections: openConnections,
66+
heartbeatCount: heartbeatCount
67+
};
68+
}
69+
70+
// Reset the numbers.
71+
function reset() {
72+
openConnections = 0;
73+
heartbeatCount = 0;
74+
totalHeartbeatDuration = 0;
75+
totalCommands = 0;
76+
totalCommandDuration = 0;
77+
}
78+
79+
/**
80+
* The handler function itself performs an insert/delete and returns the
81+
* id of the document in play.
82+
*
83+
* @param {Object} event - API Gateway Lambda Proxy Input Format
84+
* @returns {Object} object - API Gateway Lambda Proxy Output Format
85+
*/
86+
export const lambdaHandler = async (event) => {
87+
const db = mongoClient.db('lambdaTest');
88+
const collection = db.collection('test');
89+
const { insertedId } = await collection.insertOne({ n: 1 });
90+
await collection.deleteOne({ _id: insertedId });
91+
// Create the response and then reset the numbers.
92+
const response = JSON.stringify(createResponse());
93+
reset();
94+
95+
return {
96+
statusCode: 200,
97+
body: response
98+
};
99+
};

0 commit comments

Comments
 (0)