Skip to content

test(NODE-4693): test lambda function #3569

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

Merged
merged 20 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .evergreen/config.in.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,31 @@ functions:
PROJECT_DIRECTORY="${PROJECT_DIRECTORY}" \
bash ${PROJECT_DIRECTORY}/.evergreen/run-oidc-tests.sh

"run deployed aws lambda tests":
- command: ec2.assume_role
params:
role_arn: ${LAMBDA_AWS_ROLE_ARN}
duration_seconds: 3600
- command: subprocess.exec
params:
working_dir: src
binary: bash
args:
- .evergreen/run-deployed-lambda-aws-tests.sh
env:
TEST_LAMBDA_DIRECTORY: ${PROJECT_DIRECTORY}/test/lambda
DRIVERS_TOOLS: ${DRIVERS_TOOLS}
DRIVERS_ATLAS_PUBLIC_API_KEY: ${DRIVERS_ATLAS_PUBLIC_API_KEY}
DRIVERS_ATLAS_PRIVATE_API_KEY: ${DRIVERS_ATLAS_PRIVATE_API_KEY}
DRIVERS_ATLAS_LAMBDA_USER: ${DRIVERS_ATLAS_LAMBDA_USER}
DRIVERS_ATLAS_LAMBDA_PASSWORD: ${DRIVERS_ATLAS_LAMBDA_PASSWORD}
DRIVERS_ATLAS_GROUP_ID: ${DRIVERS_ATLAS_GROUP_ID}
LAMBDA_STACK_NAME: dbx-node-lambda
AWS_REGION: us-east-1
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN}

"run tests":
- command: shell.exec
type: test
Expand Down
32 changes: 32 additions & 0 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,30 @@ functions:
AWS_WEB_IDENTITY_TOKEN_FILE="/tmp/tokens/test1" \
PROJECT_DIRECTORY="${PROJECT_DIRECTORY}" \
bash ${PROJECT_DIRECTORY}/.evergreen/run-oidc-tests.sh
run deployed aws lambda tests:
- command: ec2.assume_role
params:
role_arn: ${LAMBDA_AWS_ROLE_ARN}
duration_seconds: 3600
- command: subprocess.exec
params:
working_dir: src
binary: bash
args:
- .evergreen/run-deployed-lambda-aws-tests.sh
env:
TEST_LAMBDA_DIRECTORY: ${PROJECT_DIRECTORY}/test/lambda
DRIVERS_TOOLS: ${DRIVERS_TOOLS}
DRIVERS_ATLAS_PUBLIC_API_KEY: ${DRIVERS_ATLAS_PUBLIC_API_KEY}
DRIVERS_ATLAS_PRIVATE_API_KEY: ${DRIVERS_ATLAS_PRIVATE_API_KEY}
DRIVERS_ATLAS_LAMBDA_USER: ${DRIVERS_ATLAS_LAMBDA_USER}
DRIVERS_ATLAS_LAMBDA_PASSWORD: ${DRIVERS_ATLAS_LAMBDA_PASSWORD}
DRIVERS_ATLAS_GROUP_ID: ${DRIVERS_ATLAS_GROUP_ID}
LAMBDA_STACK_NAME: dbx-node-lambda
AWS_REGION: us-east-1
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN}
run tests:
- command: shell.exec
type: test
Expand Down Expand Up @@ -2957,6 +2981,13 @@ tasks:
VERSION: rapid
TOPOLOGY: server
- func: run lambda handler example tests
- name: test-deployed-lambda
tags:
- latest
- lambda
commands:
- func: install dependencies
- func: run deployed aws lambda tests
- name: test-lambda-aws-auth-example
tags:
- latest
Expand Down Expand Up @@ -3672,3 +3703,4 @@ buildvariants:
tasks:
- test-lambda-example
- test-lambda-aws-auth-example
- test-deployed-lambda
12 changes: 11 additions & 1 deletion .evergreen/generate_evergreen_tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,16 @@ AWS_LAMBDA_HANDLER_TASKS.push({
]
});

// Add the deployed lambda function tests.
AWS_LAMBDA_HANDLER_TASKS.push({
name: 'test-deployed-lambda',
tags: ['latest', 'lambda'],
commands: [
{ func: 'install dependencies' },
{ func: 'run deployed aws lambda tests' }
]
});

// Add task for testing lambda example with aws auth.
AWS_LAMBDA_HANDLER_TASKS.push({
name: 'test-lambda-aws-auth-example',
Expand Down Expand Up @@ -689,7 +699,7 @@ BUILD_VARIANTS.push({
name: 'rhel8-test-lambda',
display_name: 'AWS Lambda handler tests',
run_on: DEFAULT_OS,
tasks: ['test-lambda-example', 'test-lambda-aws-auth-example']
tasks: ['test-lambda-example', 'test-lambda-aws-auth-example', 'test-deployed-lambda']
});

// TODO(NODE-4575): unskip zstd and snappy on node 16
Expand Down
4 changes: 4 additions & 0 deletions .evergreen/run-deployed-lambda-aws-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
set -o errexit # Exit the script with error if any of the commands fail

. ${DRIVERS_TOOLS}/.evergreen/run-deployed-lambda-aws-tests.sh
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ etc/docs/build
!docs/**/*.css
!docs/**/*.js
.nvmrc

node_index.tab
node-artifacts
.npmrc

# AWS SAM generated
test/lambda/.aws-sam
test/lambda/env.json
17 changes: 17 additions & 0 deletions test/lambda/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
AWS Lambda Testing
------------------

Running locally
===============

Prerequisites:

- AWS SAM CLI
- Docker daemon running

Steps
=====

- `sam build` from the `test/lambda`.

- `sam local invoke --parameter-overrides "MongoDbUri=mongodb://127.0.0.1:27017"`
62 changes: 62 additions & 0 deletions test/lambda/events/event.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"body": "{\"message\": \"hello world\"}",
"resource": "/{proxy+}",
"path": "/path/to/resource",
"httpMethod": "POST",
"isBase64Encoded": false,
"queryStringParameters": {
"foo": "bar"
},
"pathParameters": {
"proxy": "/path/to/resource"
},
"stageVariables": {
"baz": "qux"
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "en-US,en;q=0.8",
"Cache-Control": "max-age=0",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Host": "1234567890.execute-api.us-east-1.amazonaws.com",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Custom User Agent String",
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"requestContext": {
"accountId": "123456789012",
"resourceId": "123456",
"stage": "prod",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"requestTime": "09/Apr/2015:12:34:56 +0000",
"requestTimeEpoch": 1428582896000,
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"accessKey": null,
"sourceIp": "127.0.0.1",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "Custom User Agent String",
"user": null
},
"path": "/prod/path/to/resource",
"resourcePath": "/{proxy+}",
"httpMethod": "POST",
"apiId": "1234567890",
"protocol": "HTTP/1.1"
}
}
2 changes: 2 additions & 0 deletions test/lambda/mongodb/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.aws-sam
1 change: 1 addition & 0 deletions test/lambda/mongodb/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/*
99 changes: 99 additions & 0 deletions test/lambda/mongodb/app.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { MongoClient } from 'mongodb';

// Creates the client that is cached for all requests, subscribes to
// relevant events, and forces the connection pool to get populated.
const mongoClient = new MongoClient(process.env.MONGODB_URI, {
monitorCommands: true
});

let openConnections = 0;
let heartbeatCount = 0;
let totalHeartbeatDuration = 0;
let totalCommands = 0;
let totalCommandDuration = 0;

mongoClient.on('commandStarted', (event) => {
console.log('commandStarted', event);
});

mongoClient.on('commandSucceeded', (event) => {
totalCommands++;
totalCommandDuration += event.duration;
console.log('commandSucceeded', event);
});

mongoClient.on('commandFailed', (event) => {
totalCommands++;
totalCommandDuration += event.duration;
console.log('commandFailed', event);
});

mongoClient.on('serverHeartbeatStarted', (event) => {
console.log('serverHeartbeatStarted', event);
});

mongoClient.on('serverHeartbeatSucceeded', (event) => {
heartbeatCount++;
totalHeartbeatDuration += event.duration;
console.log('serverHeartbeatSucceeded', event);
});

mongoClient.on('serverHeartbeatFailed', (event) => {
heartbeatCount++;
totalHeartbeatDuration += event.duration;
console.log('serverHeartbeatFailed', event);
});

mongoClient.on('connectionCreated', (event) => {
openConnections++;
console.log('connectionCreated', event);
});

mongoClient.on('connectionClosed', (event) => {
openConnections--;
console.log('connectionClosed', event);
});

// Populate the connection pool.
await mongoClient.connect();

// Create the response to send back.
function createResponse() {
return {
averageCommandDuration: totalCommandDuration / totalCommands,
averageHeartbeatDuration: totalHeartbeatDuration / heartbeatCount,
openConnections: openConnections,
heartbeatCount: heartbeatCount
};
}

// Reset the numbers.
function reset() {
openConnections = 0;
heartbeatCount = 0;
totalHeartbeatDuration = 0;
totalCommands = 0;
totalCommandDuration = 0;
}

/**
* The handler function itself performs an insert/delete and returns the
* id of the document in play.
*
* @param {Object} event - API Gateway Lambda Proxy Input Format
* @returns {Object} object - API Gateway Lambda Proxy Output Format
*/
export const lambdaHandler = async (event) => {
const db = mongoClient.db('lambdaTest');
const collection = db.collection('test');
const { insertedId } = await collection.insertOne({ n: 1 });
await collection.deleteOne({ _id: insertedId });
// Create the response and then reset the numbers.
const response = JSON.stringify(createResponse());
reset();

return {
statusCode: 200,
body: response
};
};
Loading